/* * Copyright 2016 christopher.metter. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.uniwuerzburg.info3.ofcprobe.vswitch.statistics; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import de.uniwuerzburg.info3.ofcprobe.vswitch.main.config.Config; import de.uniwuerzburg.info3.ofcprobe.vswitch.statistics.snmp.SNMPManager; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.snmp4j.event.ResponseEvent; import org.snmp4j.smi.OID; /** * Controller CPU and RAM Monitor per SNMP * * @author Christopher Metter(christopher.metter@informatik.uni-wuerzburg.de) * */ public class ControllerCPUnRAMMonitor implements IStatistics { /** * Outputfile for CPU */ private String cpuFile; /** * Outputfile for RAM */ private String ramFile; /** * List of CPU Values */ private List<Double> cpuValues; /** * List of Used Ram Values */ private List<Double> ramUsedValues; /** * List of Free Ram Values */ private List<Double> ramFreeValues; /** * The Logger */ private static final Logger logger = LoggerFactory.getLogger(ControllerCPUnRAMMonitor.class); /** * Bool for Session Running */ private boolean sessionRunning; /** * Date of Last Query */ private Date lastValue; /** * IAT of Polls */ private long pollTime; /** * The SNMP Manager */ private SNMPManager snmp; /** * The LastResponse */ private ResponseEvent lastResponse; /** * List of OIDs to request */ private OID[] oids; /** * The DPID */ private String dpid; /** * Bool for CPUQueries */ private boolean queryCPU; /** * Bool for RAMQueries */ private boolean queryRAM; /** * Positon of ramFreeValues in OID Response */ private int ramFreePos; /** * Positon of ramTotalValues in OID Response */ private int ramTotalPos; /** * * * Got Error from SNMP? */ private boolean snmpError; /** * Constructor * * @param config the Config File */ public ControllerCPUnRAMMonitor(Config config) { this.cpuValues = new ArrayList<>(); this.ramUsedValues = new ArrayList<>(); this.ramFreeValues = new ArrayList<>(); this.sessionRunning = false; NumberFormat formatter = new DecimalFormat("#000"); this.dpid = formatter.format(config.getSwitchConfig().getDpid()); this.pollTime = 10000; checkForSNMP(config.getStatConfig().getMonitorAddress().getHostString()); if (!this.snmpError) { this.snmp = new SNMPManager("udp:" + config.getStatConfig().getMonitorAddress().getHostString() + "/161"); this.snmp.start(); List<String> modules = config.getStatConfig().getStatModules(); // Build correct OID Set if (modules.contains("CPU") && modules.contains("RAM")) { this.queryCPU = true; this.queryRAM = true; /* * rawUser = .1.3.6.1.4.1.2021.11.50.0 * rawNice = .1.3.6.1.4.1.2021.11.51.0 * rawSystem = .1.3.6.1.4.1.2021.11.52.0 * rawIDL = .1.3.6.1.4.1.2021.11.53.0 * rawWait = .1.3.6.1.4.1.2021.11.54.0 * rawKernel = .1.3.6.1.4.1.2021.11.55.0 * rawInterrupt = .1.3.6.1.4.1.2021.11.56.0 * ramFree = .1.3.6.1.4.1.2021.4.6.0 * ramTotal = .1.3.6.1.4.1.2021.4.5.0 */ this.oids = new OID[]{ new OID(".1.3.6.1.4.1.2021.11.50.0"), new OID(".1.3.6.1.4.1.2021.11.51.0"), new OID(".1.3.6.1.4.1.2021.11.52.0"), new OID(".1.3.6.1.4.1.2021.11.53.0"), new OID(".1.3.6.1.4.1.2021.4.6.0"), new OID(".1.3.6.1.4.1.2021.4.5.0")}; this.ramFreePos = 4; this.ramTotalPos = 5; } if (modules.contains("CPU") && !modules.contains("RAM")) { this.queryCPU = true; this.queryRAM = false; /* * rawUser = .1.3.6.1.4.1.2021.11.50.0 * rawNice = .1.3.6.1.4.1.2021.11.51.0 * rawSystem = .1.3.6.1.4.1.2021.11.52.0 * rawIDL = .1.3.6.1.4.1.2021.11.53.0 * rawWait = .1.3.6.1.4.1.2021.11.54.0 * rawKernel = .1.3.6.1.4.1.2021.11.55.0 * rawInterrupt = .1.3.6.1.4.1.2021.11.56.0 */ this.oids = new OID[]{ new OID(".1.3.6.1.4.1.2021.11.50.0"), new OID(".1.3.6.1.4.1.2021.11.51.0"), new OID(".1.3.6.1.4.1.2021.11.52.0"), new OID(".1.3.6.1.4.1.2021.11.53.0")}; } if (!modules.contains("CPU") && modules.contains("RAM")) { this.queryCPU = false; this.queryRAM = true; /* * ramFree = .1.3.6.1.4.1.2021.4.6.0 * ramTotal = .1.3.6.1.4.1.2021.4.5.0 */ this.oids = new OID[]{ new OID(".1.3.6.1.4.1.2021.4.6.0"), new OID(".1.3.6.1.4.1.2021.4.5.0")}; this.ramFreePos = 0; this.ramTotalPos = 1; } } } /** * Method thought to check if there is SNMP Server running on provided IP * * @param ip the IP Address */ private void checkForSNMP(String ip) { // SocketChannel chan; // try { // chan = SocketChannel.open(); // chan.connect(new InetSocketAddress(ip, 161)); // chan.close(); // } catch (IOException e) { // logger.error("Cannot reach SNMPD - Is SNMPD started?"); // this.snmpError = true; // } } @Override public void setReportFile(String file) { if (file.contains("cpu")) { this.cpuFile = file; } if (file.contains("ram")) { this.ramFile = file; } } @Override public void packetIn(OFMessage in) { if (!this.snmpError && this.sessionRunning && in.getType() == OFType.PACKET_OUT) { Date now = new Date(); if (now.getTime() - this.lastValue.getTime() > this.pollTime) { this.lastValue = now; queryNextValues(); } } } @Override public void packetOut(OFMessage out) { // Doing nothing } @Override public void evaluate() { } @Override public void report() { if (!this.snmpError) { writeToFile(); } } @Override public void start() { this.lastValue = new Date(); if (!this.snmpError) { this.sessionRunning = true; queryNextValues(); this.cpuValues.clear(); this.ramFreeValues.clear(); } } @Override public void stop() { this.sessionRunning = false; } private void queryNextValues() { double cpuValue = 0.0; double ramValue = 0.0; double ramFree = 0.0; if (this.lastResponse == null) { this.lastResponse = this.snmp.get(this.oids); } ResponseEvent respNow = this.snmp.get(this.oids); if (this.queryCPU) { for (int i = 0; i < 5; i++) { cpuValue += calculateCPUValue(this.lastResponse, respNow); } cpuValue = cpuValue / 5; this.lastResponse = respNow; logger.trace("[Switch#{}]: New CPU Value: {}", this.dpid, cpuValue); this.cpuValues.add(cpuValue); } if (this.queryRAM) { ramFree = queryFreeRAMValue(respNow); ramValue = calculateUsedRAMValue(respNow); logger.trace("[Switch#{}]: New Used RAM Value: {} - New Free RAM Value: {}", this.dpid, ramValue, ramFree); this.ramUsedValues.add(ramValue); this.ramFreeValues.add(ramFree); } } /** * Write Results to File */ private void writeToFile() { try { if (this.queryCPU) { File filou = new File(this.cpuFile); if (!filou.getParentFile().exists()) { filou.getParentFile().mkdirs(); } PrintWriter out = new PrintWriter(this.cpuFile); // CPU double cpuMean = 0.0; if (!this.cpuValues.isEmpty()) { for (double cpu : this.cpuValues) { out.print(cpu + ";"); cpuMean += cpu; } } else { out.print("0;"); } out.print("\n"); cpuMean = cpuMean / this.cpuValues.size(); if (Double.isNaN(cpuMean)) { cpuMean = 0; } logger.info("[Switch#{}]: CPUMean in this Session: {}", this.dpid, cpuMean); out.println(cpuMean); out.close(); } if (this.queryRAM) { File filou = new File(this.cpuFile); if (!filou.getParentFile().exists()) { filou.getParentFile().mkdirs(); } PrintWriter out = new PrintWriter(this.ramFile); // RAM Used double ramUsedMean = 0.0; if (!this.ramUsedValues.isEmpty()) { for (double ram : this.ramUsedValues) { out.print(ram + ";"); ramUsedMean += ram; } } else { out.print("0;"); } out.print("\n"); ramUsedMean = ramUsedMean / this.ramUsedValues.size(); if (Double.isNaN(ramUsedMean)) { ramUsedMean = 0; } logger.info("[Switch#{}]: RAM Used Mean in this Session: {}", this.dpid, ramUsedMean); out.println(ramUsedMean); // RAM Free double ramFreeMean = 0.0; if (!this.ramFreeValues.isEmpty()) { for (double ram : this.ramFreeValues) { out.print(ram + ";"); ramFreeMean += ram; } } else { out.print("0;"); } out.print("\n"); ramFreeMean = ramFreeMean / this.ramFreeValues.size(); if (Double.isNaN(ramFreeMean)) { ramFreeMean = 0; } logger.info("[Switch#{}]: RAM Free Mean in this Session: {}", this.dpid, ramFreeMean); out.println(ramFreeMean); out.close(); } } catch (FileNotFoundException e) { logger.error("[Switch#{}]: {}", this.dpid, e); } } /** * Calculate the CPU load * * @param respLast first Response * @param respNow second Response * @return double Value */ private double calculateCPUValue(ResponseEvent respLast, ResponseEvent respNow) { try { if (respLast != null && respNow != null && respLast.getResponse() != null && respNow.getResponse() != null) { int rawUserOne = Integer.valueOf(respLast.getResponse().get(0).toValueString()); int rawNiceOne = Integer.valueOf(respLast.getResponse().get(1).toValueString()); int rawSystemOne = Integer.valueOf(respLast.getResponse().get(2).toValueString()); int rawIDLOne = Integer.valueOf(respLast.getResponse().get(3).toValueString()); int rawUserTwo = Integer.valueOf(respNow.getResponse().get(0).toValueString()); int rawNiceTwo = Integer.valueOf(respNow.getResponse().get(1).toValueString()); int rawSystemTwo = Integer.valueOf(respNow.getResponse().get(2).toValueString()); int rawIDLTwo = Integer.valueOf(respNow.getResponse().get(3).toValueString()); int rawUserDiff = rawUserTwo - rawUserOne; int rawNiceDiff = rawNiceTwo - rawNiceOne; int rawSystemDiff = rawSystemTwo - rawSystemOne; int rawIDLDiff = rawIDLTwo - rawIDLOne; int sum = rawUserDiff + rawNiceDiff + rawSystemDiff + rawIDLDiff; if (sum != 0) { return (double) (100 - (((double) rawIDLDiff * 100) / ((double) sum))); } } else { logger.error("SNMP Response was NULL - Assuming SNMPD is offline. Exiting now!"); this.snmpError = true; stop(); System.exit(-1); } return 0; } catch (NullPointerException e) { logger.error("SNMP CPU Values threw Nullpointer - Assuming SNMPD is offline. Exiting now!"); this.snmpError = true; stop(); System.exit(-1); return 0; } } /** * Calculate the RAM load * * @param respNow Response * @return double Value */ private double queryFreeRAMValue(ResponseEvent respNow) { try { if (respNow != null && respNow.getResponse() != null) { double ramFree = Double.parseDouble(respNow.getResponse().get(this.ramFreePos).toValueString()); if (ramFree != 0) { ramFree = ramFree / 1024; } return ramFree; } else { logger.error("SNMP Response was NULL - Assuming SNMPD is offline. Exiting now!"); this.snmpError = true; stop(); System.exit(-1); } return 0; } catch (NullPointerException e) { logger.error("SNMP RAM Values threw Nullpointer - Assuming SNMPD is offline. Exiting now!"); this.snmpError = true; stop(); System.exit(-1); return 0; } } /** * Calculate the RAM load * * @param respNow Response * @return double Value */ private double calculateUsedRAMValue(ResponseEvent respNow) { try { if (respNow != null && respNow.getResponse() != null) { double ramFree = Double.valueOf(respNow.getResponse().get(this.ramFreePos).toValueString()); double ramTotal = Double.valueOf(respNow.getResponse().get(this.ramTotalPos).toValueString()); double ramUsed = ramTotal - ramFree; ramUsed = ramUsed / 1024; return ramUsed; } return 0; } catch (NullPointerException e) { return 0; } } }