Java tutorial
/** * Copyright 2014 University of Leeds * * 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 eu.tango.energymodeller.datasourceclient; import eu.tango.energymodeller.datastore.MySqlDatabaseConnector; import static eu.tango.energymodeller.datasourceclient.KpiList.BOOT_TIME_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.CPU_IDLE_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.CPU_SPOT_USAGE_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.DISK_TOTAL_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.MEMORY_TOTAL_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.POWER_KPI_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.VM_PHYSICAL_HOST_NAME; import static eu.tango.energymodeller.datasourceclient.KpiList.VM_PHYSICAL_HOST_NAME_2; import eu.tango.energymodeller.types.energyuser.ApplicationOnHost; import eu.tango.energymodeller.types.energyuser.ApplicationOnHost.JOB_STATUS; import eu.tango.energymodeller.types.energyuser.EnergyUsageSource; import eu.tango.energymodeller.types.energyuser.GeneralPurposePowerConsumer; import eu.tango.energymodeller.types.energyuser.Host; import eu.tango.energymodeller.types.energyuser.VmDeployed; import eu.tango.energymodeller.types.usage.CurrentUsageRecord; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; /** * This directly connects to a Zabbix database and scavenges the data required * directly. This thus eliminates overhead and improves overall performance. * * @author Richard Kavanagh */ public class ZabbixDirectDbDataSourceAdaptor extends MySqlDatabaseConnector implements HostDataSource { /** * Get max item id values for history items select itemid, max(clock) from * history group by itemid; * * Get all history item names for a named host/s * * select itemid, items.name from hosts, items where hosts.hostid = * items.hostid and hosts.host = "testgrid3"; select itemid, items.name from * hosts, items where hosts.hostid = items.hostid and hosts.hostid = 10084; * select itemid, items.name from hosts, items where hosts.hostid = * items.hostid and hosts.hostid IN (10084, 10105, 10106); * * SELECT history.itemid, clock, value FROM history INNER JOIN ( select * itemid, max(clock) AS mostrecent from history group by itemid) ms ON * history.itemid = ms.itemid AND clock = mostrecent WHERE history.itemid IN * (select itemid from hosts, items where hosts.hostid = items.hostid and * hosts.hostid = 10084); */ private Connection connection; /** * This query lists all hosts data items. status <> 3 excludes templates 0 - * not available (templates are in this category), 1 - available, 2 - * unknown. * * see: * https://www.zabbix.com/documentation/2.0/manual/config/items/itemtypes/internal */ private String allZabbixHosts = "SELECT hosts.hostid, hosts.host, groups.name FROM " + "groups, hosts_groups, hosts WHERE groups.groupid = hosts_groups.groupid " + "AND hosts.hostid = hosts_groups.hostid " + "AND hosts.status <> 3"; private static final String FILTER_BY_GROUP = " AND groups.name = ? "; private static final String FILTER_BY_NAME = " AND hosts.name = ?"; /** * This query searches for a named host and provides it's current latest * items. * * The order of the ? is as follows: table, table, hostid * * It returns the item id, clock, item name, item key and item value. */ private static final String QUERY_DATA_BY_ID = "SELECT h.itemid, h.clock, i.name, i.key_, h.value " + "FROM items i, XXXX h, " + "(SELECT hs.itemid, max(hs.clock) AS mostrecent FROM XXXX hs GROUP BY hs.itemid) ms " + "WHERE h.itemid = ms.itemid AND " + "h.clock = mostrecent AND " + "h.itemid = i.itemid AND " + "h.itemid IN (SELECT it.itemid FROM hosts, items it " + "WHERE hosts.hostid = it.hostid AND " + "hosts.hostid = ?)"; /** * This query searches for a named double valued history item for a given * host between a range of specified times. * * The order of the ? is as follows: hostid, item name, clock start, clock * end */ private static final String HISTORY_QUERY = "SELECT h.itemid, h.clock, h.value " + "FROM history h " + "WHERE h.clock >= ? AND " + "h.clock <= ? AND " + "h.itemid = (" + "SELECT it.itemid " + "FROM hosts, items it " + "WHERE hosts.hostid = it.hostid AND " + "hosts.hostid = ? AND " + "it.key_ = ?)"; private static final HashSet<String> HISTORY_TABLES = new HashSet<>(); /** * The url to contact the database. */ private String databaseURL; /** * The driver to be used to contact the database. */ private String databaseDriver = "com.mysql.jdbc.Driver"; /** * The user details to contact the database. */ private String databaseUser = "zabbix"; /** * The user's password to contact the database. */ private String databasePassword; /** * The filter string, if a host/VM begins with this then it is a host, if * isHost equals true. */ private String vmGroup = "Virtual machines"; private String hostGroup = "Hypervisors"; private String generalPowerConsumer = "DFS"; private boolean onlyAvailableHosts = false; private static final String CONFIG_FILE = "energy-modeller-db-zabbix.properties"; private static final Logger DB_LOGGER = Logger.getLogger(ZabbixDirectDbDataSourceAdaptor.class.getName()); /** * This creates a new database connector for use. It establishes a database * connection immediately ready for use. */ public ZabbixDirectDbDataSourceAdaptor() { HISTORY_TABLES.add("history"); HISTORY_TABLES.add("history_str"); HISTORY_TABLES.add("history_uint"); HISTORY_TABLES.add("history_text"); try { PropertiesConfiguration config; if (new File(CONFIG_FILE).exists()) { config = new PropertiesConfiguration(CONFIG_FILE); } else { config = new PropertiesConfiguration(); config.setFile(new File(CONFIG_FILE)); } config.setAutoSave(true); //This will save the configuration file back to disk. In case the defaults need setting. databaseURL = config.getString("energy.modeller.zabbix.db.url", "jdbc:mysql://<ADD_ZABBIX_DB_SERVER_ADDRESS_HERE>:3306/zabbix"); config.setProperty("energy.modeller.zabbix.db.url", databaseURL); databaseDriver = config.getString("energy.modeller.zabbix.db.driver", databaseDriver); try { Class.forName(databaseDriver); } catch (ClassNotFoundException ex) { //If the driver is not found on the class path revert to MariaDB. databaseDriver = "com.mysql.jdbc.Driver"; } config.setProperty("energy.modeller.zabbix.db.driver", databaseDriver); databasePassword = config.getString("energy.modeller.zabbix.db.password", ""); config.setProperty("energy.modeller.zabbix.db.password", databasePassword); databaseUser = config.getString("energy.modeller.zabbix.db.user", databaseUser); config.setProperty("energy.modeller.zabbix.db.user", databaseUser); vmGroup = config.getString("energy.modeller.vm.group", vmGroup); config.setProperty("energy.modeller.vm.group", vmGroup); hostGroup = config.getString("energy.modeller.host.group", hostGroup); config.setProperty("energy.modeller.host.group", hostGroup); generalPowerConsumer = config.getString("energy.modeller.dfs.group", generalPowerConsumer); config.setProperty("energy.modeller.dfs.group", generalPowerConsumer); onlyAvailableHosts = config.getBoolean("energy.zabbix.only.available.hosts", onlyAvailableHosts); config.setProperty("energy.zabbix.only.available.hosts", onlyAvailableHosts); if (onlyAvailableHosts) { allZabbixHosts = allZabbixHosts + " AND h.available = 1"; } } catch (ConfigurationException ex) { DB_LOGGER.log(Level.SEVERE, "Error loading the configuration of the IaaS energy modeller", ex); } try { connection = getConnection(); } catch (IOException | SQLException | ClassNotFoundException ex) { DB_LOGGER.log(Level.SEVERE, "Failed to establish the connection to the Zabbix DB", ex); } } /** * Establishes a connection to the database. * * @return Connection object representing the connection * @throws IOException if properties file cannot be accessed * @throws SQLException if connection fails * @throws ClassNotFoundException if the database driver class is not found */ @Override protected final Connection getConnection() throws IOException, SQLException, ClassNotFoundException { // Define JDBC driver System.setProperty("jdbc.drivers", databaseDriver); //Ensure that the driver has been loaded Class.forName(databaseDriver); return DriverManager.getConnection(databaseURL, databaseUser, databasePassword); } @Override public Host getHostByName(String hostname) { connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection .prepareStatement(allZabbixHosts + FILTER_BY_GROUP + FILTER_BY_NAME)) { preparedStatement.setString(1, hostGroup); preparedStatement.setString(2, hostname); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { Host answer = new Host(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); answer = fullyDescribeHost(answer, getHostData(answer).getMetrics().values()); return answer; } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return null; } @Override public GeneralPurposePowerConsumer getGeneralPowerConsumerByName(String hostname) { connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection .prepareStatement(allZabbixHosts + FILTER_BY_GROUP + FILTER_BY_NAME)) { preparedStatement.setString(1, generalPowerConsumer); preparedStatement.setString(2, hostname); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { GeneralPurposePowerConsumer answer = new GeneralPurposePowerConsumer( ((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); answer = (GeneralPurposePowerConsumer) fullyDescribeHost(answer, getHostData(answer).getMetrics().values()); return answer; } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return null; } @Override public VmDeployed getVmByName(String name) { connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection .prepareStatement(allZabbixHosts + FILTER_BY_GROUP + FILTER_BY_NAME)) { preparedStatement.setString(1, vmGroup); preparedStatement.setString(2, name); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { VmDeployed answer = new VmDeployed(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); answer = fullyDescribeVM(answer, getVmData(answer).getMetrics().values()); return answer; } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return null; } /** * This gathers more information about a host than is available by querying * the host list table directly. * * @param host The host to populate with more information * @param items The data items to enrich the host with * @return The host object with more information attached. */ private Host fullyDescribeHost(Host host, Collection<MetricValue> items) { for (MetricValue item : items) { if (item.getKey().equals(MEMORY_TOTAL_KPI_NAME)) { //Convert to Mb //Original value given in bytes. 1024 * 1024 = 1048576 host.setRamMb((int) (item.getValue() / 1048576)); } if (item.getKey().equals(DISK_TOTAL_KPI_NAME)) { //Convert to Mb //Original value given in bytes. 1024 * 1024 * 1024 = 1073741824 host.setDiskGb((item.getValue() / 1073741824)); } } return host; } /** * This gathers more information about a vm than is available by querying * the host list table directly. * * @param vm The vm to populate with more information * @param items The data for a given vm. * @return The vm object with more information attached. */ private VmDeployed fullyDescribeVM(VmDeployed vm, Collection<MetricValue> items) { vm = fullyDescribeVmZabbix(vm, items); vm = fullyDescribeVmLibVirt(vm, items); //A fall back incase the information is not available! if (vm.getCpus() == 0) { vm.setCpus(1); } //TODO set the information correctly below! //such as set the vms ip address vm.setState("Work in Progress"); return vm; } /** * This gathers more information about a vm than is available by querying * the host list table directly. This is geared towards default Zabbix * values. * * @param vm The vm to populate with more information * @param items The data for a given vm. * @return The vm object with more information attached. */ private VmDeployed fullyDescribeVmZabbix(VmDeployed vm, Collection<MetricValue> items) { for (MetricValue item : items) { if (item.getKey().equals(MEMORY_TOTAL_KPI_NAME)) { //Convert to Mb //Original value given in bytes. 1024 * 1024 = 1048576 vm.setRamMb((int) (Double.valueOf(item.getValue()) / 1048576)); } if (item.getKey().equals(DISK_TOTAL_KPI_NAME)) { //covert to Gb //Original value given in bytes. 1024 * 1024 * 1024 = 1073741824 vm.setDiskGb((Double.valueOf(item.getValue()) / 1073741824)); } if (item.getKey().equals(BOOT_TIME_KPI_NAME)) { Calendar cal = new GregorianCalendar(); //This converts from milliseconds into the correct time value cal.setTimeInMillis(TimeUnit.SECONDS.toMillis(Long.valueOf(item.getValueAsString()))); vm.setCreated(cal); } if (item.getKey().equals(VM_PHYSICAL_HOST_NAME)) { vm.setAllocatedTo(getHostByName(item.getValueAsString())); } } return vm; } /** * This gathers more information about a vm than is available by querying * the host list table directly. This is geared towards default values * provided by the aSCETiC libvirt connector. * * @param vm The vm to populate with more information * @param items The data for a given vm. * @return The vm object with more information attached. */ private VmDeployed fullyDescribeVmLibVirt(VmDeployed vm, Collection<MetricValue> items) { //TODO fix this here, with real values. if (vm.getRamMb() == 0) { //Convert to Mb //Original value given in bytes. 1024 * 1024 = 1048576 vm.setRamMb(4096); } if (vm.getDiskGb() == 0) { //covert to Gb //Original value given in bytes. 1024 * 1024 * 1024 = 1073741824 vm.setDiskGb(40); } //A fall back incase the information is not available! if (vm.getCpus() == 0) { vm.setCpus(2); } for (MetricValue item : items) { if (item.getKey().equals(VM_PHYSICAL_HOST_NAME_2)) { vm.setAllocatedTo(getHostByName(item.getValueAsString())); } } return vm; } @Override public List<Host> getHostList() { return getHostList(hostGroup); } public List<Host> getHostList(String groupName) { List<Host> answer = new ArrayList<>(); connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection.prepareStatement(allZabbixHosts + FILTER_BY_GROUP);) { preparedStatement.setString(1, groupName); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { Host host = new Host(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); host = fullyDescribeHost(host, getHostData(host).getMetrics().values()); answer.add(host); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return answer; } @Override public List<GeneralPurposePowerConsumer> getGeneralPowerConsumerList() { List<GeneralPurposePowerConsumer> answer = new ArrayList<>(); connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection.prepareStatement(allZabbixHosts + FILTER_BY_GROUP)) { preparedStatement.setString(1, generalPowerConsumer); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> storageData : results) { GeneralPurposePowerConsumer fileStore = new GeneralPurposePowerConsumer( ((Long) storageData.get(0)).intValue(), (String) storageData.get(1)); fileStore = (GeneralPurposePowerConsumer) fullyDescribeHost(fileStore, getHostData(fileStore).getMetrics().values()); answer.add(fileStore); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return answer; } @Override public List<EnergyUsageSource> getHostAndVmList() { List<EnergyUsageSource> answer = new ArrayList<>(); connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection .prepareStatement(allZabbixHosts + " AND (groups.name = ? OR groups.name = ?)")) { preparedStatement.setString(1, hostGroup); preparedStatement.setString(2, vmGroup); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { if (hostData.get(2).equals(hostGroup)) { Host host = new Host(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); host = fullyDescribeHost(host, getHostData(host).getMetrics().values()); answer.add(host); } else if (hostData.get(2).equals(generalPowerConsumer)) { GeneralPurposePowerConsumer host = new GeneralPurposePowerConsumer( ((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); host = (GeneralPurposePowerConsumer) fullyDescribeHost(host, getHostData(host).getMetrics().values()); answer.add(host); } else { VmDeployed vm = new VmDeployed(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); vm = fullyDescribeVM(vm, getVmData(vm).getMetrics().values()); answer.add(vm); } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return answer; } @Override public List<VmDeployed> getVmList() { return getVmList(vmGroup); } @Override public List<ApplicationOnHost> getHostApplicationList(JOB_STATUS state) { /* * Zabbix doesn't store this information thus an empty list is returned. */ return new ArrayList<>(); } @Override public List<ApplicationOnHost> getHostApplicationList() { /* * Zabbix doesn't store this information thus an empty list is returned. */ return new ArrayList<>(); } public List<VmDeployed> getVmList(String groupName) { List<VmDeployed> answer = new ArrayList<>(); connection = getConnection(connection); if (connection == null) { return null; } try (PreparedStatement preparedStatement = connection.prepareStatement(allZabbixHosts + FILTER_BY_GROUP)) { preparedStatement.setString(1, groupName); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { VmDeployed vm = new VmDeployed(((Long) hostData.get(0)).intValue(), (String) hostData.get(1)); vm = fullyDescribeVM(vm, getVmData(vm).getMetrics().values()); answer.add(vm); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return answer; } @Override public HostMeasurement getHostData(Host host) { HostMeasurement answer = new HostMeasurement(host); long clock = 0; connection = getConnection(connection); if (connection == null) { return null; } for (String historyTable : HISTORY_TABLES) { String query = QUERY_DATA_BY_ID.replace("XXXX", historyTable); try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, host.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> dataItem : results) { if ((int) dataItem.get(1) > clock) { clock = (int) dataItem.get(1); answer.setClock(clock); } //itemid | clock | name | key_ | value MetricValue value = new MetricValue((String) dataItem.get(2), (String) dataItem.get(3), dataItem.get(4) + "", (Integer) dataItem.get(1)); answer.addMetric(value); } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } return answer; } @Override public List<HostMeasurement> getHostData() { List<HostMeasurement> answer = new ArrayList<>(); for (Host host : getHostList()) { answer.add(getHostData(host)); } return answer; } @Override public List<HostMeasurement> getHostData(List<Host> hostList) { List<HostMeasurement> answer = new ArrayList<>(); for (Host host : hostList) { answer.add(getHostData(host)); } return answer; } @Override public VmMeasurement getVmData(VmDeployed vm) { VmMeasurement answer = new VmMeasurement(vm); long clock = 0; connection = getConnection(connection); if (connection == null) { return null; } for (String historyTable : HISTORY_TABLES) { String query = QUERY_DATA_BY_ID.replace("XXXX", historyTable); try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, vm.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> dataItem : results) { if ((int) dataItem.get(1) > clock) { clock = (int) dataItem.get(1); answer.setClock(clock); } //itemid | clock | name | key_ | value MetricValue value = new MetricValue((String) dataItem.get(2), //name (String) dataItem.get(3), //key dataItem.get(4) + "", //value (Integer) dataItem.get(1)); //clock answer.addMetric(value); } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } } return answer; } @Override public List<VmMeasurement> getVmData() { List<VmMeasurement> answer = new ArrayList<>(); for (VmDeployed vm : getVmList()) { answer.add(getVmData(vm)); } return answer; } @Override public List<VmMeasurement> getVmData(List<VmDeployed> vmList) { List<VmMeasurement> answer = new ArrayList<>(); for (VmDeployed host : vmList) { answer.add(getVmData(host)); } return answer; } @Override public CurrentUsageRecord getCurrentEnergyUsage(Host host) { CurrentUsageRecord answer = new CurrentUsageRecord(host); HostMeasurement measurement = getHostData(host); answer.setPower(measurement.getPower(true)); answer.setVoltage(-1); answer.setCurrent(-1); return answer; } @Override public double getLowestHostPowerUsage(Host host) { long currentTime = TimeUnit.MILLISECONDS.toSeconds(new GregorianCalendar().getTimeInMillis()); long timeInPast = currentTime - TimeUnit.MINUTES.toSeconds(10); //NOTE: The semantics do not match the other Zabbix Datasource adaptor List<Double> energyData = getHistoryDataItems(POWER_KPI_NAME, host.getId(), timeInPast, currentTime); double lowestValue = Double.MAX_VALUE; for (Double current : energyData) { if (current < lowestValue) { lowestValue = current; } } return lowestValue; } @Override public double getHighestHostPowerUsage(Host host) { long currentTime = TimeUnit.MILLISECONDS.toSeconds(new GregorianCalendar().getTimeInMillis()); long timeInPast = currentTime - TimeUnit.MINUTES.toSeconds(10); //NOTE: The semantics do not match the other Zabbix Datasource adaptor List<Double> energyData = getHistoryDataItems(POWER_KPI_NAME, host.getId(), timeInPast, currentTime); double highestValue = Double.MIN_VALUE; for (Double current : energyData) { if (current > highestValue) { highestValue = current; } } return highestValue; } @Override public double getCpuUtilisation(Host host, int durationSeconds) { long currentTime = TimeUnit.MILLISECONDS.toSeconds(new GregorianCalendar().getTimeInMillis()); long timeInPast = currentTime - durationSeconds; List<Double> spotCpuData = getHistoryDataItems(CPU_SPOT_USAGE_KPI_NAME, host.getId(), timeInPast, currentTime); if (spotCpuData != null && !spotCpuData.isEmpty()) { double usage = removeNaN(sumArray(spotCpuData) / ((double) spotCpuData.size())); return usage / 100; } List<Double> idleData = getHistoryDataItems(CPU_IDLE_KPI_NAME, host.getId(), timeInPast, currentTime); double idle = removeNaN(sumArray(idleData) / ((double) idleData.size())); return 1 - ((idle) / 100); } /** * In the case that no data is provided a NaN value will be given, this * needs to be stopped. It occurs when the getCpuUtilisation method is given * too small a time window for gathering CPU utilisation data. */ private double removeNaN(double number) { if (Double.isNaN(number)) { return 0.0; } else { return number; } } /** * This query returns a set of history items for querying. * * @param key The key of the data item to return * @param hostId The host id that the data is associated with * @param startTime The start time of the search * @param endTime The end time of the search * @return The list of double values one for each data item point. */ private List<Double> getHistoryDataItems(String key, int hostId, long startTime, long endTime) { List<Double> answer = new ArrayList<>(); connection = getConnection(connection); if (connection == null) { return answer; } try (PreparedStatement preparedStatement = connection.prepareStatement(HISTORY_QUERY)) { //hostid, item name, clock start, clock end preparedStatement.setLong(1, startTime); preparedStatement.setLong(2, endTime); preparedStatement.setInt(3, hostId); preparedStatement.setString(4, key); try (ResultSet resultSet = preparedStatement.executeQuery()) { ArrayList<ArrayList<Object>> results = resultSetToArray(resultSet); for (ArrayList<Object> hostData : results) { Double value = ((Double) hostData.get(2)); answer.add(value); } } } catch (SQLException ex) { DB_LOGGER.log(Level.SEVERE, null, ex); } return answer; } /** * This function sums a list of numbers for historic data. * * @param list The ArrayList to calculate the values of. * @return The sum of the values. */ private double sumArray(List<Double> list) { double answer = 0.0; for (Double current : list) { answer = answer + current.doubleValue(); } return answer; } }