Mercurial > hg > release > thermostat-0.6
changeset 11:a0f3609a6b9e
add a always-on system backend
line wrap: on
line diff
--- a/src/com/redhat/thermostat/agent/Main.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/agent/Main.java Fri Dec 02 12:37:01 2011 -0500 @@ -58,14 +58,6 @@ logger.setLevel(config.getLogLevel()); - BackendRegistry backendRegistry = null; - try { - backendRegistry = new BackendRegistry(config); - } catch (BackendLoadException ble) { - logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble); - System.exit(Constants.EXIT_BACKEND_LOAD_ERROR); - } - Storage storage = new MongoStorage(); try { storage.connect(config.getDatabaseURIAsString()); @@ -74,10 +66,18 @@ logger.log(Level.SEVERE, "Could not initialize storage layer.", uhe); System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE); } + config.setStorage(storage); + + BackendRegistry backendRegistry = null; + try { + backendRegistry = new BackendRegistry(config, storage); + } catch (BackendLoadException ble) { + logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble); + System.exit(Constants.EXIT_BACKEND_LOAD_ERROR); + } Agent agent = new Agent(backendRegistry, config, storage); config.setAgent(agent); - config.setStorage(storage); storage.setAgentId(agent.getId()); try { agent.start();
--- a/src/com/redhat/thermostat/agent/MongoStorage.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/agent/MongoStorage.java Fri Dec 02 12:37:01 2011 -0500 @@ -1,8 +1,12 @@ package com.redhat.thermostat.agent; import java.net.UnknownHostException; +import java.util.List; +import java.util.Map.Entry; import java.util.UUID; +import org.bson.BSONObject; + import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; @@ -11,6 +15,10 @@ import com.mongodb.MongoURI; import com.mongodb.WriteConcern; import com.redhat.thermostat.agent.config.Configuration; +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.CpuStat; +import com.redhat.thermostat.common.HostInfo; +import com.redhat.thermostat.common.MemoryStat; public class MongoStorage implements Storage { @@ -38,22 +46,22 @@ public void addAgentInformation(Configuration config) { DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); DBObject toInsert = config.toDBObject(); - toInsert.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_ID, agentId.toString()); + /* cast required to disambiguate between putAll(BSONObject) and putAll(Map) */ + toInsert.putAll((BSONObject) getAgentDBObject()); configCollection.insert(toInsert, WriteConcern.SAFE); } @Override public void removeAgentInformation() { DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); - BasicDBObject toRemove = new BasicDBObject(StorageConstants.KEY_AGENT_CONFIG_AGENT_ID, agentId.toString()); + BasicDBObject toRemove = getAgentDBObject(); configCollection.remove(toRemove, WriteConcern.NORMAL); } @Override public String getBackendConfig(String backendName, String configurationKey) { DBCollection configCollection = db.getCollection(StorageConstants.COLLECTION_AGENT_CONFIG); - BasicDBObject query = new BasicDBObject(); - query.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_ID, agentId.toString()); + BasicDBObject query = getAgentDBObject(); query.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS + "." + backendName, new BasicDBObject("$exists", true)); DBObject config = configCollection.findOne(query); Object value = config.get(configurationKey); @@ -63,4 +71,78 @@ return null; } + private BasicDBObject getAgentDBObject() { + return new BasicDBObject(StorageConstants.KEY_AGENT_ID, agentId.toString()); + } + + @Override + public void updateHostInfo(HostInfo hostInfo) { + /* + * Host Info is determined (completely) on the agent side. No one else + * should be touching it. So let's overwrite any changes to it. + */ + DBObject queryForOldObject = getAgentDBObject(); + + BasicDBObject toInsert = new BasicDBObject(); + toInsert.put(StorageConstants.KEY_AGENT_ID, agentId.toString()); + toInsert.put(StorageConstants.KEY_HOST_INFO_HOSTNAME, hostInfo.getHostname()); + + BasicDBObject osParts = new BasicDBObject(); + osParts.put(StorageConstants.KEY_HOST_INFO_OS_NAME, hostInfo.getOsName()); + osParts.put(StorageConstants.KEY_HOST_INFO_OS_KERNEL, hostInfo.getOsKernel()); + toInsert.put(StorageConstants.KEY_HOST_INFO_OS, osParts); + + BasicDBObject cpuParts = new BasicDBObject(); + cpuParts.put(StorageConstants.KEY_HOST_INFO_CPU_COUNT, hostInfo.getCpuCount()); + toInsert.put(StorageConstants.KEY_HOST_INFO_CPU, cpuParts); + + BasicDBObject memoryParts = new BasicDBObject(); + memoryParts.put(StorageConstants.KEY_HOST_INFO_MEMORY_TOTAL, hostInfo.getTotalMemory()); + toInsert.put(StorageConstants.KEY_HOST_INFO_MEMORY, memoryParts); + + BasicDBObject networkParts = new BasicDBObject(); + for (Entry<String, List<String>> entry: hostInfo.getNetworkInfo().entrySet()) { + BasicDBObject details = new BasicDBObject(); + details.put(StorageConstants.KEY_HOST_INFO_NETWORK_ADDR_IPV4, + entry.getValue().get(Constants.HOST_INFO_NETWORK_IPV4_INDEX)); + details.put(StorageConstants.KEY_HOST_INFO_NETWORK_ADDR_IPV6, + entry.getValue().get(Constants.HOST_INFO_NETWORK_IPV6_INDEX)); + networkParts.put(entry.getKey(), details); + } + toInsert.put(StorageConstants.KEY_HOST_INFO_NETWORK, networkParts); + + DBCollection hostInfoCollection = db.getCollection(StorageConstants.COLLECTION_HOST_INFO); + hostInfoCollection.update( + queryForOldObject, + toInsert, + true, + false, /* doesnt matter should only have one object */ + WriteConcern.NORMAL + ); + } + + @Override + public void addCpuStat(CpuStat stat) { + DBCollection cpuStatsCollection = db.getCollection(StorageConstants.COLLECTION_CPU_STATS); + BasicDBObject toInsert = getAgentDBObject(); + toInsert.put(StorageConstants.KEY_TIMESTAMP, stat.getTimeStamp()); + toInsert.put(StorageConstants.KEY_CPU_STATS_LOAD, stat.getLoad()); + cpuStatsCollection.insert(toInsert, WriteConcern.NORMAL); + } + + @Override + public void addMemoryStat(MemoryStat stat) { + DBCollection memoryStatsCollection = db.getCollection(StorageConstants.COLLECTION_MEMORY_STATS); + BasicDBObject toInsert = getAgentDBObject(); + toInsert.put(StorageConstants.KEY_TIMESTAMP, stat.getTimeStamp()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_TOTAL, stat.getTotal()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_FREE, stat.getFree()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_BUFFERS, stat.getBuffers()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_CACHED, stat.getCached()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_SWAP_TOTAL, stat.getSwapTotal()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_SWAP_FREE, stat.getSwapFree()); + toInsert.put(StorageConstants.KEY_MEMORY_STATS_COMMIT_LIMIT, stat.getCommitLimit()); + memoryStatsCollection.insert(toInsert, WriteConcern.NORMAL); + } + }
--- a/src/com/redhat/thermostat/agent/Storage.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/agent/Storage.java Fri Dec 02 12:37:01 2011 -0500 @@ -4,6 +4,9 @@ import java.util.UUID; import com.redhat.thermostat.agent.config.Configuration; +import com.redhat.thermostat.common.CpuStat; +import com.redhat.thermostat.common.HostInfo; +import com.redhat.thermostat.common.MemoryStat; public interface Storage { public void connect(String uri) throws UnknownHostException; @@ -14,6 +17,12 @@ public void removeAgentInformation(); + public void addCpuStat(CpuStat stat); + + public void addMemoryStat(MemoryStat stat); + + public void updateHostInfo(HostInfo hostInfo); + /** * @return {@code null} if the value is invalid or missing */
--- a/src/com/redhat/thermostat/agent/StorageConstants.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/agent/StorageConstants.java Fri Dec 02 12:37:01 2011 -0500 @@ -4,10 +4,36 @@ public static final String THERMOSTAT_DB = "thermostat"; public static final String COLLECTION_AGENT_CONFIG = "agent-config"; + public static final String COLLECTION_HOST_INFO = "host-info"; + public static final String COLLECTION_CPU_STATS = "cpu-stats"; + public static final String COLLECTION_MEMORY_STATS = "memory-stats"; - public static final String KEY_AGENT_CONFIG_AGENT_ID = "agent-id"; + public static final String KEY_AGENT_ID = "agent-id"; + public static final String KEY_TIMESTAMP = "timestamp"; + public static final String KEY_AGENT_CONFIG_BACKENDS = "backends"; - public static final String KEY_AGENT_CONFIG_AGENT_START_TIME = "start-time"; + public static final String KEY_HOST_INFO_HOSTNAME = "hostname"; + public static final String KEY_HOST_INFO_OS = "os"; + public static final String KEY_HOST_INFO_OS_NAME = "name"; + public static final String KEY_HOST_INFO_OS_KERNEL = "kernel"; + public static final String KEY_HOST_INFO_CPU = "cpu"; + public static final String KEY_HOST_INFO_CPU_COUNT = "num"; + public static final String KEY_HOST_INFO_MEMORY = "memory"; + public static final String KEY_HOST_INFO_MEMORY_TOTAL = "total"; + public static final String KEY_HOST_INFO_NETWORK = "network"; + public static final String KEY_HOST_INFO_NETWORK_ADDR_IPV4 = "ipv4addr"; + public static final String KEY_HOST_INFO_NETWORK_ADDR_IPV6 = "ipv6addr"; + + public static final String KEY_CPU_STATS_LOAD = "load"; + + public static final String KEY_MEMORY_STATS_TOTAL = "total"; + public static final String KEY_MEMORY_STATS_FREE = "free"; + public static final String KEY_MEMORY_STATS_BUFFERS = "buffers"; + public static final String KEY_MEMORY_STATS_CACHED = "cached"; + public static final String KEY_MEMORY_STATS_SWAP_TOTAL = "swap-total"; + public static final String KEY_MEMORY_STATS_SWAP_FREE = "swap-free"; + public static final String KEY_MEMORY_STATS_COMMIT_LIMIT = "commit-limit"; + }
--- a/src/com/redhat/thermostat/agent/config/Configuration.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/agent/config/Configuration.java Fri Dec 02 12:37:01 2011 -0500 @@ -120,7 +120,7 @@ public DBObject toDBObject() { BasicDBObject result = new BasicDBObject(); // TODO explicit exception if agent not yet set. - result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_ID, agent.getId().toString()); + result.put(StorageConstants.KEY_AGENT_ID, agent.getId().toString()); result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_START_TIME, startTimestamp); // TODO create nested backend config parts return result;
--- a/src/com/redhat/thermostat/backend/Backend.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/backend/Backend.java Fri Dec 02 12:37:01 2011 -0500 @@ -3,14 +3,15 @@ import java.util.Map; import java.util.Map.Entry; +import com.redhat.thermostat.agent.Storage; + /** * Represents a monitoring back-end. All the {@link Backend}s should be * registered with the {@link BackendRegistry}. */ public abstract class Backend { - public Backend() { - } + protected Storage storage; public final void setInitialConfiguration(Map<String, String> configMap) { for (Entry<String, String> e : configMap.entrySet()) { @@ -20,6 +21,8 @@ protected abstract void setConfigurationValue(String name, String value); + + /** Returns the name of the {@link Backend} */ public abstract String getName(); @@ -37,6 +40,10 @@ */ public abstract Map<String, String> getConfigurationMap(); + protected void setStorage(Storage storage) { + this.storage = storage; + } + /** * Activate the {@link Backend}. Based on the current configuration, * begin pushing data to the Storage layer. If the {@link Backend} is
--- a/src/com/redhat/thermostat/backend/BackendRegistry.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/backend/BackendRegistry.java Fri Dec 02 12:37:01 2011 -0500 @@ -7,7 +7,9 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.redhat.thermostat.agent.Storage; import com.redhat.thermostat.agent.config.Configuration; +import com.redhat.thermostat.backend.system.SystemBackend; import com.redhat.thermostat.common.utils.LoggingUtils; /** @@ -20,9 +22,21 @@ private final Map<String, Backend> registeredBackends; - public BackendRegistry(Configuration config) throws BackendLoadException { + public BackendRegistry(Configuration config, Storage storage) throws BackendLoadException { registeredBackends = new HashMap<String, Backend>(); - + + /* + * Configure the always-on backends + */ + Backend systemBackend = new SystemBackend(); + logger.log(Level.FINE, "Initializing backend: \"" + systemBackend.getClass().getCanonicalName() + "\""); + systemBackend.setInitialConfiguration(config.getStartupBackendConfigMap(systemBackend.getName())); + systemBackend.setStorage(storage); + register(systemBackend); + + /* + * Configure the dynamic/custom backends + */ for (String backendClassName : config.getStartupBackendClassNames()) { logger.log(Level.FINE, "Initializing backend: \"" + backendClassName + "\""); Backend backend = null; @@ -32,6 +46,7 @@ Constructor<? extends Backend> backendConstructor = narrowed.getConstructor(); backend = backendConstructor.newInstance(); backend.setInitialConfiguration(config.getStartupBackendConfigMap(backend.getName())); + backend.setStorage(storage); } catch (Exception e) { throw new BackendLoadException("Could not instantiate configured backend class: " + backendClassName, e); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/CpuStatBuilder.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,43 @@ +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.CpuStat; +import com.redhat.thermostat.common.utils.LoggingUtils; + +/** + * Implementation note: uses information from /proc/ + */ +public class CpuStatBuilder { + + private static final String LOAD_FILE = "/proc/loadavg"; + + private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class); + + public CpuStat build() { + long timestamp = System.currentTimeMillis(); + double load5 = CpuStat.INVALID_LOAD; + double load10 = CpuStat.INVALID_LOAD; + double load15 = CpuStat.INVALID_LOAD; + + try { + BufferedReader reader = new BufferedReader(new FileReader(LOAD_FILE)); + String[] loadAvgParts = reader.readLine().split(" +"); + if (loadAvgParts.length >= 3) { + load5 = Double.valueOf(loadAvgParts[0]); + load10 = Double.valueOf(loadAvgParts[1]); + load15 = Double.valueOf(loadAvgParts[2]); + } + } catch (NumberFormatException nfe) { + logger.log(Level.WARNING, "error extracting load from " + LOAD_FILE); + } catch (IOException e) { + logger.log(Level.WARNING, "unable to read " + LOAD_FILE); + } + + return new CpuStat(timestamp, load5, load10, load15); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/DistributionIdentity.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,70 @@ +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; + +/** + * Implementation note: this relies on the {@code lsb_release} program to work. + */ +public class DistributionIdentity { + + private static final String DISTRIBUTION_NAME = "distributor id"; + private static final String DISTRIBUTION_VERSION = "release"; + + private static final Logger logger = LoggingUtils.getLogger(DistributionIdentity.class); + + private final String name; + private final String version; + + public DistributionIdentity() { + String tempName = "Unknown Distribution"; + String tempVersion = "Unknown"; + try { + Process lsbProc = Runtime.getRuntime().exec(new String[] { "lsb_release", "-a" }); + InputStream progOutput = lsbProc.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(progOutput)); + String line; + while ((line = reader.readLine()) != null) { + int sepLocation = line.indexOf(":"); + if (sepLocation != -1) { + String key = line.substring(0, sepLocation).toLowerCase(); + if (key.equals(DISTRIBUTION_NAME)) { + tempName = line.substring(sepLocation + 1).trim(); + } else if (key.equals(DISTRIBUTION_VERSION)) { + tempVersion = line.substring(sepLocation + 1).trim(); + } + } + } + } catch (IOException e) { + logger.log(Level.WARNING, "unable to identify distribution"); + } + name = tempName; + version = tempVersion; + + logger.log(Level.FINE, "distro-name: " + name); + logger.log(Level.FINE, "distro-version: " + version); + } + + /** + * @return the name of the distrbution, or {@code null} if it can not be + * identified + */ + public String getName() { + return name; + } + + /** + * @return the release of the distribution or {@code null} if it can not be + * identified + */ + public String getVersion() { + return version; + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/HostInfoBuilder.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,105 @@ +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.HostInfo; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class HostInfoBuilder { + + private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class); + + public HostInfo build() { + InetAddress localAddr; + String hostname; + try { + localAddr = InetAddress.getLocalHost(); + hostname = localAddr.getCanonicalHostName(); + } catch (UnknownHostException e) { + hostname = Constants.AGENT_LOCAL_HOSTNAME; + } + logger.log(Level.FINEST, "hostname: " + hostname); + DistributionIdentity identifier = new DistributionIdentity(); + String osName = identifier.getName() + " " + identifier.getVersion(); + logger.log(Level.FINEST, "osName: " + osName); + + String osKernel = System.getProperty("os.name") + " " + System.getProperty("os.version"); + logger.log(Level.FINEST, "osKernel: " + osKernel); + + // FIXME replace with a real implementation. This is the number of + // processors available to the _JVM_ + int cpuCount = Runtime.getRuntime().availableProcessors(); + logger.log(Level.FINEST, "cpuCount: " + cpuCount); + + long totalMemory = -1; + try { + BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo")); + String[] memTotalParts = reader.readLine().split(" +"); + long data = Long.valueOf(memTotalParts[1]); + String units = memTotalParts[2]; + if (units.equals("kB")) { + totalMemory = data * Constants.KILOBYTES_TO_BYTES; + } + } catch (IOException e) { + logger.log(Level.WARNING, "unable to read /proc/meminfo"); + } + logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes"); + + HashMap<String, List<String>> networkInfo = new HashMap<String, List<String>>(); + try { + Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface iface : Collections.list(ifaces)) { + List<String> ipAddresses = new ArrayList<String>(2); + ipAddresses.add(Constants.HOST_INFO_NETWORK_IPV4_INDEX, null); + ipAddresses.add(Constants.HOST_INFO_NETWORK_IPV6_INDEX, null); + for (InetAddress addr : Collections.list(iface.getInetAddresses())) { + if (addr instanceof Inet4Address) { + ipAddresses.set(Constants.HOST_INFO_NETWORK_IPV4_INDEX, fixAddr(addr.toString())); + } else if (addr instanceof Inet6Address) { + ipAddresses.set(Constants.HOST_INFO_NETWORK_IPV6_INDEX, fixAddr(addr.toString())); + } + } + networkInfo.put(iface.getName(), ipAddresses); + } + } catch (SocketException e) { + logger.log(Level.WARNING, "error enumerating network interfaces"); + } + + return new HostInfo(hostname, osName, osKernel, cpuCount, totalMemory, networkInfo); + + } + + /** + * Removes the "hostname/" and the "%scope_id" parts from the + * {@link InetAddress#toString()} output. + */ + private String fixAddr(String addr) { + int slashPos = addr.indexOf("/"); + if (slashPos == -1) { + return addr; + } + String fixed = addr.substring(slashPos + 1); + int percentPos = fixed.indexOf("%"); + if (percentPos == -1) { + return fixed; + } + fixed = fixed.substring(0, percentPos); + return fixed; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/MemoryStatBuilder.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,100 @@ +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.MemoryStat; +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.utils.LoggingUtils; + +/** + * Implementation note: uses information from /proc/ + */ +public class MemoryStatBuilder { + + private static final long UNAVAILABLE = -1; + + private static final String MEMINFO_FILE = "/proc/meminfo"; + + private static final String KEY_MEMORY_TOTAL = "MemTotal"; + private static final String KEY_MEMORY_FREE = "MemFree"; + private static final String KEY_BUFFERS = "Buffers"; + private static final String KEY_CACHED = "Cached"; + private static final String KEY_SWAP_TOTAL = "SwapTotal"; + private static final String KEY_SWAP_FREE = "SwapFree"; + private static final String KEY_COMMIT_LIMIT = "CommitLimit"; + + private static final Logger logger = LoggingUtils.getLogger(MemoryStatBuilder.class); + + public MemoryStat build() { + long timestamp = System.currentTimeMillis(); + + long total = UNAVAILABLE; + long free = UNAVAILABLE; + long swapTotal = UNAVAILABLE; + long swapFree = UNAVAILABLE; + long buffers = UNAVAILABLE; + long cached = UNAVAILABLE; + long commitLimit = UNAVAILABLE; + try { + BufferedReader reader = new BufferedReader(new FileReader(MEMINFO_FILE)); + String line = null; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(":"); + if (parts.length == 2) { + String key = parts[0].trim(); + long value = getValue(parts[1].trim()); + if (key.equals(KEY_MEMORY_TOTAL)) { + total = value; + } else if (key.equals(KEY_MEMORY_FREE)) { + free = value; + } else if (key.equals(KEY_SWAP_TOTAL)) { + swapTotal = value; + } else if (key.equals(KEY_SWAP_FREE)) { + swapFree = value; + } else if (key.equals(KEY_BUFFERS)) { + buffers = value; + } else if (key.equals(KEY_CACHED)) { + cached = value; + } else if (key.equals(KEY_COMMIT_LIMIT)) { + commitLimit = value; + } + + } + } + } catch (IOException e) { + logger.log(Level.WARNING, "unable to read " + MEMINFO_FILE); + } + return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit); + } + + private long getValue(String rawValue) { + String[] parts = rawValue.split(" +"); + String value = rawValue; + String units = null; + if (parts.length > 1) { + value = parts[0]; + units = parts[1]; + } + + long result = UNAVAILABLE; + try { + result = Long.parseLong(value); + if (units != null) { + if (units.equals("kB") || units.equals("KB")) { + result = result * Constants.KILOBYTES_TO_BYTES; + } else { + throw new NotImplementedException("unit conversion from " + units + " not implemented"); + } + } + } catch (NumberFormatException nfe) { + logger.log(Level.WARNING, "error extracting memory info from " + MEMINFO_FILE); + } + + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/backend/system/SystemBackend.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,100 @@ +package com.redhat.thermostat.backend.system; + +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.common.CpuStat; +import com.redhat.thermostat.common.HostInfo; +import com.redhat.thermostat.common.MemoryStat; +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class SystemBackend extends Backend { + + private static final String NAME = "system"; + private static final String DESCRIPTION = "gathers basic information from the system"; + private static final String VENDOR = "thermostat project"; + private static final String VERSION = "0.01"; + + private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class); + + private long procCheckInterval = 1000; + + private Timer timer = null; + + @Override + protected void setConfigurationValue(String name, String value) { + logger.log(Level.INFO, "configuring " + NAME + " not supported"); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } + + @Override + public String getVendor() { + return VENDOR; + } + + @Override + public String getVersion() { + return VERSION; + } + + @Override + public Map<String, String> getConfigurationMap() { + throw new NotImplementedException("get configuration"); + } + + @Override + public synchronized boolean activate() { + if (timer != null) { + return true; + } + + HostInfo hostInfo = new HostInfoBuilder().build(); + storage.updateHostInfo(hostInfo); + + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + CpuStat cpuStat = new CpuStatBuilder().build(); + storage.addCpuStat(cpuStat); + + MemoryStat memoryStat = new MemoryStatBuilder().build(); + storage.addMemoryStat(memoryStat); + } + }, 0, procCheckInterval); + + return true; + } + + @Override + public synchronized boolean deactivate() { + if (timer == null) { + return true; + } + + timer.cancel(); + timer = null; + + return true; + } + + @Override + public synchronized boolean isActive() { + return (timer != null); + } + +}
--- a/src/com/redhat/thermostat/common/Constants.java Tue Nov 29 11:58:37 2011 -0500 +++ b/src/com/redhat/thermostat/common/Constants.java Fri Dec 02 12:37:01 2011 -0500 @@ -29,4 +29,10 @@ public static final String AGENT_LOCAL_HOSTNAME = "localhost"; + public static final long KILOBYTES_TO_BYTES = 1000; + + public static final int HOST_INFO_NETWORK_IPV4_INDEX = 0; + public static final int HOST_INFO_NETWORK_IPV6_INDEX = 1; + + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/CpuStat.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,38 @@ +package com.redhat.thermostat.common; + +public class CpuStat { + + public static final double INVALID_LOAD = Double.MIN_VALUE; + + private final double load5; + private final double load10; + private final double load15; + private final long timeStamp; + + public CpuStat(long timestamp, double load5, double load10, double load15) { + this.timeStamp = timestamp; + this.load5 = load5; + this.load10 = load10; + this.load15 = load15; + } + + public double getLoad5() { + return load5; + } + + public double getLoad10() { + return load10; + } + + public double getLoad15() { + return load15; + } + + public double[] getLoad() { + return new double[] { load5, load10, load15 }; + } + + public long getTimeStamp() { + return timeStamp; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/HostInfo.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,55 @@ +package com.redhat.thermostat.common; + +import java.util.List; +import java.util.Map; + +public class HostInfo { + + private final String hostname; + private final String osName; + private final String osKernel; + private final int cpuCount; + private final long totalMemory; + private final Map<String, List<String>> networkInfo; + + public HostInfo(String hostname, String osName, String osKernel, int cpuCount, long totalMemory, Map<String, List<String>> networkInfo) { + this.hostname = hostname; + this.osName = osName; + this.osKernel = osKernel; + this.cpuCount = cpuCount; + this.totalMemory = totalMemory; + this.networkInfo = networkInfo; + } + + public String getHostname() { + return hostname; + } + + public String getOsName() { + return osName; + } + + public String getOsKernel() { + return osKernel; + } + + public int getCpuCount() { + return cpuCount; + } + + /** + * Total memory in bytes + */ + public long getTotalMemory() { + return totalMemory; + } + + /** + * @returns a map of the following form: {iface-name: [ipv4_addr, + * ipv6_addr]} + */ + public Map<String, List<String>> getNetworkInfo() { + return networkInfo; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/MemoryStat.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,56 @@ +package com.redhat.thermostat.common; + +public class MemoryStat { + private final long timestamp; + private final long total; + private final long free; + private final long buffers; + private final long cached; + private final long swapTotal; + private final long swapFree; + private final long commitLimit; + + public MemoryStat(long timestamp, long total, long free, long buffers, long cached, long swapTotal, long swapFree, long commitLimit) { + this.timestamp = timestamp; + this.total = total; + this.free = free; + this.buffers = buffers; + this.cached = cached; + this.swapTotal = swapTotal; + this.swapFree = swapFree; + this.commitLimit = commitLimit; + } + + public long getTimeStamp() { + return timestamp; + } + + public long getTotal() { + return total; + } + + public long getFree() { + return free; + } + + public long getBuffers() { + return buffers; + } + + public long getCached() { + return cached; + } + + public long getSwapTotal() { + return swapTotal; + } + + public long getSwapFree() { + return swapFree; + } + + public long getCommitLimit() { + return commitLimit; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/redhat/thermostat/common/NotImplementedException.java Fri Dec 02 12:37:01 2011 -0500 @@ -0,0 +1,15 @@ +package com.redhat.thermostat.common; + +public class NotImplementedException extends RuntimeException { + + private static final long serialVersionUID = -1620198443624195618L; + + public NotImplementedException(String message) { + super(message); + } + + public NotImplementedException(String message, Throwable cause) { + super(message, cause); + } + +}