All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aoindustries.aoserv.daemon.monitor.MrtgManager Maven / Gradle / Ivy

/*
 * aoserv-daemon - Server management daemon for the AOServ Platform.
 * Copyright (C) 2006-2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022  AO Industries, Inc.
 *     [email protected]
 *     7262 Bull Pen Cir
 *     Mobile, AL 36695
 *
 * This file is part of aoserv-daemon.
 *
 * aoserv-daemon is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * aoserv-daemon is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with aoserv-daemon.  If not, see .
 */

package com.aoindustries.aoserv.daemon.monitor;

import com.aoapps.encoding.ChainWriter;
import com.aoapps.hodgepodge.io.stream.StreamableOutput;
import com.aoapps.io.posix.PosixFile;
import com.aoapps.lang.Strings;
import com.aoapps.lang.io.FileUtils;
import com.aoapps.lang.util.BufferManager;
import com.aoindustries.aoserv.client.AoservConnector;
import com.aoindustries.aoserv.client.distribution.OperatingSystemVersion;
import com.aoindustries.aoserv.client.linux.Server;
import com.aoindustries.aoserv.client.net.Device;
import com.aoindustries.aoserv.client.net.Host;
import com.aoindustries.aoserv.client.web.HttpdServer;
import com.aoindustries.aoserv.daemon.AoservDaemon;
import com.aoindustries.aoserv.daemon.AoservDaemonConfiguration;
import com.aoindustries.aoserv.daemon.client.AoservDaemonProtocol;
import com.aoindustries.aoserv.daemon.posix.linux.PackageManager;
import com.aoindustries.aoserv.daemon.util.BuilderThread;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Handles the building of name server processes and files.
 *
 * @author  AO Industries, Inc.
 */
public final class MrtgManager extends BuilderThread {

  private static final Logger logger = Logger.getLogger(MrtgManager.class.getName());

  public static final int GRAPH_WIDTH = 600;
  public static final int GRAPH_HEIGHT = 150;

  private static final int TOTAL_GRAPH_WIDTH = GRAPH_WIDTH + 100;
  private static final int TOTAL_GRAPH_HEIGHT = GRAPH_HEIGHT + 35;

  private static final PosixFile centosCfgFile = new PosixFile("/etc/mrtg/mrtg.cfg");
  private static final PosixFile centosCfgFileNew = new PosixFile("/etc/mrtg/mrtg.cfg.new");
  private static final PosixFile centosStatsFile = new PosixFile("/var/www/mrtg/stats.html");
  private static final PosixFile centosStatsFileNew = new PosixFile("/var/www/mrtg/stats.html.new");

  private static MrtgManager mrtgManager;

  private MrtgManager() {
    // Do nothing
  }

  /**
   * Gets the safe name (used for filenames and resource name) for an Apache server instance.
   */
  private static String getHttpdServerSafeName(HttpdServer httpdServer) {
    return "hs_" + httpdServer.getPkey();
  }

  /**
   * Gets the display name for an Apache server instance.
   */
  private static String getHttpdServerDisplay(OperatingSystemVersion osv, HttpdServer hs) {
    String name = hs.getName();
    int osvId = osv.getPkey();
    if (osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64) {
      int number = (name == null) ? 1 : Integer.parseInt(name);
      return "Apache Workers #" + number;
    } else if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) {
      if (name == null) {
        return "Apache Workers";
      } else {
        return "Apache Workers (" + name + ")";
      }
    } else {
      throw new AssertionError("Unexpected OperatingSystemVersion: " + osv);
    }
  }

  private static final Object rebuildLock = new Object();

  @Override
  @SuppressWarnings({"UseSpecificCatch", "TooBroadCatch"})
  protected boolean doRebuild() {
    try {
      Server thisServer = AoservDaemon.getThisServer();
      Host thisHost = thisServer.getHost();
      OperatingSystemVersion osv = thisHost.getOperatingSystemVersion();
      int osvId = osv.getPkey();
      if (
          osvId != OperatingSystemVersion.CENTOS_5_I686_AND_X86_64
              && osvId != OperatingSystemVersion.CENTOS_7_X86_64
      ) {
        throw new AssertionError("Unsupported OperatingSystemVersion: " + osv);
      }

      int uidMin = thisServer.getUidMin().getId();
      int gidMin = thisServer.getGidMin().getId();

      Server failoverServer = thisServer.getFailoverServer();
      String aoservMrtgBin;
      PosixFile cfgFile;
      PosixFile cfgFileNew;
      PosixFile statsFile;
      PosixFile statsFileNew;
      if (
          osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64
              || osvId == OperatingSystemVersion.CENTOS_7_X86_64
      ) {
        aoservMrtgBin = "/opt/aoserv-mrtg/bin";
        cfgFile = centosCfgFile;
        cfgFileNew = centosCfgFileNew;
        statsFile = centosStatsFile;
        statsFileNew = centosStatsFileNew;
      } else {
        throw new AssertionError("Unsupported OperatingSystemVersion: " + osv);
      }

      synchronized (rebuildLock) {
        // Make sure mrtg package is installed and enabled
        PackageManager.installPackage(
            PackageManager.PackageName.MRTG,
            () -> {
              if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) {
                try {
                  AoservDaemon.exec("/usr/bin/systemctl", "enable", "mrtg");
                  AoservDaemon.exec("/usr/bin/systemctl", "restart", "mrtg");
                } catch (IOException e) {
                  throw new UncheckedIOException(e);
                }
              }
            }
        );

        // Make sure aoserv-mrtg package is installed
        PackageManager.installPackage(PackageManager.PackageName.AOSERV_MRTG);

        List dfDevices = getDfDevices();
        List dfSafeNames = getSafeNames(dfDevices);

        // Get the set of HttpdServer that will have their concurrency monitored
        List httpdServers = thisServer.getHttpdServers();

          {
            /*
             * Create the new config file in RAM first
             */
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            try (ChainWriter out = new ChainWriter(new OutputStreamWriter(bout, StandardCharsets.UTF_8))) {
              out.print("#\n"
                  + "# Automatically generated by ").print(MrtgManager.class.getName()).print("\n"
                  + "#\n");
              if (
                  osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64
                      || osvId == OperatingSystemVersion.CENTOS_7_X86_64
              ) {
                out.print("HtmlDir: /var/www/mrtg\n"
                    + "ImageDir: /var/www/mrtg\n"
                    + "LogDir: /var/lib/mrtg\n"
                    + "ThreshDir: /var/lib/mrtg\n");
                if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) {
                  // Runs as daemon in CentOS 7
                  out.print("RunAsDaemon: yes\n"
                      + "Interval: 5\n"
                      + "NoDetach: yes\n");
                }
              } else {
                throw new AssertionError("Unsupported OperatingSystemVersion: " + osv);
              }
              out.print("PageTop[^]: \n"
                  + "  
\n" + "

\n" + " \"\"
\n" + " ").textInXhtml(thisServer.getHostname()); if (failoverServer != null) { out.print(" on ").textInXhtml(failoverServer.getHostname()); } out.print("\n" + "

\n" + "
\n" + " | Servers |\n" + " Stats Overview |\n" + " Load |\n" + " CPU |\n" + " DiskIO |\n"); for (int c = 0; c < dfDevices.size(); c++) { out.print(" ").textInXhtml(dfDevices.get(c)).print(" |\n"); } out.print(" Memory |\n"); // Add the network devices List netDevices = thisHost.getNetDevices(); for (Device netDevice : netDevices) { out.print(" ").textInXhtml(netDevice.getDescription()).print(" |\n"); } out.print(" Swap |\n"); for (HttpdServer httpdServer : httpdServers) { String safeName = getHttpdServerSafeName(httpdServer); out.print(" ").textInXhtml(getHttpdServerDisplay(osv, httpdServer)).print(" |\n"); } out.print(" \n" + "
\n" + "
\n" + "\n" + "Interval: 5\n"); for (Device netDevice : netDevices) { String deviceId = netDevice.getDeviceId().getName(); out.print("\n" + "Target[").print(deviceId).print("]: `").print(aoservMrtgBin).print("/mrtg_net_device ").print(deviceId).print("`\n" + "Options[").print(deviceId).print("]: noinfo, growright, transparent"); long maxBitRate = netDevice.getMaxBitRate(); if (maxBitRate == -1) { out.print(", nopercent"); } out.print("\n" + "MaxBytes[").print(deviceId).print("]: ").print(maxBitRate == -1 ? 100000000 : netDevice.getMaxBitRate()).print("\n" + "kilo[").print(deviceId).print("]: 1024\n" + "YLegend[").print(deviceId).print("]: Bits per second\n" + "ShortLegend[").print(deviceId).print("]: b/s\n" + "Legend1[").print(deviceId).print("]: Incoming Traffic in Bits per second\n" + "Legend2[").print(deviceId).print("]: Outgoing Traffic in Bits per second\n" + "Legend3[").print(deviceId).print("]: Maximal 5 Minute Incoming Traffic\n" + "Legend4[").print(deviceId).print("]: Maximal 5 Minute Outgoing Traffic\n" + "LegendI[").print(deviceId).print("]: In:\n" + "LegendO[").print(deviceId).print("]: Out:\n" + "Timezone[").print(deviceId).print("]: ").print(thisServer.getTimeZone()).print("\n" + "Title[").print(deviceId).print("]: ").print(netDevice.getDescription()).print(" traffic\n" + "PageFoot[").print(deviceId).print("]:

\n" + "PageTop[").print(deviceId).print("]:

").print(netDevice.getDescription()).print(" traffic

\n" + "XSize[").print(deviceId).print("]: ").print(GRAPH_WIDTH).print("\n" + "YSize[").print(deviceId).print("]: ").print(GRAPH_HEIGHT).print("\n"); } out.print("\n" + "Target[load]: `").print(aoservMrtgBin).print("/mrtg_load`\n" + "Options[load]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[load]: 100000\n" + "YLegend[load]: Load Average (x 1000)\n" + "ShortLegend[load]: / 1000\n" + "Legend1[load]: Load Average\n" + "Legend2[load]: Load Average\n" + "Legend3[load]: Load Average\n" + "Legend4[load]: Load Average\n" + "LegendI[load]: Load:\n" + "LegendO[load]:\n" + "Timezone[load]: ").print(thisServer.getTimeZone()).print("\n" + "Title[load]: Load Average (x 1000)\n" + "PageFoot[load]:

\n" + "PageTop[load]:

Load Average (x 1000)

\n" + "XSize[load]: ").print(GRAPH_WIDTH).print("\n" + "YSize[load]: ").print(GRAPH_HEIGHT).print("\n"); // Figure out the number of CPUs int numCpus = getNumberOfCpus(); out.print("\n" + "Target[cpu]: `").print(aoservMrtgBin).print("/mrtg_cpu`\n" + "Options[cpu]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[cpu]: 100\n" + "YLegend[cpu]: CPU Utilization\n" + "ShortLegend[cpu]: %\n"); // Handle any even number of CPU if (numCpus >= 6 && (numCpus & 1) == 0) { out.print("Legend1[cpu]: CPU 0 - ").print((numCpus / 2) - 1).print("\n" + "Legend2[cpu]: CPU ").print(numCpus / 2).print(" - ").print(numCpus - 1).print("\n" + "Legend3[cpu]: Maximal 5 Minute\n" + "Legend4[cpu]: Maximal 5 Minute\n" + "LegendI[cpu]: cpu0-").print((numCpus / 2) - 1).print(":\n" + "LegendO[cpu]: cpu").print(numCpus / 2).print('-').print(numCpus - 1).print(":\n"); } else if (numCpus == 4) { out.print("Legend1[cpu]: CPU 0 and 1\n" + "Legend2[cpu]: CPU 2 and 3\n" + "Legend3[cpu]: Maximal 5 Minute\n" + "Legend4[cpu]: Maximal 5 Minute\n" + "LegendI[cpu]: cpu0+1:\n" + "LegendO[cpu]: cpu2+3:\n"); } else if (numCpus == 2) { out.print("Legend1[cpu]: CPU 0\n" + "Legend2[cpu]: CPU 1\n" + "Legend3[cpu]: Maximal 5 Minute\n" + "Legend4[cpu]: Maximal 5 Minute\n" + "LegendI[cpu]: cpu0:\n" + "LegendO[cpu]: cpu1:\n"); } else if (numCpus == 1) { out.print("Legend1[cpu]: System\n" + "Legend2[cpu]: Total\n" + "Legend3[cpu]: Maximal 5 Minute\n" + "Legend4[cpu]: Maximal 5 Minute\n" + "LegendI[cpu]: system:\n" + "LegendO[cpu]: total:\n"); } else { throw new IOException("Unsupported number of CPUs: " + numCpus); } out.print("Timezone[cpu]: ").print(thisServer.getTimeZone()).print("\n" + "Title[cpu]: Server CPU Utilization (%)\n" + "PageFoot[cpu]:

\n" + "PageTop[cpu]:

Server CPU Utilization (%)

\n" + "XSize[cpu]: ").print(GRAPH_WIDTH).print("\n" + "YSize[cpu]: ").print(GRAPH_HEIGHT).print("\n" + "\n" + "Target[mem]: `").print(aoservMrtgBin).print("/mrtg_mem`\n" + "Options[mem]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[mem]: 100\n" + "YLegend[mem]: % Free memory and swap space\n" + "ShortLegend[mem]: %\n" + "Legend1[mem]: % swap space used\n" + "Legend2[mem]: % memory used\n" + "Legend3[mem]: Maximal 5 Minute\n" + "Legend4[mem]: Maximal 5 Minute\n" + "LegendI[mem]: Swp:\n" + "LegendO[mem]: Mem:\n" + "Timezone[mem]: ").print(thisServer.getTimeZone()).print("\n" + "Title[mem]: Server Memory and Swap space\n" + "PageFoot[mem]:

\n" + "PageTop[mem]:

Server Memory and Swap space

\n" + "XSize[mem]: ").print(GRAPH_WIDTH).print("\n" + "YSize[mem]: ").print(GRAPH_HEIGHT).print("\n" + "\n" + "Target[diskio]: `").print(aoservMrtgBin).print("/mrtg_diskio`\n" + "Options[diskio]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[diskio]: 100000000\n" + "YLegend[diskio]: Disk I/O blocks/sec\n" + "ShortLegend[diskio]: blk/s\n" + "Legend1[diskio]: read\n" + "Legend2[diskio]: write\n" + "Legend3[diskio]: Maximal 5 Minute\n" + "Legend4[diskio]: Maximal 5 Minute\n" + "LegendI[diskio]: read:\n" + "LegendO[diskio]: write:\n" + "Timezone[diskio]: ").print(thisServer.getTimeZone()).print("\n" + "Title[diskio]: Server Disk I/O (blocks per second)\n" + "PageFoot[diskio]:

\n" + "PageTop[diskio]:

Server Disk I/O (blocks per second)

\n" + "XSize[diskio]: ").print(GRAPH_WIDTH).print("\n" + "YSize[diskio]: ").print(GRAPH_HEIGHT).print("\n"); for (int c = 0; c < dfDevices.size(); c++) { String device = dfDevices.get(c); String safeName = dfSafeNames.get(c); out.print("\n" + "Target[").print(safeName).print("]: `").print(aoservMrtgBin).print("/mrtg_df ").print(device).print("`\n" + "Options[").print(safeName).print("]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[").print(safeName).print("]: 100\n" + "YLegend[").print(safeName).print("]: % Used space and inodes\n" + "ShortLegend[").print(safeName).print("]: %\n" + "Legend1[").print(safeName).print("]: % space used\n" + "Legend2[").print(safeName).print("]: % inodes used\n" + "Legend3[").print(safeName).print("]: Maximal 5 Minute\n" + "Legend4[").print(safeName).print("]: Maximal 5 Minute\n" + "LegendI[").print(safeName).print("]: Space:\n" + "LegendO[").print(safeName).print("]: Inodes:\n" + "Timezone[").print(safeName).print("]: ").print(thisServer.getTimeZone()).print("\n" + "Title[").print(safeName).print("]: ").print(device).print(" Space and Inodes (%)\n" + "PageFoot[").print(safeName).print("]:

\n" + "PageTop[").print(safeName).print("]:

").print(device).print(" Space and Inodes (%)

\n" + "XSize[").print(safeName).print("]: ").print(GRAPH_WIDTH).print("\n" + "YSize[").print(safeName).print("]: ").print(GRAPH_HEIGHT).print("\n"); } out.print("\n" + "Target[swap]: `").print(aoservMrtgBin).print("/mrtg_swap`\n" + "Options[swap]: gauge, noinfo, growright, transparent, nopercent, integer\n" + "MaxBytes[swap]: 100000000\n" + "YLegend[swap]: In+Out blocks per second\n" + "ShortLegend[swap]: io blk/s\n" + "Legend1[swap]: swap\n" + "Legend2[swap]: page\n" + "Legend3[swap]: Maximal 5 Minute\n" + "Legend4[swap]: Maximal 5 Minute\n" + "LegendI[swap]: swap:\n" + "LegendO[swap]: page:\n" + "Timezone[swap]: ").print(thisServer.getTimeZone()).print("\n" + "Title[swap]: Server Swap and Paging I/O (in+out blocks per second)\n" + "PageFoot[swap]:

\n" + "PageTop[swap]:

Server Swap and Paging I/O (in+out blocks per second)

\n" + "XSize[swap]: ").print(GRAPH_WIDTH).print("\n" + "YSize[swap]: ").print(GRAPH_HEIGHT).print("\n"); for (HttpdServer httpdServer : httpdServers) { String safeName = getHttpdServerSafeName(httpdServer); String systemdName = httpdServer.getSystemdEscapedName(); out.print("\n" + "Target[").print(safeName).print("]: `").print(aoservMrtgBin).print("/mrtg_httpd_concurrency '") .print(systemdName == null ? "" : systemdName).print("'`\n" // TODO: Which quoting and escaping needed here? + "Options[").print(safeName).print("]: gauge, noinfo, growright, transparent, integer\n" + "MaxBytes[").print(safeName).print("]: ").print(httpdServer.getMaxConcurrency()).print("\n" + "YLegend[").print(safeName).print("]: Number of Workers\n" + "ShortLegend[").print(safeName).print("]: workers\n" + "Legend1[").print(safeName).print("]: Number of Workers\n" + "Legend2[").print(safeName).print("]: Number of Workers\n" + "Legend3[").print(safeName).print("]: Number of Workers\n" + "Legend4[").print(safeName).print("]: Number of Workers\n" + "LegendI[").print(safeName).print("]: Workers:\n" + "LegendO[").print(safeName).print("]:\n" + "Timezone[").print(safeName).print("]: ").print(thisServer.getTimeZone()).print("\n" + "Title[").print(safeName).print("]: ").print(getHttpdServerDisplay(osv, httpdServer)).print("\n" + "PageFoot[").print(safeName).print("]:

\n" + "PageTop[").print(safeName).print("]:

").textInXhtml(getHttpdServerDisplay(osv, httpdServer)).print("

\n" + "XSize[").print(safeName).print("]: ").print(GRAPH_WIDTH).print("\n" + "YSize[").print(safeName).print("]: ").print(GRAPH_HEIGHT).print("\n"); } out.flush(); } byte[] newFile = bout.toByteArray(); if (!cfgFile.getStat().exists() || !cfgFile.contentEquals(newFile)) { try (OutputStream fileOut = cfgFileNew.getSecureOutputStream(PosixFile.ROOT_UID, PosixFile.ROOT_GID, 0600, true, uidMin, gidMin)) { fileOut.write(newFile); fileOut.flush(); } cfgFileNew.renameTo(cfgFile); if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) { // Restart service for new config AoservDaemon.exec("/usr/bin/systemctl", "restart", "mrtg"); } } } /* * Rewrite stats.html */ { ByteArrayOutputStream bout = new ByteArrayOutputStream(); try (ChainWriter out = new ChainWriter(new OutputStreamWriter(bout, StandardCharsets.UTF_8))) { if (osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64) { out.print("\n" + "\n" + "\n" + " \n" + " Stats Overview\n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n"); } else if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) { out.print("\n" + "\n" + "\n" + " \n" + " Stats Overview\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n" + " \n" + "\n" + " \n" + "\n"); } else { throw new AssertionError("Unsupported OperatingSystemVersion: " + osv); } out.print("
\n" + "

\n" + " \"\"
\n" + " ").textInXhtml(thisServer.getHostname()); if (failoverServer != null) { out.print(" on ").textInXhtml(failoverServer.getHostname()); } out.print("\n" + "

\n" + "
\n" + "\n" + " \n" + " | Servers |\n" + " Stats Overview |\n" + " Load |\n" + " CPU |\n" + " DiskIO |\n"); for (int c = 0; c < dfDevices.size(); c++) { out.print(" ").textInXhtml(dfDevices.get(c)).print(" |\n"); } out.print(" Memory |\n"); // Add the network devices List netDevices = thisHost.getNetDevices(); for (Device netDevice : netDevices) { out.print(" ").textInXhtml(netDevice.getDescription()).print(" |\n"); } out.print(" Swap |\n"); for (HttpdServer httpdServer : httpdServers) { String safeName = getHttpdServerSafeName(httpdServer); out.print(" ").textInXhtml(getHttpdServerDisplay(osv, httpdServer)).print(" |\n"); } out.print(" \n" + "
\n" + "\n" + "
\n" + "

Load Average (times 1000)

\n" + "

\n" + " \"load\"\n" + "

\n" + "
\n" + "

Server CPU Utilization (%)

\n" + "

\n" + " \"cpu\"\n" + "

\n" + "
\n" + "

Server Disk I/O (blocks per second)

\n" + "

\n" + " \"diskio\"\n" + "

\n"); for (int c = 0; c < dfDevices.size(); c++) { out.print("
\n" + "

").textInXhtml(dfDevices.get(c)).print(" Space and Inodes (%)

\n" + "

\n" + " \"").textInXmlAttribute(dfDevices.get(c)).print("\"\n" + "

\n"); } out.print("
\n" + "

Server Memory and Swap space (%)

\n" + "

\n" + " \"mem\"\n" + "

\n"); for (Device netDevice : netDevices) { String deviceId = netDevice.getDeviceId().getName(); out.print("
\n" + "

").textInXhtml(netDevice.getDescription()).print(" traffic

\n" + "

\n" + " \"").textInXmlAttribute(deviceId).print("\"\n" + "

\n"); } out.print("
\n" + "

Server Swap and Paging I/O (in+out blocks per second)

\n" + "

\n" + " \"swap\"\n" + "

\n"); for (HttpdServer httpdServer : httpdServers) { String safeName = getHttpdServerSafeName(httpdServer); out.print("
\n" + "

").textInXhtml(getHttpdServerDisplay(osv, httpdServer)).print("

\n" + "

\n" + " \"").textInXmlAttribute(getHttpdServerDisplay(osv,\n" + "

\n"); } if (osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64) { out.print("\n" + "
\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "\n" + " \n" + " \n" + "\n" + "
\n" + " Tobias Oetiker\n" + " <[email protected]>\n" + " and Dave Rand <[email protected]>\n" + "
\n" + "\n"); } else if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) { out.print("
\n" + "\n" + "
\n" + " \"MRTG\"\"MRTG\"\"Multi\n" + "

2.17.4

\n" + "
\n" + " Tobias Oetiker\n" + " <[email protected]>
\n" + "and Dave Rand\n" + " <[email protected]>\n" + "
\n" + "
\n" + " \n"); } else { throw new AssertionError("Unsupported OperatingSystemVersion: " + osv); } out.print(" \n" + "\n"); out.flush(); } byte[] newFile = bout.toByteArray(); if (!statsFile.getStat().exists() || !statsFile.contentEquals(newFile)) { try (OutputStream fileOut = statsFileNew.getSecureOutputStream(PosixFile.ROOT_UID, PosixFile.ROOT_GID, 0644, true, uidMin, gidMin)) { fileOut.write(newFile); fileOut.flush(); } statsFileNew.renameTo(statsFile); } } } return true; } catch (ThreadDeath td) { throw td; } catch (Throwable t) { logger.log(Level.SEVERE, null, t); return false; } } @SuppressWarnings("UseOfSystemOutOrSystemErr") public static void start() throws IOException, SQLException { Server thisServer = AoservDaemon.getThisServer(); OperatingSystemVersion osv = thisServer.getHost().getOperatingSystemVersion(); int osvId = osv.getPkey(); synchronized (System.out) { if ( // Nothing is done for these operating systems osvId != OperatingSystemVersion.CENTOS_5_DOM0_I686 && osvId != OperatingSystemVersion.CENTOS_5_DOM0_X86_64 && osvId != OperatingSystemVersion.CENTOS_7_DOM0_X86_64 // Check config after OS check so config entry not needed && AoservDaemonConfiguration.isManagerEnabled(MrtgManager.class) && mrtgManager == null ) { System.out.print("Starting MrtgManager: "); // Must be a supported operating system if ( osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64 || osvId == OperatingSystemVersion.CENTOS_7_X86_64 ) { AoservConnector conn = AoservDaemon.getConnector(); mrtgManager = new MrtgManager(); conn.getLinux().getServer().addTableListener(mrtgManager, 0); conn.getLinux().getTimeZone().addTableListener(mrtgManager, 0); conn.getNet().getDevice().addTableListener(mrtgManager, 0); conn.getNet().getDeviceId().addTableListener(mrtgManager, 0); conn.getNet().getHost().addTableListener(mrtgManager, 0); conn.getWeb().getHttpdServer().addTableListener(mrtgManager, 0); System.out.println("Done"); } else { System.out.println("Unsupported OperatingSystemVersion: " + osv); } } } } @Override public String getProcessTimerDescription() { return "Rebuild mrtg.cfg"; } /** * Reads /proc/cpuinfo and determines the number of CPUs. */ public static int getNumberOfCpus() throws IOException { try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/cpuinfo")))) { int count = 0; String line; while ((line = in.readLine()) != null) { if (line.startsWith("processor\t: ")) { count++; } } return count; } } /** * Gets the list of devices for df commands. When in a failover state, returns empty list. */ @SuppressWarnings({"UseSpecificCatch", "TooBroadCatch"}) private static List getDfDevices() throws IOException, SQLException { Server thisServer = AoservDaemon.getThisServer(); if (thisServer.getFailoverServer() != null) { return Collections.emptyList(); } OperatingSystemVersion osv = thisServer.getHost().getOperatingSystemVersion(); int osvId = osv.getPkey(); String listPartitionsCommand; if ( osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64 || osvId == OperatingSystemVersion.CENTOS_7_X86_64 ) { listPartitionsCommand = "/opt/aoserv-daemon/bin/list_partitions"; } else { throw new AssertionError("Unsupporter OperatingSystemVersion: " + osv); } List devices = new ArrayList<>(); AoservDaemon.execRun( stdout -> { try (BufferedReader in = new BufferedReader(new InputStreamReader(stdout))) { String line; while ((line = in.readLine()) != null) { if (devices.contains(line)) { logger.log(Level.WARNING, null, new Throwable("Warning: duplicate device from list_partitions: " + line)); } else { devices.add(line); } } } }, listPartitionsCommand ); Collections.sort(devices); return devices; } @SuppressWarnings("AssignmentToForLoopParameter") private static List getSafeNames(List devices) throws IOException { if (devices.isEmpty()) { return Collections.emptyList(); } List safeNames = new ArrayList<>(devices.size()); for (String device : devices) { final String safeName; switch (device) { case "/var/lib/pgsql.aes256.img": safeName = "pgsqlaes256"; break; case "/www.aes256.img": safeName = "wwwaes256"; break; case "/ao.aes256.img": safeName = "aoaes256"; break; case "/ao.copy.aes256.img": safeName = "aocopyaes256"; break; case "/dev/mapper/ao": safeName = "aoluks"; break; default: { if (device.startsWith("/dev/mapper/")) { device = "mapper_" + device.substring(12).replace('-', '_'); } else if (device.startsWith("/dev/")) { device = device.substring(5); } // All characters should now be a-z, A-Z, 0-9 or _ if (device.isEmpty()) { throw new IOException("Empty device name: " + device); } for (int c = 0; c < device.length(); c++) { char ch = device.charAt(c); if ( (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && ch != '_' ) { throw new IOException("Invalid character in device. ch=" + ch + ", device=" + device); } } safeName = device; } } safeNames.add(safeName); } return safeNames; } public static final File centosMrtgDirectory = new File("/var/www/mrtg"); public static void getMrtgFile(String filename, StreamableOutput out) throws IOException, SQLException { OperatingSystemVersion osv = AoservDaemon.getThisServer().getHost().getOperatingSystemVersion(); int osvId = osv.getPkey(); File mrtgDirectory; if ( osvId == OperatingSystemVersion.CENTOS_5_I686_AND_X86_64 || osvId == OperatingSystemVersion.CENTOS_7_X86_64 ) { mrtgDirectory = centosMrtgDirectory; } else { throw new AssertionError("Unsupported OperatingSystemVersion: " + osv); } InputStream in = null; try { File file = new File(mrtgDirectory, filename); if (filename.endsWith(".html")) { // Find-replace the hard-coded charset created by MRTG in = new ByteArrayInputStream( Strings.replace( FileUtils.readFileAsString(file, StandardCharsets.UTF_8), "charset=iso-8859-1", "charset=utf-8" ).getBytes(StandardCharsets.UTF_8) ); } else { in = new FileInputStream(file); } byte[] buff = BufferManager.getBytes(); try { int ret; while ((ret = in.read(buff, 0, BufferManager.BUFFER_SIZE)) != -1) { out.write(AoservDaemonProtocol.NEXT); out.writeShort(ret); out.write(buff, 0, ret); } } finally { BufferManager.release(buff, false); } } finally { if (in != null) { in.close(); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy