
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"
+ "
\n"
+ " Server CPU Utilization (%)
\n"
+ " \n"
+ "
\n"
+ " Server Disk I/O (blocks per second)
\n"
+ " \n");
for (int c = 0; c < dfDevices.size(); c++) {
out.print("
\n"
+ " ").textInXhtml(dfDevices.get(c)).print(" Space and Inodes (%)
\n"
+ " \n");
}
out.print("
\n"
+ " Server Memory and Swap space (%)
\n"
+ " \n");
for (Device netDevice : netDevices) {
String deviceId = netDevice.getDeviceId().getName();
out.print("
\n"
+ " ").textInXhtml(netDevice.getDescription()).print(" traffic
\n"
+ " \n");
}
out.print("
\n"
+ " Server Swap and Paging I/O (in+out blocks per second)
\n"
+ " \n");
for (HttpdServer httpdServer : httpdServers) {
String safeName = getHttpdServerSafeName(httpdServer);
out.print("
\n"
+ " ").textInXhtml(getHttpdServerDisplay(osv, httpdServer)).print("
\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"
+ " Tobias Oetiker\n"
+ " <[email protected]>\n"
+ " and Dave Rand <[email protected]>\n"
+ " \n"
+ " \n"
+ "
\n"
+ "\n");
} else if (osvId == OperatingSystemVersion.CENTOS_7_X86_64) {
out.print("
\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