From 6a1742e72a6ec4fa52c7b080d9f4d5e753aa87f6 Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Fri, 9 Oct 2020 10:20:50 +0200 Subject: [PATCH 1/4] Refactoring work for more Java compatibility and static compilation. --- bitbucket-pipelines.yml | 3 +- build.gradle | 27 +- src/main/groovy/biz/nellemann/hmci/App.groovy | 246 ---------------- .../biz/nellemann/hmci/HmcClient.groovy | 37 ++- .../biz/nellemann/hmci/InfluxClient.groovy | 266 +++++++++--------- .../groovy/biz/nellemann/hmci/Insights.groovy | 176 ++++++++++++ .../nellemann/hmci/LogicalPartition.groovy | 78 ++--- .../groovy/biz/nellemann/hmci/Main.groovy | 59 ++++ .../biz/nellemann/hmci/ManagedSystem.groovy | 131 +++++---- .../biz/nellemann/hmci/MetaSystem.groovy | 12 +- .../biz/nellemann/hmci/Configuration.java | 161 +++++++++++ .../java/biz/nellemann/hmci/Measurement.java | 17 ++ .../biz/nellemann/hmci/VersionProvider.java | 19 ++ src/main/resources/logback.xml | 2 +- .../nellemann/hmci/ConfigurationTest.groovy | 30 ++ .../biz/nellemann/hmci/HmcClientTest.groovy | 7 +- .../{AppTest.groovy => InsightsTest.groovy} | 4 +- .../hmci/LogicalPartitionTest.groovy | 32 +-- .../nellemann/hmci/ManagedSystemTest.groovy | 24 +- src/test/resources/hmci.toml | 32 +++ 20 files changed, 837 insertions(+), 526 deletions(-) delete mode 100644 src/main/groovy/biz/nellemann/hmci/App.groovy create mode 100644 src/main/groovy/biz/nellemann/hmci/Insights.groovy create mode 100644 src/main/groovy/biz/nellemann/hmci/Main.groovy create mode 100644 src/main/java/biz/nellemann/hmci/Configuration.java create mode 100644 src/main/java/biz/nellemann/hmci/Measurement.java create mode 100644 src/main/java/biz/nellemann/hmci/VersionProvider.java create mode 100644 src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy rename src/test/groovy/biz/nellemann/hmci/{AppTest.groovy => InsightsTest.groovy} (75%) create mode 100644 src/test/resources/hmci.toml diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index be2396f..7c2cc8b 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -1,5 +1,4 @@ -image: adoptopenjdk:8-openj9 -#image: openjdk:8 +image: openjdk:8 pipelines: branches: diff --git a/build.gradle b/build.gradle index a5dc29e..0146626 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,6 @@ plugins { - // Apply the groovy plugin to add support for Groovy + id 'java' id 'groovy' - - // Apply the application plugin to add support for building a CLI application. id 'application' // Code coverage of tests @@ -18,6 +16,9 @@ repositories { } dependencies { + implementation 'info.picocli:picocli:4.5.1' + annotationProcessor 'info.picocli:picocli-codegen:4.5.1' + implementation 'org.tomlj:tomlj:1.0.0' implementation 'org.codehaus.groovy:groovy-all:3.0.5' implementation 'com.squareup.okhttp3:okhttp:4.8.0' implementation 'org.influxdb:influxdb-java:2.19' @@ -32,7 +33,7 @@ dependencies { } application { - mainClassName = 'biz.nellemann.hmci.App' + mainClassName = 'biz.nellemann.hmci.Main' } test { @@ -68,7 +69,6 @@ ospackage { buildRpm { dependsOn startShadowScripts - //requires('java-1.8.0-openjdk-headless') os = LINUX } @@ -77,7 +77,6 @@ buildDeb { requires('default-jre-headless') } - jacoco { toolVersion = "0.8.5" } @@ -103,22 +102,16 @@ jacocoTestCoverageVerification { } check.dependsOn jacocoTestCoverageVerification - -processResources.dependsOn.add("versionFile") -versionFile { - // Path to the file to be written - file = new File(project.buildDir, 'resources/main/version.properties') -} - jar { manifest { attributes( - 'Built-By' : System.properties['user.name'], - 'Build-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ss.SSSZ").toString(), - 'Build-Revision' : versioning.info.commit, 'Created-By' : "Gradle ${gradle.gradleVersion}", + 'Build-OS' : "${System.properties['os.name']} ${System.properties['os.arch']} ${System.properties['os.version']}", 'Build-Jdk' : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']})", - 'Build-OS' : "${System.properties['os.name']} ${System.properties['os.arch']} ${System.properties['os.version']}" + 'Build-User' : System.properties['user.name'], + 'Build-Version' : versioning.info.tag ?: (versioning.info.branch + "-" + versioning.info.build), + 'Build-Revision' : versioning.info.commit, + 'Build-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ss.SSSZ").toString(), ) } } diff --git a/src/main/groovy/biz/nellemann/hmci/App.groovy b/src/main/groovy/biz/nellemann/hmci/App.groovy deleted file mode 100644 index 677f7d2..0000000 --- a/src/main/groovy/biz/nellemann/hmci/App.groovy +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Copyright 2020 Mark Nellemann - * - * 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 biz.nellemann.hmci - -import groovy.cli.picocli.CliBuilder -import groovy.cli.picocli.OptionAccessor -import groovy.util.logging.Slf4j - -@Slf4j -class App implements Runnable { - - final ConfigObject configuration - final Integer refreshEverySec - final Integer rescanHmcEvery - - InfluxClient influxClient - Map hmcClients = new HashMap<>() - Map systems = new HashMap() - Map partitions = new HashMap() - - - App(ConfigObject configuration) { - this.configuration = configuration - log.debug configuration.toString() - - refreshEverySec = (Integer)configuration.get('hmci.refresh') ?: 60 - rescanHmcEvery = (Integer)configuration.get('hmci.rescan') ?: 15 - - String influxUrl = configuration.get('influx')['url'] - String influxUsername = configuration.get('influx')['username'] - String influxPassword = configuration.get('influx')['password'] - String influxDatabase = configuration.get('influx')['database'] - - try { - influxClient = new InfluxClient(influxUrl, influxUsername, influxPassword, influxDatabase) - influxClient.login() - } catch(Exception e) { - System.exit(1) - } - - // Initial scan - discover() - - run() - } - - - void discover() { - - configuration.get('hmc').each { Object key, Object hmc -> - if(!hmcClients?.containsKey(key)) { - log.info("Adding HMC: " + hmc.toString()) - String hmcKey = key - String hmcUrl = hmc['url'] - String hmcUsername = hmc['username'] - String hmcPassword = hmc['password'] - Boolean hmcUnsafe = hmc['unsafe'] - HmcClient hmcClient = new HmcClient(hmcKey, hmcUrl, hmcUsername, hmcPassword, hmcUnsafe) - hmcClients.put(hmcKey, hmcClient) - } - } - - hmcClients.each { hmcId, hmcClient -> - - - try { - hmcClient.login() - hmcClient.getManagedSystems().each { systemId, system -> - - // Add to list of known systems - systems.putIfAbsent(systemId, system) - - // Get LPAR's for this system - hmcClient.getLogicalPartitionsForManagedSystem(system).each { partitionId, partition -> - - // Add to list of known partitions - partitions.putIfAbsent(partitionId, partition) - } - } - } catch(Exception e) { - log.error("discover() - " + hmcId + " error: " + e.message) - //hmcClients.remove(hmcId) - } - - } - - } - - - void getMetricsForSystems() { - - try { - - systems.each {systemId, system -> - - HmcClient hmcClient = hmcClients.get(system.hmcId) - - // Get and process metrics for this system - String tmpJsonString = hmcClient.getPcmDataForManagedSystem(system) - if(tmpJsonString && !tmpJsonString.empty) { - system.processMetrics(tmpJsonString) - } - - } - - } catch(Exception e) { - log.error(e.message) - } - - } - - - void getMetricsForPartitions() { - - try { - - // Get LPAR's for this system - partitions.each { partitionId, partition -> - - HmcClient hmcClient = hmcClients.get(partition.system.hmcId) - - // Get and process metrics for this partition - String tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition) - if(tmpJsonString2 && !tmpJsonString2.empty) { - partition.processMetrics(tmpJsonString2) - } - - } - - } catch(Exception e) { - log.error(e.message) - } - } - - - void writeMetricsForManagedSystems() { - systems.each {systemId, system -> - influxClient.writeManagedSystem(system) - } - } - - - void writeMetricsForLogicalPartitions() { - partitions.each {partitionId, partition -> - influxClient.writeLogicalPartition(partition) - } - } - - - static String getVersion() { - URL url = getClass().getResource("/version.properties"); - if (url == null) { - return "No version.txt file found in the classpath." - } - Properties properties = new Properties(); - properties.load(url.openStream()); - return properties.getProperty("VERSION_GRADLE") + "-" + properties.getProperty("VERSION_BUILD") - } - - - static void main(String... args) { - - def cli = new CliBuilder(name: "hmci") - cli.h(longOpt: 'help', usageHelp: true, 'display usage information') - cli.v(longOpt: 'version', versionHelp: true, 'display version information') - cli.c(longOpt: 'config', args: 1, required: true, paramLabel: "FILE", defaultValue: '/etc/hmci.groovy', 'configuration file') - - OptionAccessor options = cli.parse(args) - if (options.h) { - cli.usage() - return - } - - if(options.v) { - println("Version " + getVersion()) - return - } - - ConfigObject configuration - if(options.c) { - - File configurationFile = new File((String)options.config) - if(!configurationFile.exists()) { - println("Error - No configuration file found at: " + configurationFile.toString()) - System.exit(1) - } - - configuration = new ConfigSlurper("development").parse(configurationFile.toURI().toURL()); - } - - if(configuration == null || configuration.isEmpty()) { - println("Error - Empty or faulty configuration") - System.exit(1) - } - - new App(configuration) - } - - - @Override - void run() { - - log.debug("run()") - - boolean keepRunning = true - int executions = 0 - - while(keepRunning) { - - try { - getMetricsForSystems() - getMetricsForPartitions() - - writeMetricsForManagedSystems() - writeMetricsForLogicalPartitions() - influxClient.writeBatchPoints() - - // Refresh HMC's - if(executions > rescanHmcEvery) { - executions = 0 - discover() - } - } catch(Exception e) { - log.error(e.message, e) - } - - executions++ - Thread.sleep(refreshEverySec * 1000) - } - - } - -} diff --git a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy b/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy index 9e19aa4..27a6d3c 100644 --- a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy +++ b/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy @@ -15,6 +15,9 @@ */ package biz.nellemann.hmci +import biz.nellemann.hmci.Configuration.HmcObject +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import groovy.xml.XmlSlurper import okhttp3.MediaType @@ -34,6 +37,7 @@ import java.security.cert.CertificateException import java.security.cert.X509Certificate; @Slf4j +@CompileStatic class HmcClient { private final MediaType MEDIA_TYPE_IBM_XML_LOGIN = MediaType.parse("application/vnd.ibm.powervm.web+xml; type=LogonRequest"); @@ -48,18 +52,21 @@ class HmcClient { protected String authToken private final OkHttpClient client - HmcClient(String hmcId, String baseUrl, String username, String password, Boolean unsafe = false) { - this.hmcId = hmcId - this.baseUrl = baseUrl - this.username = username - this.password = password - this.unsafe = unsafe + + HmcClient(HmcObject configHmc) { + + this.hmcId = configHmc.name + this.baseUrl = configHmc.url + this.username = configHmc.username + this.password = configHmc.password + this.unsafe = configHmc.unsafe if(unsafe) { this.client = getUnsafeOkHttpClient() } else { this.client = new OkHttpClient() } + } @@ -69,12 +76,15 @@ class HmcClient { * * @throws IOException */ + //@CompileDynamic void login(Boolean force = false) throws IOException { if(authToken && !force) { return } + log.info("Connecting to HMC - " + baseUrl); + String payload = """\ @@ -96,7 +106,7 @@ class HmcClient { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); // Get response body and parse - String responseBody = response.body.string() + String responseBody = response.body().string(); response.body().close() def xml = new XmlSlurper().parseText(responseBody) @@ -144,6 +154,7 @@ class HmcClient { * * @return */ + @CompileDynamic Map getManagedSystems() { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl)) Response response = getResponse(url) @@ -185,6 +196,7 @@ class HmcClient { * @param UUID of managed system * @return */ + @CompileDynamic Map getLogicalPartitionsForManagedSystem(ManagedSystem system) { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id)) Response response = getResponse(url) @@ -225,6 +237,7 @@ class HmcClient { * @param systemId * @return */ + @CompileDynamic String getPcmDataForManagedSystem(ManagedSystem system) { log.debug("getPcmDataForManagedSystem() - " + system.id) URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, system.id)) @@ -257,6 +270,7 @@ class HmcClient { * @param partitionId * @return */ + @CompileDynamic String getPcmDataForLogicalPartition(LogicalPartition partition) { log.debug(String.format("getPcmDataForLogicalPartition() - %s @ %s", partition.id, partition.system.id)) @@ -305,6 +319,7 @@ class HmcClient { * @param url * @return */ + //@CompileDynamic private Response getResponse(URL url, Integer retry = 0) { if(responseErrors > 2) { @@ -324,18 +339,18 @@ class HmcClient { if (!response.isSuccessful()) { response.body().close() - if(response.code == 401) { + if(response.code() == 401) { login(true) return getResponse(url, retry++) } if(retry < 2) { - log.warn("getResponse() - Retrying due to unexpected response: " + response.code) + log.warn("getResponse() - Retrying due to unexpected response: " + response.code()) return getResponse(url, retry++) } - log.error("getResponse() - Unexpected response: " + response.code) - throw new IOException("getResponse() - Unexpected response: " + response.code) + log.error("getResponse() - Unexpected response: " + response.code()) + throw new IOException("getResponse() - Unexpected response: " + response.code()) }; return response diff --git a/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy b/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy index e15854c..04a21d2 100644 --- a/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy +++ b/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy @@ -13,63 +13,74 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package biz.nellemann.hmci +package biz.nellemann.hmci; -import groovy.util.logging.Slf4j -import org.influxdb.BatchOptions -import org.influxdb.InfluxDB -import org.influxdb.InfluxDBFactory -import org.influxdb.dto.BatchPoints -import org.influxdb.dto.Point -import org.influxdb.dto.Query +import biz.nellemann.hmci.Configuration.InfluxObject +import groovy.transform.CompileStatic; +import org.influxdb.BatchOptions; +import org.influxdb.InfluxDB; +import org.influxdb.InfluxDBFactory; +import org.influxdb.dto.BatchPoints; +import org.influxdb.dto.Point; +import org.influxdb.dto.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.time.Instant -import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeUnit; -@Slf4j +@CompileStatic class InfluxClient { - final String url - final String username - final String password - final String database + private final static Logger log = LoggerFactory.getLogger(InfluxClient.class); - InfluxDB influxDB - BatchPoints batchPoints + final private String url; + final private String username; + final private String password; + final private String database; + + private InfluxDB influxDB; + private BatchPoints batchPoints; - InfluxClient(String url, String username, String password, String database) { - this.url = url - this.username = username - this.password = password - this.database = database + InfluxClient(InfluxObject config) { + this.url = config.url; + this.username = config.username; + this.password = config.password; + this.database = config.database; } - void login() { - if(!influxDB) { - try { - influxDB = InfluxDBFactory.connect(url, username, password); - createDatabase() + void login() throws Exception { - // Enable batch writes to get better performance. - //BatchOptions options = BatchOptions.DEFAULTS.actions(300).flushDuration(500); - influxDB.enableBatch(BatchOptions.DEFAULTS); - //influxDB.setLogLevel(InfluxDB.LogLevel.BASIC); + if(influxDB != null) { + return + } - batchPoints = BatchPoints.database(database).precision(TimeUnit.SECONDS).build(); + try { + log.info("Connecting to InfluxDB - " + url); + influxDB = InfluxDBFactory.connect(url, username, password); + createDatabase(); - } catch(Exception e) { - log.error(e.message) - throw new Exception(e) - } + // Enable batch writes to get better performance. + //BatchOptions options = BatchOptions.DEFAULTS.actions(300).flushDuration(500); + influxDB.enableBatch(BatchOptions.DEFAULTS); + //influxDB.setLogLevel(InfluxDB.LogLevel.BASIC); + + batchPoints = BatchPoints.database(database).precision(TimeUnit.SECONDS).build(); + + } catch(Exception e) { + log.error(e.getMessage()); + throw new Exception(e); } } void logoff() { - influxDB?.close(); - influxDB = null + if(influxDB != null) { + influxDB.close(); + } + influxDB = null; } @@ -81,13 +92,13 @@ class InfluxClient { void writeBatchPoints() { - log.debug("writeBatchPoints()") + log.debug("writeBatchPoints()"); try { influxDB.write(batchPoints); } catch(Exception e) { - log.error("writeBatchPoints() error - " + e.message) - logoff() - login() + log.error("writeBatchPoints() error - " + e.getMessage()); + logoff(); + login(); } } @@ -101,81 +112,81 @@ class InfluxClient { void writeManagedSystem(ManagedSystem system) { if(system.metrics == null) { - log.warn("writeManagedSystem() - null metrics, skipping") - return + log.warn("writeManagedSystem() - null metrics, skipping"); + return; } - Instant timestamp = system.getTimestamp() - if(!timestamp) { - log.warn("writeManagedSystem() - no timestamp, skipping") - return + Instant timestamp = system.getTimestamp(); + if(timestamp == null) { + log.warn("writeManagedSystem() - no timestamp, skipping"); + return; } //BatchPoints batchPoints = BatchPoints.database(database).build(); - getSystemMemory(system, timestamp).each { - batchPoints.point(it) - } + getSystemMemory(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemProcessor(system, timestamp).each { - batchPoints.point(it) - } + getSystemProcessor(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemSharedProcessorPools(system, timestamp).each { - batchPoints.point(it) - } + getSystemSharedProcessorPools(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemSharedAdapters(system, timestamp).each { - batchPoints.point(it) - } + getSystemSharedAdapters(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemFiberChannelAdapters(system, timestamp).each { - batchPoints.point(it) - } + getSystemFiberChannelAdapters(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemGenericPhysicalAdapters(system, timestamp).each { - batchPoints.point(it) - } + getSystemGenericPhysicalAdapters(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getSystemGenericVirtualAdapters(system, timestamp).each { - batchPoints.point(it) - } + getSystemGenericVirtualAdapters(system, timestamp).forEach( it -> { + batchPoints.point(it); + }); } private static List getSystemMemory(ManagedSystem system, Instant timestamp) { - List metrics = system.getMemoryMetrics() - return processMeasurementMap(metrics, timestamp, "SystemMemory") + List metrics = system.getMemoryMetrics(); + return processMeasurementMap(metrics, timestamp, "SystemMemory"); } private static List getSystemProcessor(ManagedSystem system, Instant timestamp) { - List metrics = system.getProcessorMetrics() - return processMeasurementMap(metrics, timestamp, "SystemProcessor") + List metrics = system.getProcessorMetrics(); + return processMeasurementMap(metrics, timestamp, "SystemProcessor"); } private static List getSystemSharedProcessorPools(ManagedSystem system, Instant timestamp) { - List metrics = system.getSharedProcessorPools() - return processMeasurementMap(metrics, timestamp, "SystemSharedProcessorPool") + List metrics = system.getSharedProcessorPools(); + return processMeasurementMap(metrics, timestamp, "SystemSharedProcessorPool"); } private static List getSystemSharedAdapters(ManagedSystem system, Instant timestamp) { - List metrics = system.getSystemSharedAdapters() - return processMeasurementMap(metrics, timestamp, "SystemSharedAdapters") + List metrics = system.getSystemSharedAdapters(); + return processMeasurementMap(metrics, timestamp, "SystemSharedAdapters"); } private static List getSystemFiberChannelAdapters(ManagedSystem system, Instant timestamp) { - List metrics = system.getSystemFiberChannelAdapters() - return processMeasurementMap(metrics, timestamp, "SystemFiberChannelAdapters") + List metrics = system.getSystemFiberChannelAdapters(); + return processMeasurementMap(metrics, timestamp, "SystemFiberChannelAdapters"); } private static List getSystemGenericPhysicalAdapters(ManagedSystem system, Instant timestamp) { - List metrics = system.getSystemGenericPhysicalAdapters() - return processMeasurementMap(metrics, timestamp, "SystemGenericPhysicalAdapters") + List metrics = system.getSystemGenericPhysicalAdapters(); + return processMeasurementMap(metrics, timestamp, "SystemGenericPhysicalAdapters"); } private static List getSystemGenericVirtualAdapters(ManagedSystem system, Instant timestamp) { - List metrics = system.getSystemGenericVirtualAdapters() - return processMeasurementMap(metrics, timestamp, "SystemGenericVirtualAdapters") + List metrics = system.getSystemGenericVirtualAdapters(); + return processMeasurementMap(metrics, timestamp, "SystemGenericVirtualAdapters"); } @@ -186,64 +197,64 @@ class InfluxClient { void writeLogicalPartition(LogicalPartition partition) { if(partition.metrics == null) { - log.warn("writeLogicalPartition() - null metrics, skipping") - return + log.warn("writeLogicalPartition() - null metrics, skipping"); + return; } - Instant timestamp = partition.getTimestamp() - if(!timestamp) { - log.warn("writeLogicalPartition() - no timestamp, skipping") - return + Instant timestamp = partition.getTimestamp(); + if(timestamp == null) { + log.warn("writeLogicalPartition() - no timestamp, skipping"); + return; } //BatchPoints batchPoints = BatchPoints.database(database).build(); - getPartitionAffinityScore(partition, timestamp).each { - batchPoints.point(it) - } + getPartitionAffinityScore(partition, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getPartitionMemory(partition, timestamp).each { - batchPoints.point(it) - } + getPartitionMemory(partition, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getPartitionProcessor(partition, timestamp).each { - batchPoints.point(it) - } + getPartitionProcessor(partition, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getPartitionVirtualEthernetAdapter(partition, timestamp).each { - batchPoints.point(it) - } + getPartitionVirtualEthernetAdapter(partition, timestamp).forEach( it -> { + batchPoints.point(it); + }); - getPartitionVirtualFiberChannelAdapter(partition, timestamp).each { - batchPoints.point(it) - } + getPartitionVirtualFiberChannelAdapter(partition, timestamp).forEach( it -> { + batchPoints.point(it); + }); //influxDB.write(batchPoints); } private static List getPartitionAffinityScore(LogicalPartition partition, Instant timestamp) { - List metrics = partition.getAffinityScore() - return processMeasurementMap(metrics, timestamp, "PartitionAffinityScore") + List metrics = partition.getAffinityScore(); + return processMeasurementMap(metrics, timestamp, "PartitionAffinityScore"); } private static List getPartitionMemory(LogicalPartition partition, Instant timestamp) { - List metrics = partition.getMemoryMetrics() - return processMeasurementMap(metrics, timestamp, "PartitionMemory") + List metrics = partition.getMemoryMetrics(); + return processMeasurementMap(metrics, timestamp, "PartitionMemory"); } private static List getPartitionProcessor(LogicalPartition partition, Instant timestamp) { - List metrics = partition.getProcessorMetrics() - return processMeasurementMap(metrics, timestamp, "PartitionProcessor") + List metrics = partition.getProcessorMetrics(); + return processMeasurementMap(metrics, timestamp, "PartitionProcessor"); } private static List getPartitionVirtualEthernetAdapter(LogicalPartition partition, Instant timestamp) { - List metrics = partition.getVirtualEthernetAdapterMetrics() - return processMeasurementMap(metrics, timestamp, "PartitionVirtualEthernetAdapters") + List metrics = partition.getVirtualEthernetAdapterMetrics(); + return processMeasurementMap(metrics, timestamp, "PartitionVirtualEthernetAdapters"); } private static List getPartitionVirtualFiberChannelAdapter(LogicalPartition partition, Instant timestamp) { - List metrics = partition.getVirtualFiberChannelAdaptersMetrics() - return processMeasurementMap(metrics, timestamp, "PartitionVirtualFiberChannelAdapters") + List metrics = partition.getVirtualFiberChannelAdaptersMetrics(); + return processMeasurementMap(metrics, timestamp, "PartitionVirtualFiberChannelAdapters"); } @@ -252,33 +263,34 @@ class InfluxClient { Shared */ - private static List processMeasurementMap(List listOfMaps, Instant timestamp, String measurement) { + private static List processMeasurementMap(List measurements, Instant timestamp, String measurement) { - List list = new ArrayList<>() - - listOfMaps.each { map -> + List listOfPoints = new ArrayList<>(); + measurements.forEach( m -> { // Iterate fields - map.get("fields").each { String fieldName, BigDecimal fieldValue -> + //Map fieldsMap = m.get("fields"); + m.fields.forEach((fieldName, fieldValue) -> { log.debug("processMeasurementMap() " + measurement + " - fieldName: " + fieldName + ", fieldValue: " + fieldValue) Point.Builder builder = Point.measurement(measurement) .time(timestamp.toEpochMilli(), TimeUnit.MILLISECONDS) .tag("name", fieldName) - .addField("value", fieldValue) + .addField("value", fieldValue); // For each field, we add all tags - map.get("tags").each { String tagName, String tagValue -> - builder.tag(tagName, tagValue) - log.debug("processMeasurementMap() " + measurement + " - tagName: " + tagName + ", tagValue: " + tagValue) - } + //Map tagsMap = m.get("tags"); + m.tags.forEach((tagName, tagValue) -> { + builder.tag(tagName, tagValue); + log.debug("processMeasurementMap() " + measurement + " - tagName: " + tagName + ", tagValue: " + tagValue); + }); - list.add(builder.build()) - } + listOfPoints.add(builder.build()); + }); - } + }); - return list + return listOfPoints; } diff --git a/src/main/groovy/biz/nellemann/hmci/Insights.groovy b/src/main/groovy/biz/nellemann/hmci/Insights.groovy new file mode 100644 index 0000000..9334bed --- /dev/null +++ b/src/main/groovy/biz/nellemann/hmci/Insights.groovy @@ -0,0 +1,176 @@ +/** + * Copyright 2020 Mark Nellemann + * + * 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 biz.nellemann.hmci + +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j; + +@Slf4j +@CompileStatic +class Insights { + + final Configuration configuration; + + InfluxClient influxClient; + Map hmcClients = new HashMap<>(); + Map systems = new HashMap(); + Map partitions = new HashMap(); + + + Insights(Configuration configuration) { + this.configuration = configuration; + + try { + influxClient = new InfluxClient(configuration.influx); + influxClient.login(); + } catch(Exception e) { + System.exit(1); + } + + // Initial scan + discover(); + } + + + void discover() { + + configuration.hmc.forEach( configHmc -> { + if(!hmcClients?.containsKey(configHmc.name)) { + log.debug("Adding HMC: " + configHmc.toString()) + HmcClient hmcClient = new HmcClient(configHmc) + hmcClients.put(configHmc.name, hmcClient) + } + }); + + hmcClients.forEach(( hmcId, hmcClient) -> { + + try { + hmcClient.login() + hmcClient.getManagedSystems().each { systemId, system -> + + // Add to list of known systems + systems.putIfAbsent(systemId, system) + + // Get LPAR's for this system + hmcClient.getLogicalPartitionsForManagedSystem(system).forEach((partitionId, partition) -> { + + // Add to list of known partitions + partitions.putIfAbsent(partitionId, partition) + }); + } + } catch(Exception e) { + log.error("discover() - " + hmcId + " error: " + e.message) + //hmcClients.remove(hmcId) + } + + }); + + } + + + void getMetricsForSystems() { + + try { + + systems.forEach((systemId, system) -> { + + HmcClient hmcClient = hmcClients.get(system.hmcId) + + // Get and process metrics for this system + String tmpJsonString = hmcClient.getPcmDataForManagedSystem(system) + if(tmpJsonString && !tmpJsonString.empty) { + system.processMetrics(tmpJsonString) + } + + }); + + } catch(Exception e) { + log.error(e.message) + } + + } + + + void getMetricsForPartitions() { + + try { + + // Get LPAR's for this system + partitions.forEach((partitionId, partition) -> { + + HmcClient hmcClient = hmcClients.get(partition.system.hmcId) + + // Get and process metrics for this partition + String tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition) + if(tmpJsonString2 && !tmpJsonString2.empty) { + partition.processMetrics(tmpJsonString2) + } + + }); + + } catch(Exception e) { + log.error(e.message) + } + } + + + void writeMetricsForManagedSystems() { + systems.forEach((systemId, system) -> { + influxClient.writeManagedSystem(system) + }); + } + + + void writeMetricsForLogicalPartitions() { + partitions.each {partitionId, partition -> + influxClient.writeLogicalPartition(partition) + } + } + + + void run() { + + log.debug("run()") + + boolean keepRunning = true + int executions = 0 + + while(keepRunning) { + + try { + getMetricsForSystems() + getMetricsForPartitions() + + writeMetricsForManagedSystems() + writeMetricsForLogicalPartitions() + influxClient.writeBatchPoints() + + // Refresh HMC's + if(executions > configuration.rescan) { + executions = 0 + discover() + } + } catch(Exception e) { + log.error(e.message, e) + } + + executions++ + Thread.sleep(configuration.refresh * 1000) + } + + } + +} diff --git a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy b/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy index 98c4ab5..9dbb073 100644 --- a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy +++ b/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy @@ -15,9 +15,12 @@ */ package biz.nellemann.hmci +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @Slf4j +@CompileStatic class LogicalPartition extends MetaSystem { public String id @@ -36,64 +39,68 @@ class LogicalPartition extends MetaSystem { return "[${id}] ${name} (${type})" } + @CompileDynamic + List getAffinityScore() { - List getAffinityScore() { - - List list = new ArrayList<>() - Map map = new HashMap() + List list = new ArrayList<>() + //Map map = new HashMap() HashMap tagsMap = [ system: system.name, partition: name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getAffinityScore() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ affinityScore: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.affinityScore, ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getAffinityScore() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); return list } - List getMemoryMetrics() { + @CompileDynamic + List getMemoryMetrics() { - List list = new ArrayList<>() - Map map = new HashMap() + List list = new ArrayList<>() + //Map map = new HashMap() HashMap tagsMap = [ system: system.name, partition: name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ logicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.logicalMem?.first(), backedPhysicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.backedPhysicalMem?.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + return list } + @CompileDynamic + List getProcessorMetrics() { - List getProcessorMetrics() { - - List list = new ArrayList<>() - Map map = new HashMap() + List list = new ArrayList<>() + //Map map = new HashMap() HashMap tagsMap = [ system: system.name, partition: name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -109,19 +116,21 @@ class LogicalPartition extends MetaSystem { timePerInstructionExecution: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timeSpentWaitingForDispatch?.first(), timeSpentWaitingForDispatch: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timePerInstructionExecution?.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + return list } + @CompileDynamic + List getVirtualEthernetAdapterMetrics() { - List getVirtualEthernetAdapterMetrics() { - - List list = new ArrayList<>() + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.network?.virtualEthernetAdapters?.each { - Map map = new HashMap() + //Map map = new HashMap() HashMap tagsMap = [ system: system.name, @@ -131,7 +140,7 @@ class LogicalPartition extends MetaSystem { vlanId: it.vlanId as String, vswitchId: it.vswitchId as String, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getVirtualEthernetAdapterMetrics() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -140,10 +149,11 @@ class LogicalPartition extends MetaSystem { receivedBytes: it.receivedBytes.first(), sentBytes: it.sentBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getVirtualEthernetAdapterMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); } return list @@ -151,11 +161,12 @@ class LogicalPartition extends MetaSystem { //PartitionVirtualFiberChannelAdapters - List getVirtualFiberChannelAdaptersMetrics() { + @CompileDynamic + List getVirtualFiberChannelAdaptersMetrics() { - List list = new ArrayList<>() + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.storage?.virtualFiberChannelAdapters?.each { - Map map = new HashMap() + //Map map = new HashMap() HashMap tagsMap = [ system: system.name, @@ -163,7 +174,7 @@ class LogicalPartition extends MetaSystem { viosId: it.viosId as String, wwpn: it.wwpn, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getVirtualFiberChannelAdaptersMetrics() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -171,10 +182,11 @@ class LogicalPartition extends MetaSystem { writeBytes: it.writeBytes.first(), readBytes: it.readBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getVirtualFiberChannelAdaptersMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); } return list diff --git a/src/main/groovy/biz/nellemann/hmci/Main.groovy b/src/main/groovy/biz/nellemann/hmci/Main.groovy new file mode 100644 index 0000000..0994d74 --- /dev/null +++ b/src/main/groovy/biz/nellemann/hmci/Main.groovy @@ -0,0 +1,59 @@ +/* + Copyright 2020 mark.nellemann@gmail.com + + 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 biz.nellemann.hmci + +import groovy.transform.CompileStatic; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import java.util.concurrent.Callable; + +@CompileStatic +@Command(name = "hmci", + mixinStandardHelpOptions = true, + description = "HMC Insights.", + versionProvider = biz.nellemann.hmci.VersionProvider.class) +public class Main implements Callable { + + private final static Logger log = LoggerFactory.getLogger(Main.class); + + @CommandLine.Option(names = ["-c", "--conf"], description = "Configuration file [default: '/etc/hmci.toml'].") + private String configurationFile = "/etc/hmci.toml"; + + public static void main(String... args) { + int exitCode = new CommandLine(new Main()).execute(args); + System.exit(exitCode); + } + + + @Override + public Integer call() throws IOException { + + File file = new File(configurationFile); + if(!file.exists()) { + System.err.println("Error - No configuration file found at: " + file.toString()); + return -1; + } + + Configuration configuration = new Configuration(configurationFile); + Insights insights = new Insights(configuration); + insights.run(); + + return 0; + } + +} diff --git a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy b/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy index c339519..0d5ce1b 100644 --- a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy +++ b/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy @@ -15,10 +15,13 @@ */ package biz.nellemann.hmci +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @Slf4j +@CompileStatic class ManagedSystem extends MetaSystem { public final String hmcId @@ -43,40 +46,46 @@ class ManagedSystem extends MetaSystem { } - List getMemoryMetrics() { + @CompileDynamic + List getMemoryMetrics() { - List list = new ArrayList<>() - Map map = new HashMap() + List list = new ArrayList<>() + //Map map = new HashMap() HashMap tagsMap = [ system: name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ - totalMem: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.totalMem?.first(), - availableMem: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.availableMem?.first(), - configurableMem: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.configurableMem?.first(), - assignedMemToLpars: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.assignedMemToLpars?.first(), + Map fieldsMap = [ + "totalMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.totalMem?.first(), + "availableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.availableMem?.first(), + "configurableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.configurableMem?.first(), + "assignedMemToLpars": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.assignedMemToLpars?.first(), ] - map.put("fields", fieldsMap) + + //map.put("fields", fieldsMap) log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement) + return list } - List getProcessorMetrics() { + @CompileDynamic + List getProcessorMetrics() { - List list = new ArrayList<>() - Map map = new HashMap() + List list = new ArrayList<>() + //Map map = new HashMap<>() HashMap tagsMap = [ system: name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) + //measurement.tags = tagsMap; log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -85,55 +94,62 @@ class ManagedSystem extends MetaSystem { availableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.availableProcUnits?.first(), configurableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.configurableProcUnits?.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) + //measurement.fields = fieldsMap; log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) - list.add(map) + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement) + return list } - List getSharedProcessorPools() { + @CompileDynamic + List getSharedProcessorPools() { - List list = new ArrayList<>() + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.serverUtil?.sharedProcessorPool?.each { - Map map = new HashMap() + //Map map = new HashMap() HashMap tagsMap = [ system: name, pool: it.name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ assignedProcUnits: it.assignedProcUnits.first(), availableProcUnits: it.availableProcUnits.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) log.debug("getSharedProcessorPools() - fields: " + fieldsMap.toString()) - list.add(map) - + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement) } return list } - List getSystemSharedAdapters() { + @CompileDynamic + List getSystemSharedAdapters() { - List list = new ArrayList<>() + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each {vios -> vios.network.sharedAdapters.each { - Map map = new HashMap() + //Map map = new HashMap() + Measurement measurement = new Measurement(); HashMap tagsMap = [ system: name, type: it.type, vios: vios.name, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) + measurement.tags = tagsMap; log.debug("getSystemSharedAdapters() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -141,25 +157,27 @@ class ManagedSystem extends MetaSystem { receivedBytes: it.receivedBytes.first(), transferredBytes: it.transferredBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; log.debug("getSystemSharedAdapters() - fields: " + fieldsMap.toString()) - list.add(map) + list.add(measurement) } - } return list } - List getSystemFiberChannelAdapters() { + @CompileDynamic + List getSystemFiberChannelAdapters() { - List list = new ArrayList<>() + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> log.debug("getSystemFiberChannelAdapters() - VIOS: " + vios.name) vios.storage?.fiberChannelAdapters?.each { - Map map = new HashMap() + //HashMap map = new HashMap<>() + Measurement measurement = new Measurement(); HashMap tagsMap = [ id: it.id, @@ -168,7 +186,8 @@ class ManagedSystem extends MetaSystem { vios: vios.name, device: it.physicalLocation, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) + measurement.tags = tagsMap; log.debug("getSystemFiberChannelAdapters() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -176,23 +195,25 @@ class ManagedSystem extends MetaSystem { readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; log.debug("getSystemFiberChannelAdapters() - fields: " + fieldsMap.toString()) - list.add(map) + list.add(measurement) } - } return list } - List getSystemGenericPhysicalAdapters() { - List list = new ArrayList<>() + @CompileDynamic + List getSystemGenericPhysicalAdapters() { + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> vios.storage?.genericPhysicalAdapters?.each { - Map map = new HashMap() + //Map map = new HashMap() + Measurement measurement = new Measurement(); HashMap tagsMap = [ id: it.id, @@ -200,7 +221,8 @@ class ManagedSystem extends MetaSystem { vios: vios.name, device: it.physicalLocation, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) + measurement.tags = tagsMap; log.debug("getSystemGenericPhysicalAdapters() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -208,24 +230,25 @@ class ManagedSystem extends MetaSystem { readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; log.debug("getSystemGenericPhysicalAdapters() - fields: " + fieldsMap.toString()) - list.add(map) - + list.add(measurement) } - } return list } - List getSystemGenericVirtualAdapters() { - List list = new ArrayList<>() + @CompileDynamic + List getSystemGenericVirtualAdapters() { + List list = new ArrayList<>() metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> vios.storage?.genericVirtualAdapters?.each { - Map map = new HashMap() + //Map map = new HashMap() + Measurement measurement = new Measurement(); HashMap tagsMap = [ id: it.id, @@ -233,7 +256,8 @@ class ManagedSystem extends MetaSystem { vios: vios.name, device: it.physicalLocation, ] - map.put("tags", tagsMap) + //map.put("tags", tagsMap) + measurement.tags = tagsMap; log.debug("getSystemGenericVirtualAdapters() - tags: " + tagsMap.toString()) HashMap fieldsMap = [ @@ -241,13 +265,12 @@ class ManagedSystem extends MetaSystem { readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), ] - map.put("fields", fieldsMap) + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; log.debug("getSystemGenericVirtualAdapters() - fields: " + fieldsMap.toString()) - list.add(map) - + list.add(measurement); } - } return list diff --git a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy b/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy index 065a780..c73a24e 100644 --- a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy +++ b/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy @@ -17,6 +17,8 @@ package biz.nellemann.hmci import biz.nellemann.hmci.pcm.PcmData import groovy.json.JsonSlurper +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import java.time.Instant @@ -24,20 +26,22 @@ import java.time.format.DateTimeFormatter import java.time.format.DateTimeParseException @Slf4j +@CompileStatic abstract class MetaSystem { protected PcmData metrics + @CompileDynamic void processMetrics(String json) { - def pcmMap = new JsonSlurper().parseText(json) - metrics = new PcmData(pcmMap as Map) + Map pcmMap = new JsonSlurper().parseText(json) as Map + metrics = new PcmData(pcmMap) } - + @CompileDynamic Instant getTimestamp() { String timestamp = metrics.systemUtil.utilSamples.first().sampleInfo.timeStamp - Instant instant + Instant instant = null try { log.debug("getTimeStamp() - PMC Timestamp: " + timestamp) DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[XXX][X]"); diff --git a/src/main/java/biz/nellemann/hmci/Configuration.java b/src/main/java/biz/nellemann/hmci/Configuration.java new file mode 100644 index 0000000..215b93a --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/Configuration.java @@ -0,0 +1,161 @@ +package biz.nellemann.hmci; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tomlj.Toml; +import org.tomlj.TomlParseResult; +import org.tomlj.TomlTable; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class Configuration { + + private final static Logger log = LoggerFactory.getLogger(Configuration.class); + + final public Long refresh; + final public Long rescan; + final public InfluxObject influx; + final public List hmc; + + Configuration(String configurationFile) throws IOException { + + Path source = Paths.get(configurationFile); + TomlParseResult result = Toml.parse(source); + result.errors().forEach(error -> System.err.println(error.toString())); + //System.out.println(result.toJson()); + + if(result.contains("refresh")) { + refresh = result.getLong("refresh"); + } else { + refresh = 15l; + } + + if(result.contains("rescan")) { + rescan = result.getLong("rescan"); + } else { + rescan = 60l; + } + + hmc = getHmc(result); + influx = getInflux(result); + + } + + + List getHmc(TomlParseResult result) { + + ArrayList list = new ArrayList<>(); + + if(result.contains("hmc") && result.isTable("hmc")) { + TomlTable hmcTable = result.getTable("hmc"); + for(String key : hmcTable.keySet()) { + + HmcObject c = new HmcObject(); + c.name = key; + + if(hmcTable.contains(key+".url")) { + c.url = hmcTable.getString(key+".url"); + } + + if(hmcTable.contains(key+".username")) { + c.username = hmcTable.getString(key+".username"); + } + + if(hmcTable.contains(key+".password")) { + c.password = hmcTable.getString(key+".password"); + } + + if(hmcTable.contains(key+".unsafe")) { + c.unsafe = hmcTable.getBoolean(key+".unsafe"); + } else { + c.unsafe = false; + } + + list.add(c); + } + } + + return list; + } + + + InfluxObject getInflux(TomlParseResult result) { + + InfluxObject c = new InfluxObject(); + + if(result.contains("influx")) { + TomlTable t = result.getTable("influx"); + + if(t != null && t.contains("url")) { + c.url = t.getString("url"); + } + + if(t != null && t.contains("username")) { + c.username = t.getString("username"); + } + + if(t != null && t.contains("password")) { + c.password = t.getString("password"); + } + + if(t != null && t.contains("database")) { + c.database = t.getString("database"); + } + + } + + return c; + } + + + static class InfluxObject { + + String url = "http://localhost:8086"; + String username = "root"; + String password = ""; + String database = "hmci"; + + private boolean isValid = false; + + Boolean isValid() { + return isValid(); + } + + // TODO: Fixme + void validate() { + isValid = true; + } + + } + + + static class HmcObject { + + String name; + String url; + String username; + String password; + Boolean unsafe; + + private boolean isValid = false; + + Boolean isValid() { + return isValid(); + } + + // TODO: Fixme + void validate() { + isValid = true; + } + + @Override + public String toString() { + return name; + } + } + +} diff --git a/src/main/java/biz/nellemann/hmci/Measurement.java b/src/main/java/biz/nellemann/hmci/Measurement.java new file mode 100644 index 0000000..ad1bff9 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/Measurement.java @@ -0,0 +1,17 @@ +package biz.nellemann.hmci; + +import java.util.Map; + +public class Measurement { + + Map tags; + Map fields; + + Measurement() { + } + + Measurement(Map tags, Map fields) { + this.tags = tags; + this.fields = fields; + } +} diff --git a/src/main/java/biz/nellemann/hmci/VersionProvider.java b/src/main/java/biz/nellemann/hmci/VersionProvider.java new file mode 100644 index 0000000..dcd480f --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/VersionProvider.java @@ -0,0 +1,19 @@ +package biz.nellemann.hmci; + +import picocli.CommandLine; + +import java.io.IOException; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +class VersionProvider implements CommandLine.IVersionProvider { + + public String[] getVersion() throws IOException { + + Manifest manifest = new Manifest(getClass().getResourceAsStream("/META-INF/MANIFEST.MF")); + Attributes attrs = manifest.getMainAttributes(); + + return new String[] { "${COMMAND-FULL-NAME} " + attrs.getValue("Build-Version") }; + } + +} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index feefcff..c394543 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -3,7 +3,7 @@ - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{12} - %msg%n diff --git a/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy b/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy new file mode 100644 index 0000000..b88eb18 --- /dev/null +++ b/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy @@ -0,0 +1,30 @@ +package biz.nellemann.hmci + +import spock.lang.Specification + + +class ConfigurationTest extends Specification { + + String testConfigurationFile = new File(getClass().getResource('/hmci.toml').toURI()).absolutePath + + void "test parsing"() { + + when: + Configuration conf = new Configuration(testConfigurationFile); + + then: + conf != null + + } + + void "test lookup influx"() { + + when: + Configuration conf = new Configuration(testConfigurationFile); + + then: + conf != null + + } + +} diff --git a/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy b/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy index a29e1ad..49f265b 100644 --- a/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy @@ -12,7 +12,12 @@ class HmcClientTest extends Specification { def setup() { mockServer.start(); - hmc = new HmcClient("site", mockServer.url("/").toString(), "testUser", "testPassword") + Configuration.HmcObject configHmc = new Configuration.HmcObject() + configHmc.name = "site1" + configHmc.url = mockServer.url("/").toString() + configHmc.username = "testUser" + configHmc.password = "testPassword" + hmc = new HmcClient(configHmc) hmc.authToken = "blaBla" } diff --git a/src/test/groovy/biz/nellemann/hmci/AppTest.groovy b/src/test/groovy/biz/nellemann/hmci/InsightsTest.groovy similarity index 75% rename from src/test/groovy/biz/nellemann/hmci/AppTest.groovy rename to src/test/groovy/biz/nellemann/hmci/InsightsTest.groovy index ef9c7e7..241827a 100644 --- a/src/test/groovy/biz/nellemann/hmci/AppTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/InsightsTest.groovy @@ -5,6 +5,6 @@ package biz.nellemann.hmci import spock.lang.Specification -class AppTest extends Specification { - +class InsightsTest extends Specification { + } diff --git a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy index 0984707..3445c82 100644 --- a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy @@ -34,12 +34,12 @@ class LogicalPartitionTest extends Specification { when: lpar.processMetrics(testJson) - List listOfMaps = lpar.getMemoryMetrics() + List listOfMeasurements = lpar.getMemoryMetrics() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['logicalMem'] == 8192.000 - listOfMaps.first().get("tags")['partition'] == '9Flash01' + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['logicalMem'] == 8192.000 + listOfMeasurements.first().tags['partition'] == '9Flash01' } @@ -53,12 +53,12 @@ class LogicalPartitionTest extends Specification { when: lpar.processMetrics(testJson) - List listOfMaps = lpar.getProcessorMetrics() + List listOfMeasurements = lpar.getProcessorMetrics() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['utilizedProcUnits'] == 0.001 - listOfMaps.first().get("tags")['partition'] == '9Flash01' + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['utilizedProcUnits'] == 0.001 + listOfMeasurements.first().tags['partition'] == '9Flash01' } @@ -72,12 +72,12 @@ class LogicalPartitionTest extends Specification { when: lpar.processMetrics(testJson) - List listOfMaps = lpar.getVirtualEthernetAdapterMetrics() + List listOfMeasurements = lpar.getVirtualEthernetAdapterMetrics() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['receivedBytes'] == 276.467 - listOfMaps.first().get("tags")['sea'] == 'ent5' + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['receivedBytes'] == 276.467 + listOfMeasurements.first().tags['sea'] == 'ent5' } void "test getVirtualFiberChannelAdaptersMetrics"() { @@ -90,12 +90,12 @@ class LogicalPartitionTest extends Specification { when: lpar.processMetrics(testJson) - List listOfMaps = lpar.getVirtualFiberChannelAdaptersMetrics() + List listOfMeasurements = lpar.getVirtualFiberChannelAdaptersMetrics() then: - listOfMaps.size() == 4 - listOfMaps.first().get("fields")['writeBytes'] == 6690.133 - listOfMaps.first().get("tags")['viosId'] == '1' + listOfMeasurements.size() == 4 + listOfMeasurements.first().fields['writeBytes'] == 6690.133 + listOfMeasurements.first().tags['viosId'] == '1' } diff --git a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy index 115b78f..9f58ffc 100644 --- a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy @@ -33,11 +33,11 @@ class ManagedSystemTest extends Specification { when: system.processMetrics(testJson) - List listOfMaps = system.getMemoryMetrics() + List listOfMeasurements = system.getMemoryMetrics() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['totalMem'] == 1048576.000 + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['totalMem'] == 1048576.000 } void "test getProcessorMetrics"() { @@ -49,11 +49,11 @@ class ManagedSystemTest extends Specification { when: system.processMetrics(testJson) - List listOfMaps = system.getProcessorMetrics() + List listOfMeasurements = system.getProcessorMetrics() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['availableProcUnits'] == 16.000 + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['availableProcUnits'] == 16.000 } void "test getSystemSharedProcessorPools"() { @@ -65,11 +65,11 @@ class ManagedSystemTest extends Specification { when: system.processMetrics(testJson) - List listOfMaps = system.getSharedProcessorPools() + List listOfMeasurements = system.getSharedProcessorPools() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['assignedProcUnits'] == 23.767 + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['assignedProcUnits'] == 23.767 } void "test VIOS data"() { @@ -80,11 +80,11 @@ class ManagedSystemTest extends Specification { when: system.processMetrics(testJson) - List listOfMaps = system.getSharedProcessorPools() + List listOfMeasurements = system.getSharedProcessorPools() then: - listOfMaps.size() == 1 - listOfMaps.first().get("fields")['assignedProcUnits'] == 23.767 + listOfMeasurements.size() == 1 + listOfMeasurements.first().fields['assignedProcUnits'] == 23.767 } } diff --git a/src/test/resources/hmci.toml b/src/test/resources/hmci.toml new file mode 100644 index 0000000..a5c87f5 --- /dev/null +++ b/src/test/resources/hmci.toml @@ -0,0 +1,32 @@ +# HMCi Configuration + +# How often to query HMC's for data - in seconds +hmci.refresh = 30 + +# Rescan HMC's for new systems and partitions - every x refresh +hmci.rescan = 60 + +# InfluxDB to save metrics +[influx] +url = "http://localhost:8086" +username = "root" +password = "" +database = "hmci" + + +# One or more HMC's to query for data and metrics +[hmc] + + # HMC on our primary site + [hmc.site1] + url = "https://10.10.10.10:12443" + username = "hmci" + password = "hmcihmci" + unsafe = true # Ignore SSL cert. errors + + # Example + #[hmc.site2] + #url = "https://10.10.20.20:12443" + #username = "viewer" + #password = "someSecret" + #unsafe = false From 3f71aabd4e31d7c85a6409c215cf8d030597dd60 Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Fri, 9 Oct 2020 16:32:16 +0200 Subject: [PATCH 2/4] Refactoring work, replaced Groovy xml and json w. jsoup and moshi. --- build.gradle | 5 + .../biz/nellemann/hmci/HmcClient.groovy | 130 +++++++++--------- .../nellemann/hmci/LogicalPartition.groovy | 20 +-- .../biz/nellemann/hmci/ManagedSystem.groovy | 28 ++-- .../biz/nellemann/hmci/MetaSystem.groovy | 66 +++++++-- .../hmci/pcm/FiberChannelAdapter.groovy | 19 --- .../nellemann/hmci/pcm/GenericAdapter.groovy | 18 --- .../hmci/pcm/GenericPhysicalAdapters.groovy | 17 --- .../hmci/pcm/GenericVirtualAdapter.groovy | 18 --- .../biz/nellemann/hmci/pcm/LparMemory.groovy | 11 -- .../nellemann/hmci/pcm/LparProcessor.groovy | 23 ---- .../biz/nellemann/hmci/pcm/LparUtil.groovy | 21 --- .../biz/nellemann/hmci/pcm/Network.groovy | 10 -- .../biz/nellemann/hmci/pcm/PcmData.groovy | 10 -- .../hmci/pcm/PhysicalProcessorPool.groovy | 14 -- .../biz/nellemann/hmci/pcm/SampleInfo.groovy | 11 -- .../nellemann/hmci/pcm/ServerMemory.groovy | 13 -- .../nellemann/hmci/pcm/ServerProcessor.groovy | 13 -- .../biz/nellemann/hmci/pcm/ServerUtil.groovy | 13 -- .../nellemann/hmci/pcm/SharedAdapter.groovy | 19 --- .../hmci/pcm/SharedProcessorPool.groovy | 16 --- .../biz/nellemann/hmci/pcm/Storage.groovy | 14 -- .../biz/nellemann/hmci/pcm/SystemUtil.groovy | 11 -- .../biz/nellemann/hmci/pcm/UtilInfo.groovy | 18 --- .../biz/nellemann/hmci/pcm/UtilSample.groovy | 14 -- .../biz/nellemann/hmci/pcm/ViosUtil.groovy | 24 ---- .../hmci/pcm/VirtualEthernetAdapter.groovy | 27 ---- .../pcm/VirtualFiberChannelAdapter.groovy | 20 --- .../hmci/pcm/FiberChannelAdapter.java | 18 +++ .../nellemann/hmci/pcm/GenericAdapter.java | 17 +++ .../hmci/pcm/GenericPhysicalAdapters.java | 16 +++ .../hmci/pcm/GenericVirtualAdapter.java | 17 +++ .../biz/nellemann/hmci/pcm/LparMemory.java | 10 ++ .../biz/nellemann/hmci/pcm/LparProcessor.java | 22 +++ .../java/biz/nellemann/hmci/pcm/LparUtil.java | 18 +++ .../java/biz/nellemann/hmci/pcm/Network.java | 11 ++ .../java/biz/nellemann/hmci/pcm/PcmData.java | 7 + .../hmci/pcm/PhysicalProcessorPool.java | 13 ++ .../biz/nellemann/hmci/pcm/SampleInfo.java | 8 ++ .../biz/nellemann/hmci/pcm/ServerMemory.java | 12 ++ .../nellemann/hmci/pcm/ServerProcessor.java | 12 ++ .../biz/nellemann/hmci/pcm/ServerUtil.java | 12 ++ .../biz/nellemann/hmci/pcm/SharedAdapter.java | 18 +++ .../hmci/pcm/SharedProcessorPool.java | 15 ++ .../java/biz/nellemann/hmci/pcm/Storage.java | 13 ++ .../biz/nellemann/hmci/pcm/SystemUtil.java | 10 ++ .../java/biz/nellemann/hmci/pcm/UtilInfo.java | 17 +++ .../biz/nellemann/hmci/pcm/UtilSample.java | 13 ++ .../biz/nellemann/hmci/pcm/ViosMemory.java | 10 ++ .../java/biz/nellemann/hmci/pcm/ViosUtil.java | 16 +++ .../hmci/pcm/VirtualEthernetAdapter.java | 26 ++++ .../hmci/pcm/VirtualFiberChannelAdapter.java | 19 +++ 52 files changed, 505 insertions(+), 468 deletions(-) delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/FiberChannelAdapter.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/GenericAdapter.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/GenericVirtualAdapter.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/LparMemory.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/LparProcessor.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/LparUtil.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/Network.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/PcmData.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/PhysicalProcessorPool.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/SampleInfo.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/ServerMemory.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/ServerProcessor.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/ServerUtil.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/SharedAdapter.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/SharedProcessorPool.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/Storage.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/SystemUtil.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/UtilInfo.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/UtilSample.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/ViosUtil.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.groovy create mode 100644 src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/LparMemory.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/LparUtil.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/Network.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/PcmData.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/Storage.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/UtilSample.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java create mode 100644 src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java diff --git a/build.gradle b/build.gradle index 0146626..6af8634 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,10 @@ repositories { dependencies { implementation 'info.picocli:picocli:4.5.1' annotationProcessor 'info.picocli:picocli-codegen:4.5.1' + // implementation 'com.thoughtworks.xstream:xstream:1.4.13' + // https://mvnrepository.com/artifact/org.jsoup/jsoup + implementation 'org.jsoup:jsoup:1.13.1' + implementation 'com.squareup.moshi:moshi:1.11.0' implementation 'org.tomlj:tomlj:1.0.0' implementation 'org.codehaus.groovy:groovy-all:3.0.5' implementation 'com.squareup.okhttp3:okhttp:4.8.0' @@ -25,6 +29,7 @@ dependencies { implementation 'org.slf4j:slf4j-api:1.7.+' runtimeOnly 'ch.qos.logback:logback-classic:1.+' + testImplementation('org.spockframework:spock-core:2.0-M3-groovy-3.0') testImplementation("org.slf4j:slf4j-simple:1.7.+") testImplementation('com.squareup.okhttp3:mockwebserver:4.8.0') diff --git a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy b/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy index 27a6d3c..3f53f69 100644 --- a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy +++ b/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy @@ -16,25 +16,21 @@ package biz.nellemann.hmci import biz.nellemann.hmci.Configuration.HmcObject +import com.squareup.moshi.Moshi import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import groovy.xml.XmlSlurper -import okhttp3.MediaType -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.RequestBody -import okhttp3.Response +import okhttp3.* +import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import org.jsoup.select.Elements -import javax.net.ssl.HostnameVerifier -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLSession -import javax.net.ssl.SSLSocketFactory -import javax.net.ssl.TrustManager -import javax.net.ssl.X509TrustManager +import javax.net.ssl.* import java.security.SecureRandom import java.security.cert.CertificateException -import java.security.cert.X509Certificate; +import java.security.cert.X509Certificate @Slf4j @CompileStatic @@ -154,11 +150,11 @@ class HmcClient { * * @return */ - @CompileDynamic + //@CompileDynamic Map getManagedSystems() { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl)) Response response = getResponse(url) - String responseBody = response.body.string() + String responseBody = response.body().string() Map managedSystemsMap = new HashMap() // Do not try to parse empty response @@ -167,22 +163,24 @@ class HmcClient { return managedSystemsMap } - def feed = new XmlSlurper().parseText(responseBody) - feed?.entry?.each { entry -> - entry.content.each { content -> - content.ManagedSystem.each { system -> - ManagedSystem managedSystem = new ManagedSystem( - hmcId, - entry.id as String, - system.SystemName as String, - system.MachineTypeModelAndSerialNumber?.MachineType as String, - system.MachineTypeModelAndSerialNumber?.Model as String, - system.MachineTypeModelAndSerialNumber?.SerialNumber as String - ) - managedSystemsMap.put(managedSystem.id, managedSystem) - log.debug("getManagedSystems() - Found system: " + managedSystem.toString()) - } + try { + Document doc = Jsoup.parse(responseBody); + Elements managedSystems = doc.select("ManagedSystem|ManagedSystem") // doc.select("img[src$=.png]"); + for(Element el : managedSystems) { + ManagedSystem system = new ManagedSystem( + hmcId, + el.select("Metadata > Atom > AtomID").text() as String, + el.select("SystemName").text() as String, + el.select("MachineTypeModelAndSerialNumber > MachineType").text() as String, + el.select("MachineTypeModelAndSerialNumber > Model").text() as String, + el.select("MachineTypeModelAndSerialNumber > SerialNumber").text() as String, + ) + managedSystemsMap.put(system.id, system) + log.info("getManagedSystems() - Found system: " + system.toString()) } + + } catch(Exception e) { + log.warn("getManagedSystems() - xml parse error", e); } return managedSystemsMap @@ -196,11 +194,11 @@ class HmcClient { * @param UUID of managed system * @return */ - @CompileDynamic + //@CompileDynamic Map getLogicalPartitionsForManagedSystem(ManagedSystem system) { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id)) Response response = getResponse(url) - String responseBody = response.body.string() + String responseBody = response.body().string() Map partitionMap = new HashMap() {} // Do not try to parse empty response @@ -209,22 +207,22 @@ class HmcClient { return partitionMap } - def feed = new XmlSlurper().parseText(responseBody) - feed?.entry?.each { entry -> - //log.debug("Entry") - entry.content.each { content -> - //log.debug("Content") - content.LogicalPartition.each { partition -> - LogicalPartition logicalPartition = new LogicalPartition( - partition.PartitionUUID as String, - partition.PartitionName as String, - partition.PartitionType as String, - system - ) - partitionMap.put(logicalPartition.id, logicalPartition) - log.debug("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()) - } + try { + Document doc = Jsoup.parse(responseBody); + Elements logicalPartitions = doc.select("LogicalPartition|LogicalPartition") // doc.select("img[src$=.png]"); + for(Element el : logicalPartitions) { + LogicalPartition logicalPartition = new LogicalPartition( + el.select("PartitionUUID").text() as String, + el.select("PartitionName").text() as String, + el.select("PartitionType").text() as String, + system + ) + partitionMap.put(logicalPartition.id, logicalPartition) + log.info("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()) } + + } catch(Exception e) { + log.warn("getLogicalPartitionsForManagedSystem() - xml parse error", e); } return partitionMap @@ -237,12 +235,12 @@ class HmcClient { * @param systemId * @return */ - @CompileDynamic + //@CompileDynamic String getPcmDataForManagedSystem(ManagedSystem system) { log.debug("getPcmDataForManagedSystem() - " + system.id) URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, system.id)) Response response = getResponse(url) - String responseBody = response.body.string() + String responseBody = response.body().string() String jsonBody // Do not try to parse empty response @@ -251,13 +249,17 @@ class HmcClient { return jsonBody } - // Parse XML and fetch JSON link - def feed = new XmlSlurper().parseText(responseBody) - feed?.entry?.each { entry -> - String link = entry.link["@href"] - if(entry.category["@term"] == "ManagedSystem") { - jsonBody = getResponseBody(new URL(link)) + try { + Document doc = Jsoup.parse(responseBody); + Element entry = doc.select("entry").first(); + Element link = entry.select("link[href]").first(); + if(link.attr("type") == "application/json") { + String href = (String) link.attr("href"); + log.debug("getPcmDataForManagedSystem() - json url: " + href); + jsonBody = getResponseBody(new URL(href)); } + } catch(Exception e) { + log.warn("getPcmDataForManagedSystem() - xml parse error", e); } return jsonBody @@ -270,13 +272,13 @@ class HmcClient { * @param partitionId * @return */ - @CompileDynamic + //@CompileDynamic String getPcmDataForLogicalPartition(LogicalPartition partition) { log.debug(String.format("getPcmDataForLogicalPartition() - %s @ %s", partition.id, partition.system.id)) URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/LogicalPartition/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, partition.system.id, partition.id)) Response response = getResponse(url) - String responseBody = response.body.string() + String responseBody = response.body().string() String jsonBody // Do not try to parse empty response @@ -285,13 +287,17 @@ class HmcClient { return jsonBody } - // Parse XML and fetch JSON link - def feed = new XmlSlurper().parseText(responseBody) - feed?.entry?.each { entry -> - String link = entry.link["@href"] - if(entry.category["@term"] == "LogicalPartition") { - jsonBody = getResponseBody(new URL(link)) + try { + Document doc = Jsoup.parse(responseBody); + Element entry = doc.select("entry").first(); + Element link = entry.select("link[href]").first(); + if(link.attr("type") == "application/json") { + String href = (String) link.attr("href"); + log.debug("getPcmDataForLogicalPartition() - json url: " + href); + jsonBody = getResponseBody(new URL(href)); } + } catch(Exception e) { + log.warn("getPcmDataForLogicalPartition() - xml parse error", e); } return jsonBody diff --git a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy b/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy index 9dbb073..8f229a0 100644 --- a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy +++ b/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy @@ -52,9 +52,9 @@ class LogicalPartition extends MetaSystem { //map.put("tags", tagsMap) log.debug("getAffinityScore() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ affinityScore: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.affinityScore, - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getAffinityScore() - fields: " + fieldsMap.toString()) @@ -77,10 +77,10 @@ class LogicalPartition extends MetaSystem { //map.put("tags", tagsMap) log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ logicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.logicalMem?.first(), backedPhysicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.backedPhysicalMem?.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) @@ -103,7 +103,7 @@ class LogicalPartition extends MetaSystem { //map.put("tags", tagsMap) log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ utilizedProcUnits: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.utilizedProcUnits?.first(), maxVirtualProcessors: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.maxVirtualProcessors.first(), currentVirtualProcessors: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.currentVirtualProcessors.first(), @@ -115,7 +115,7 @@ class LogicalPartition extends MetaSystem { utilizedUncappedProcUnits: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.utilizedUncappedProcUnits?.first(), timePerInstructionExecution: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timeSpentWaitingForDispatch?.first(), timeSpentWaitingForDispatch: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timePerInstructionExecution?.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) @@ -143,12 +143,12 @@ class LogicalPartition extends MetaSystem { //map.put("tags", tagsMap) log.debug("getVirtualEthernetAdapterMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ receivedPhysicalBytes: it.receivedPhysicalBytes.first(), sentPhysicalBytes: it.sentPhysicalBytes.first(), receivedBytes: it.receivedBytes.first(), sentBytes: it.sentBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getVirtualEthernetAdapterMetrics() - fields: " + fieldsMap.toString()) @@ -177,11 +177,11 @@ class LogicalPartition extends MetaSystem { //map.put("tags", tagsMap) log.debug("getVirtualFiberChannelAdaptersMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ transmittedBytes: it.transmittedBytes.first(), writeBytes: it.writeBytes.first(), readBytes: it.readBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getVirtualFiberChannelAdaptersMetrics() - fields: " + fieldsMap.toString()) diff --git a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy b/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy index 0d5ce1b..2238f85 100644 --- a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy +++ b/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy @@ -58,12 +58,12 @@ class ManagedSystem extends MetaSystem { //map.put("tags", tagsMap) log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) - Map fieldsMap = [ + Map fieldsMap = [ "totalMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.totalMem?.first(), "availableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.availableMem?.first(), "configurableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.configurableMem?.first(), "assignedMemToLpars": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.assignedMemToLpars?.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) @@ -88,12 +88,12 @@ class ManagedSystem extends MetaSystem { //measurement.tags = tagsMap; log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ availableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.totalProcUnits?.first(), utilizedProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.utilizedProcUnits?.first(), availableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.availableProcUnits?.first(), configurableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.configurableProcUnits?.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) //measurement.fields = fieldsMap; log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) @@ -119,10 +119,10 @@ class ManagedSystem extends MetaSystem { //map.put("tags", tagsMap) log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ assignedProcUnits: it.assignedProcUnits.first(), availableProcUnits: it.availableProcUnits.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) log.debug("getSharedProcessorPools() - fields: " + fieldsMap.toString()) @@ -152,11 +152,11 @@ class ManagedSystem extends MetaSystem { measurement.tags = tagsMap; log.debug("getSystemSharedAdapters() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ sentBytes: it.sentBytes.first(), receivedBytes: it.receivedBytes.first(), transferredBytes: it.transferredBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) measurement.fields = fieldsMap; log.debug("getSystemSharedAdapters() - fields: " + fieldsMap.toString()) @@ -190,11 +190,11 @@ class ManagedSystem extends MetaSystem { measurement.tags = tagsMap; log.debug("getSystemFiberChannelAdapters() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ writeBytes: it.writeBytes.first(), readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) measurement.fields = fieldsMap; log.debug("getSystemFiberChannelAdapters() - fields: " + fieldsMap.toString()) @@ -225,11 +225,11 @@ class ManagedSystem extends MetaSystem { measurement.tags = tagsMap; log.debug("getSystemGenericPhysicalAdapters() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ writeBytes: it.writeBytes.first(), readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) measurement.fields = fieldsMap; log.debug("getSystemGenericPhysicalAdapters() - fields: " + fieldsMap.toString()) @@ -260,11 +260,11 @@ class ManagedSystem extends MetaSystem { measurement.tags = tagsMap; log.debug("getSystemGenericVirtualAdapters() - tags: " + tagsMap.toString()) - HashMap fieldsMap = [ + HashMap fieldsMap = [ writeBytes: it.writeBytes.first(), readBytes: it.readBytes.first(), transmittedBytes: it.transmittedBytes.first(), - ] + ] as HashMap //map.put("fields", fieldsMap) measurement.fields = fieldsMap; log.debug("getSystemGenericVirtualAdapters() - fields: " + fieldsMap.toString()) diff --git a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy b/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy index c73a24e..6f50bb9 100644 --- a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy +++ b/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy @@ -16,8 +16,10 @@ package biz.nellemann.hmci import biz.nellemann.hmci.pcm.PcmData -import groovy.json.JsonSlurper -import groovy.transform.CompileDynamic +import com.squareup.moshi.FromJson +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.ToJson import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -29,16 +31,36 @@ import java.time.format.DateTimeParseException @CompileStatic abstract class MetaSystem { + private final Moshi moshi; + private final JsonAdapter jsonAdapter; + protected PcmData metrics - @CompileDynamic - void processMetrics(String json) { - Map pcmMap = new JsonSlurper().parseText(json) as Map - metrics = new PcmData(pcmMap) + MetaSystem() { + try { + moshi = new Moshi.Builder().add(new NumberAdapter()).add(new BigDecimalAdapter())build(); + jsonAdapter = moshi.adapter(PcmData.class); + } catch(Exception e) { + log.warn("MetaSystem() error", e) + throw new ExceptionInInitializerError(e); + } } - @CompileDynamic - Instant getTimestamp() { + //@CompileDynamic + void processMetrics(String json) { + + try { + metrics = jsonAdapter.fromJson(json); + } catch(Exception e) { + log.warn("processMetrics() error", e) + } + + //Map pcmMap = new JsonSlurper().parseText(json) as Map + //metrics = new PcmData(pcmMap) + } + + //@CompileDynamic + Instant getTimestamp() { String timestamp = metrics.systemUtil.utilSamples.first().sampleInfo.timeStamp Instant instant = null @@ -54,4 +76,32 @@ abstract class MetaSystem { return instant ?: Instant.now() } + + class BigDecimalAdapter { + + @FromJson + BigDecimal fromJson(String string) { + return new BigDecimal(string); + } + + @ToJson + String toJson(BigDecimal value) { + return value.toString(); + } + } + + class NumberAdapter { + + @FromJson + Number fromJson(String string) { + return new Double(string); + } + + @ToJson + String toJson(Number value) { + return value.toString(); + } + } + } + diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/FiberChannelAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/FiberChannelAdapter.groovy deleted file mode 100644 index f8612f8..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/FiberChannelAdapter.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class FiberChannelAdapter { - - String id - String wwpn - String physicalLocation - Integer numOfPorts - List numOfReads - List numOfWrites - List readBytes - List writeBytes - List runningSpeed - List transmittedBytes - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/GenericAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/GenericAdapter.groovy deleted file mode 100644 index d8a34d1..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/GenericAdapter.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class GenericAdapter { - - String id - String type - String physicalLocation - List receivedPackets - List sentPackets - List droppedPackets - List sentBytes - List receivedBytes - List transferredBytes - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.groovy deleted file mode 100644 index 9fc2539..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class GenericPhysicalAdapters { - - String id - String type - String physicalLocation - List numOfReads - List numOfWrites - List readBytes - List writeBytes - List transmittedBytes - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/GenericVirtualAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/GenericVirtualAdapter.groovy deleted file mode 100644 index 1a2334e..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/GenericVirtualAdapter.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class GenericVirtualAdapter { - - String id - String type - Integer viosId - String physicalLocation - List numOfReads - List numOfWrites - List readBytes - List writeBytes - List transmittedBytes - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/LparMemory.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/LparMemory.groovy deleted file mode 100644 index 4865447..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/LparMemory.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class LparMemory { - - List logicalMem - List backedPhysicalMem - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/LparProcessor.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/LparProcessor.groovy deleted file mode 100644 index 50f773b..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/LparProcessor.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class LparProcessor { - - Integer poolId - Integer weight - String mode - List maxVirtualProcessors - List currentVirtualProcessors - List maxProcUnits - List entitledProcUnits - List utilizedProcUnits - List utilizedCappedProcUnits - List utilizedUncappedProcUnits - List idleProcUnits - List donatedProcUnits - List timeSpentWaitingForDispatch - List timePerInstructionExecution - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/LparUtil.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/LparUtil.groovy deleted file mode 100644 index 73ed269..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/LparUtil.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class LparUtil { - - Integer id - String uuid - String name - String state - String type - String osType - Integer affinityScore - - LparMemory memory - LparProcessor processor - Network network - Storage storage - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/Network.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/Network.groovy deleted file mode 100644 index 3913083..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/Network.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class Network { - List genericAdapters - List sharedAdapters - List virtualEthernetAdapters -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/PcmData.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/PcmData.groovy deleted file mode 100644 index 986c54c..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/PcmData.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class PcmData { - - SystemUtil systemUtil - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/PhysicalProcessorPool.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/PhysicalProcessorPool.groovy deleted file mode 100644 index 85d6f48..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/PhysicalProcessorPool.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class PhysicalProcessorPool { - - List assignedProcUnits - List utilizedProcUnits - List availableProcUnits - List configuredProcUnits - List borrowedProcUnits - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/SampleInfo.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/SampleInfo.groovy deleted file mode 100644 index 10bb780..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/SampleInfo.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class SampleInfo { - - String timeStamp - Integer status - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/ServerMemory.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/ServerMemory.groovy deleted file mode 100644 index a293af4..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/ServerMemory.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class ServerMemory { - - List totalMem - List availableMem - List configurableMem - List assignedMemToLpars - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/ServerProcessor.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/ServerProcessor.groovy deleted file mode 100644 index b03a367..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/ServerProcessor.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class ServerProcessor { - - List totalProcUnits - List utilizedProcUnits - List availableProcUnits - List configurableProcUnits - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/ServerUtil.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/ServerUtil.groovy deleted file mode 100644 index 9f184a1..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/ServerUtil.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class ServerUtil { - - ServerProcessor processor - ServerMemory memory - PhysicalProcessorPool physicalProcessorPool - List sharedProcessorPool - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/SharedAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/SharedAdapter.groovy deleted file mode 100644 index 0b9ab69..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/SharedAdapter.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class SharedAdapter { - - String id - String type - String physicalLocation - List receivedPackets - List sentPackets - List droppedPackets - List sentBytes - List receivedBytes - List transferredBytes - List bridgedAdapters - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/SharedProcessorPool.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/SharedProcessorPool.groovy deleted file mode 100644 index 2a0d5e9..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/SharedProcessorPool.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class SharedProcessorPool { - - String id - String name - List assignedProcUnits - List utilizedProcUnits - List availableProcUnits - List configuredProcUnits - List borrowedProcUnits - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/Storage.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/Storage.groovy deleted file mode 100644 index 150152a..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/Storage.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class Storage { - - List clientLpars - List genericPhysicalAdapters - List genericVirtualAdapters - List fiberChannelAdapters - List virtualFiberChannelAdapters - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/SystemUtil.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/SystemUtil.groovy deleted file mode 100644 index 707b706..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/SystemUtil.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class SystemUtil { - - UtilInfo utilInfo - List utilSamples - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/UtilInfo.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/UtilInfo.groovy deleted file mode 100644 index c30d1cf..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/UtilInfo.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class UtilInfo { - - String version - String metricType - Integer frequency - String startTimeStamp - String endTimeStamp - String mtms - String name - String uuid - List metricArrayOrder - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/UtilSample.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/UtilSample.groovy deleted file mode 100644 index b595aad..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/UtilSample.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class UtilSample { - - String sampleType - SampleInfo sampleInfo - ServerUtil serverUtil - List viosUtil - List lparsUtil - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/ViosUtil.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/ViosUtil.groovy deleted file mode 100644 index 2873d6e..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/ViosUtil.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class ViosUtil { - - String id - String uuid - String name - String state - Integer affinityScore - - Memory memory - LparProcessor processor - Network network - Storage storage - - class Memory { - List assignedMem - List utilizedMem - } - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.groovy deleted file mode 100644 index 4930a73..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class VirtualEthernetAdapter { - - String physicalLocation - Integer vlanId - Integer vswitchId - Boolean isPortVlanId - Integer viosId - String sharedEthernetAdapterId - List receivedPackets - List sentPackets - List droppedPackets - List sentBytes - List receivedBytes - List receivedPhysicalPackets - List sentPhysicalPackets - List droppedPhysicalPackets - List sentPhysicalBytes - List receivedPhysicalBytes - List transferredBytes - List transferredPhysicalBytes - -} diff --git a/src/main/groovy/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.groovy b/src/main/groovy/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.groovy deleted file mode 100644 index 380c251..0000000 --- a/src/main/groovy/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package biz.nellemann.hmci.pcm - -import groovy.transform.ToString - -@ToString -class VirtualFiberChannelAdapter { - - String wwpn - String wwpn2 - String physicalLocation - String physicalPortWWPN - Integer viosId - List numOfReads - List numOfWrites - List readBytes - List writeBytes - List runningSpeed - List transmittedBytes - -} diff --git a/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java new file mode 100644 index 0000000..d91235c --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java @@ -0,0 +1,18 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class FiberChannelAdapter { + + String id; + String wwpn; + String physicalLocation; + Integer numOfPorts; + List numOfReads; + List numOfWrites; + List readBytes; + List writeBytes; + List runningSpeed; + List transmittedBytes; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java new file mode 100644 index 0000000..c2dbeea --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java @@ -0,0 +1,17 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class GenericAdapter { + + String id; + String type; + String physicalLocation; + List receivedPackets; + List sentPackets; + List droppedPackets; + List sentBytes; + List receivedBytes; + List transferredBytes; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java new file mode 100644 index 0000000..008c716 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java @@ -0,0 +1,16 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class GenericPhysicalAdapters { + + String id; + String type; + String physicalLocation; + List numOfReads; + List numOfWrites; + List readBytes; + List writeBytes; + List transmittedBytes; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java new file mode 100644 index 0000000..cff608a --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java @@ -0,0 +1,17 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class GenericVirtualAdapter { + + String id; + String type; + Integer viosId; + String physicalLocation; + List numOfReads; + List numOfWrites; + List readBytes; + List writeBytes; + List transmittedBytes; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java b/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java new file mode 100644 index 0000000..025022f --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java @@ -0,0 +1,10 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class LparMemory { + + List logicalMem; + List backedPhysicalMem; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java new file mode 100644 index 0000000..d6e18a3 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java @@ -0,0 +1,22 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class LparProcessor { + + Integer poolId; + Integer weight; + String mode; + List maxVirtualProcessors; + List currentVirtualProcessors; + List maxProcUnits; + List entitledProcUnits; + List utilizedProcUnits; + List utilizedCappedProcUnits; + List utilizedUncappedProcUnits; + List idleProcUnits; + List donatedProcUnits; + List timeSpentWaitingForDispatch; + List timePerInstructionExecution; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java b/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java new file mode 100644 index 0000000..ffa50af --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java @@ -0,0 +1,18 @@ +package biz.nellemann.hmci.pcm; + +public class LparUtil { + + Integer id; + String uuid; + String name; + String state; + String type; + String osType; + Integer affinityScore; + + LparMemory memory; + LparProcessor processor; + Network network; + Storage storage; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/Network.java b/src/main/java/biz/nellemann/hmci/pcm/Network.java new file mode 100644 index 0000000..053c148 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/Network.java @@ -0,0 +1,11 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class Network { + + List genericAdapters; + List sharedAdapters; + List virtualEthernetAdapters; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/PcmData.java b/src/main/java/biz/nellemann/hmci/pcm/PcmData.java new file mode 100644 index 0000000..b3d6d04 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/PcmData.java @@ -0,0 +1,7 @@ +package biz.nellemann.hmci.pcm; + +public class PcmData { + + public SystemUtil systemUtil; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java b/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java new file mode 100644 index 0000000..443c661 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java @@ -0,0 +1,13 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class PhysicalProcessorPool { + + List assignedProcUnits; + List utilizedProcUnits; + List availableProcUnits; + List configuredProcUnits; + List borrowedProcUnits; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java b/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java new file mode 100644 index 0000000..d5a2fcc --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java @@ -0,0 +1,8 @@ +package biz.nellemann.hmci.pcm; + +public class SampleInfo { + + public String timeStamp; + Integer status; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java new file mode 100644 index 0000000..b835a0d --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java @@ -0,0 +1,12 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class ServerMemory { + + List totalMem; + List availableMem; + List configurableMem; + List assignedMemToLpars; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java b/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java new file mode 100644 index 0000000..0da20ae --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java @@ -0,0 +1,12 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class ServerProcessor { + + List totalProcUnits; + List utilizedProcUnits; + List availableProcUnits; + List configurableProcUnits; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java b/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java new file mode 100644 index 0000000..2b027b6 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java @@ -0,0 +1,12 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class ServerUtil { + + ServerProcessor processor; + ServerMemory memory; + PhysicalProcessorPool physicalProcessorPool; + List sharedProcessorPool; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java new file mode 100644 index 0000000..5ba0e07 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java @@ -0,0 +1,18 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class SharedAdapter { + + String id; + String type; + String physicalLocation; + List receivedPackets; + List sentPackets; + List droppedPackets; + List sentBytes; + List receivedBytes; + List transferredBytes; + List bridgedAdapters; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java b/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java new file mode 100644 index 0000000..5d86d38 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java @@ -0,0 +1,15 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class SharedProcessorPool { + + String id; + String name; + List assignedProcUnits; + List utilizedProcUnits; + List availableProcUnits; + List configuredProcUnits; + List borrowedProcUnits; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/Storage.java b/src/main/java/biz/nellemann/hmci/pcm/Storage.java new file mode 100644 index 0000000..8c854ac --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/Storage.java @@ -0,0 +1,13 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class Storage { + + List clientLpars; + List genericPhysicalAdapters; + List genericVirtualAdapters; + List fiberChannelAdapters; + List virtualFiberChannelAdapters; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java b/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java new file mode 100644 index 0000000..f2eedb6 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java @@ -0,0 +1,10 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class SystemUtil { + + UtilInfo utilInfo; + public List utilSamples; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java b/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java new file mode 100644 index 0000000..b8ceaa2 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java @@ -0,0 +1,17 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class UtilInfo { + + String version; + String metricType; + Integer frequency; + String startTimeStamp; + String endTimeStamp; + String mtms; + String name; + String uuid; + List metricArrayOrder; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java b/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java new file mode 100644 index 0000000..6298c6c --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java @@ -0,0 +1,13 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class UtilSample { + + String sampleType; + public SampleInfo sampleInfo; + ServerUtil serverUtil; + List viosUtil; + List lparsUtil; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java b/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java new file mode 100644 index 0000000..449299d --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java @@ -0,0 +1,10 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class ViosMemory { + + List assignedMem; + List utilizedMem; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java b/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java new file mode 100644 index 0000000..ff5fce3 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java @@ -0,0 +1,16 @@ +package biz.nellemann.hmci.pcm; + +public class ViosUtil { + + String id; + String uuid; + String name; + String state; + Integer affinityScore; + + ViosMemory memory; + LparProcessor processor; + Network network; + Storage storage; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java new file mode 100644 index 0000000..f1498a4 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java @@ -0,0 +1,26 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class VirtualEthernetAdapter { + + String physicalLocation; + Integer vlanId; + Integer vswitchId; + Boolean isPortVlanId; + Integer viosId; + String sharedEthernetAdapterId; + List receivedPackets; + List sentPackets; + List droppedPackets; + List sentBytes; + List receivedBytes; + List receivedPhysicalPackets; + List sentPhysicalPackets; + List droppedPhysicalPackets; + List sentPhysicalBytes; + List receivedPhysicalBytes; + List transferredBytes; + List transferredPhysicalBytes; + +} diff --git a/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java new file mode 100644 index 0000000..df3192a --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java @@ -0,0 +1,19 @@ +package biz.nellemann.hmci.pcm; + +import java.util.List; + +public class VirtualFiberChannelAdapter { + + String wwpn; + String wwpn2; + String physicalLocation; + String physicalPortWWPN; + Integer viosId; + List numOfReads; + List numOfWrites; + List readBytes; + List writeBytes; + List runningSpeed; + List transmittedBytes; + +} From b0053769413d1cfb92646e7d98d00ac226509210 Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Sun, 11 Oct 2020 12:25:55 +0200 Subject: [PATCH 3/4] More refactoring work, from Groovy to plain Java. --- README.md | 2 +- build.gradle | 12 +- doc/hmci.groovy.tpl | 39 --- doc/hmci.toml | 31 ++ .../groovy/biz/nellemann/hmci/Insights.groovy | 176 ---------- .../nellemann/hmci/LogicalPartition.groovy | 194 ----------- .../biz/nellemann/hmci/ManagedSystem.groovy | 279 --------------- .../biz/nellemann/hmci/Configuration.java | 2 +- .../biz/nellemann/hmci/HmcClient.java} | 326 ++++++++++-------- .../biz/nellemann/hmci/InfluxClient.java} | 14 +- .../java/biz/nellemann/hmci/Insights.java | 189 ++++++++++ .../biz/nellemann/hmci/LogicalPartition.java | 225 ++++++++++++ .../biz/nellemann/hmci/Main.java} | 15 +- .../biz/nellemann/hmci/ManagedSystem.java | 326 ++++++++++++++++++ .../biz/nellemann/hmci/MetaSystem.java} | 55 +-- .../hmci/pcm/FiberChannelAdapter.java | 34 +- .../nellemann/hmci/pcm/GenericAdapter.java | 18 +- .../hmci/pcm/GenericPhysicalAdapters.java | 28 +- .../hmci/pcm/GenericVirtualAdapter.java | 31 +- .../biz/nellemann/hmci/pcm/LparMemory.java | 9 +- .../biz/nellemann/hmci/pcm/LparProcessor.java | 52 ++- .../java/biz/nellemann/hmci/pcm/LparUtil.java | 22 +- .../java/biz/nellemann/hmci/pcm/Network.java | 7 +- .../hmci/pcm/PhysicalProcessorPool.java | 10 +- .../biz/nellemann/hmci/pcm/SampleInfo.java | 2 +- .../biz/nellemann/hmci/pcm/ServerMemory.java | 18 +- .../nellemann/hmci/pcm/ServerProcessor.java | 17 +- .../biz/nellemann/hmci/pcm/ServerUtil.java | 8 +- .../biz/nellemann/hmci/pcm/SharedAdapter.java | 36 +- .../hmci/pcm/SharedProcessorPool.java | 26 +- .../java/biz/nellemann/hmci/pcm/Storage.java | 12 +- .../biz/nellemann/hmci/pcm/SystemUtil.java | 10 +- .../java/biz/nellemann/hmci/pcm/UtilInfo.java | 18 +- .../biz/nellemann/hmci/pcm/UtilSample.java | 23 +- .../biz/nellemann/hmci/pcm/ViosMemory.java | 9 +- .../java/biz/nellemann/hmci/pcm/ViosUtil.java | 18 +- .../hmci/pcm/VirtualEthernetAdapter.java | 62 +++- .../hmci/pcm/VirtualFiberChannelAdapter.java | 22 +- src/main/resources/logback.xml | 2 +- .../hmci/LogicalPartitionTest.groovy | 6 +- .../nellemann/hmci/ManagedSystemTest.groovy | 12 +- 41 files changed, 1337 insertions(+), 1060 deletions(-) delete mode 100644 doc/hmci.groovy.tpl create mode 100644 doc/hmci.toml delete mode 100644 src/main/groovy/biz/nellemann/hmci/Insights.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy delete mode 100644 src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy rename src/main/{groovy/biz/nellemann/hmci/HmcClient.groovy => java/biz/nellemann/hmci/HmcClient.java} (56%) rename src/main/{groovy/biz/nellemann/hmci/InfluxClient.groovy => java/biz/nellemann/hmci/InfluxClient.java} (97%) create mode 100644 src/main/java/biz/nellemann/hmci/Insights.java create mode 100644 src/main/java/biz/nellemann/hmci/LogicalPartition.java rename src/main/{groovy/biz/nellemann/hmci/Main.groovy => java/biz/nellemann/hmci/Main.java} (83%) create mode 100644 src/main/java/biz/nellemann/hmci/ManagedSystem.java rename src/main/{groovy/biz/nellemann/hmci/MetaSystem.groovy => java/biz/nellemann/hmci/MetaSystem.java} (67%) diff --git a/README.md b/README.md index c411467..822a16b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ HMCi is a small utility to fetch metrics from one or more HMC's and push those t - Ensure you have correct date/time and use a NTP service to keep it accurate! - Install the HMCi package (*.deb* or *.rpm*) from [downloads](https://bitbucket.org/mnellemann/hmci/downloads/) or compile from source. -- Copy the *doc/hmci.groovy.tpl* configuration template into */etc/hmci.groovy* and edit the configuration to suit your environment. You can use the *-c [conf-file]* switch if you place this file elsewhere. +- Copy the *doc/hmci.tpml* configuration template into */etc/hmci.toml* and edit the configuration to suit your environment. You can use the *-c* option if you place this file elsewhere. - Configure Grafana to communicate with your InfluxDB and import dashboards from *doc/* into Grafana (The dashboards are slightly modified versions of the dashboard provided by the nmon2influxdb tool). - Run the *bin/hmci* program in a shell, as a @reboot cron task or setup a proper service :) diff --git a/build.gradle b/build.gradle index 6af8634..cd4aa0a 100644 --- a/build.gradle +++ b/build.gradle @@ -16,20 +16,18 @@ repositories { } dependencies { - implementation 'info.picocli:picocli:4.5.1' annotationProcessor 'info.picocli:picocli-codegen:4.5.1' - // implementation 'com.thoughtworks.xstream:xstream:1.4.13' - // https://mvnrepository.com/artifact/org.jsoup/jsoup + implementation 'info.picocli:picocli:4.5.1' implementation 'org.jsoup:jsoup:1.13.1' - implementation 'com.squareup.moshi:moshi:1.11.0' - implementation 'org.tomlj:tomlj:1.0.0' - implementation 'org.codehaus.groovy:groovy-all:3.0.5' implementation 'com.squareup.okhttp3:okhttp:4.8.0' + implementation 'com.squareup.moshi:moshi:1.11.0' + implementation 'com.serjltt.moshi:moshi-lazy-adapters:2.2' + implementation 'org.tomlj:tomlj:1.0.0' implementation 'org.influxdb:influxdb-java:2.19' implementation 'org.slf4j:slf4j-api:1.7.+' runtimeOnly 'ch.qos.logback:logback-classic:1.+' - + testImplementation 'org.codehaus.groovy:groovy-all:3.0.5' testImplementation('org.spockframework:spock-core:2.0-M3-groovy-3.0') testImplementation("org.slf4j:slf4j-simple:1.7.+") testImplementation('com.squareup.okhttp3:mockwebserver:4.8.0') diff --git a/doc/hmci.groovy.tpl b/doc/hmci.groovy.tpl deleted file mode 100644 index 37bc0eb..0000000 --- a/doc/hmci.groovy.tpl +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copy this file to /etc/hmci.groovy and change it to suit your environment. -*/ - -// How often to query HMC's for data - in seconds -hmci.refresh = 30 - -// Rescan HMC's for new systems and partitions - every x refresh -hmci.rescan = 60 - -// InfluxDB to save metrics -influx { - url = "http://localhost:8086" - username = "root" - password = "" - database = "hmci" -} - -// One or more HMC's to query for data and metrics -hmc { - - // HMC on our primary site - site1 { - url = "https://10.10.10.10:12443" - username = "hmci" - password = "hmcihmci" - unsafe = true // Ignore SSL cert. errors - } - - /* - site2 { - url = "https://10.10.20.20:12443" - username = "viewer" - password = "someSecret" - unsafe = false - } - */ - -} diff --git a/doc/hmci.toml b/doc/hmci.toml new file mode 100644 index 0000000..da9e502 --- /dev/null +++ b/doc/hmci.toml @@ -0,0 +1,31 @@ +# HMCi Configuration + +# How often to query HMC's for data - in seconds +hmci.refresh = 30 + +# Rescan HMC's for new systems and partitions - every x refresh +hmci.rescan = 60 + +# InfluxDB to save metrics +[influx] +url = "http://localhost:8086" +username = "root" +password = "" +database = "hmci" + +# One or more HMC's to query for data and metrics +[hmc] + + # HMC on our primary site + [hmc.site1] + url = "https://10.10.10.10:12443" + username = "hmci" + password = "hmcihmci" + unsafe = true # Ignore SSL cert. errors + + # Example + #[hmc.site2] + #url = "https://10.10.20.20:12443" + #username = "viewer" + #password = "someSecret" + #unsafe = false diff --git a/src/main/groovy/biz/nellemann/hmci/Insights.groovy b/src/main/groovy/biz/nellemann/hmci/Insights.groovy deleted file mode 100644 index 9334bed..0000000 --- a/src/main/groovy/biz/nellemann/hmci/Insights.groovy +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright 2020 Mark Nellemann - * - * 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 biz.nellemann.hmci - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j; - -@Slf4j -@CompileStatic -class Insights { - - final Configuration configuration; - - InfluxClient influxClient; - Map hmcClients = new HashMap<>(); - Map systems = new HashMap(); - Map partitions = new HashMap(); - - - Insights(Configuration configuration) { - this.configuration = configuration; - - try { - influxClient = new InfluxClient(configuration.influx); - influxClient.login(); - } catch(Exception e) { - System.exit(1); - } - - // Initial scan - discover(); - } - - - void discover() { - - configuration.hmc.forEach( configHmc -> { - if(!hmcClients?.containsKey(configHmc.name)) { - log.debug("Adding HMC: " + configHmc.toString()) - HmcClient hmcClient = new HmcClient(configHmc) - hmcClients.put(configHmc.name, hmcClient) - } - }); - - hmcClients.forEach(( hmcId, hmcClient) -> { - - try { - hmcClient.login() - hmcClient.getManagedSystems().each { systemId, system -> - - // Add to list of known systems - systems.putIfAbsent(systemId, system) - - // Get LPAR's for this system - hmcClient.getLogicalPartitionsForManagedSystem(system).forEach((partitionId, partition) -> { - - // Add to list of known partitions - partitions.putIfAbsent(partitionId, partition) - }); - } - } catch(Exception e) { - log.error("discover() - " + hmcId + " error: " + e.message) - //hmcClients.remove(hmcId) - } - - }); - - } - - - void getMetricsForSystems() { - - try { - - systems.forEach((systemId, system) -> { - - HmcClient hmcClient = hmcClients.get(system.hmcId) - - // Get and process metrics for this system - String tmpJsonString = hmcClient.getPcmDataForManagedSystem(system) - if(tmpJsonString && !tmpJsonString.empty) { - system.processMetrics(tmpJsonString) - } - - }); - - } catch(Exception e) { - log.error(e.message) - } - - } - - - void getMetricsForPartitions() { - - try { - - // Get LPAR's for this system - partitions.forEach((partitionId, partition) -> { - - HmcClient hmcClient = hmcClients.get(partition.system.hmcId) - - // Get and process metrics for this partition - String tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition) - if(tmpJsonString2 && !tmpJsonString2.empty) { - partition.processMetrics(tmpJsonString2) - } - - }); - - } catch(Exception e) { - log.error(e.message) - } - } - - - void writeMetricsForManagedSystems() { - systems.forEach((systemId, system) -> { - influxClient.writeManagedSystem(system) - }); - } - - - void writeMetricsForLogicalPartitions() { - partitions.each {partitionId, partition -> - influxClient.writeLogicalPartition(partition) - } - } - - - void run() { - - log.debug("run()") - - boolean keepRunning = true - int executions = 0 - - while(keepRunning) { - - try { - getMetricsForSystems() - getMetricsForPartitions() - - writeMetricsForManagedSystems() - writeMetricsForLogicalPartitions() - influxClient.writeBatchPoints() - - // Refresh HMC's - if(executions > configuration.rescan) { - executions = 0 - discover() - } - } catch(Exception e) { - log.error(e.message, e) - } - - executions++ - Thread.sleep(configuration.refresh * 1000) - } - - } - -} diff --git a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy b/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy deleted file mode 100644 index 8f229a0..0000000 --- a/src/main/groovy/biz/nellemann/hmci/LogicalPartition.groovy +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Copyright 2020 Mark Nellemann - * - * 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 biz.nellemann.hmci - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j - -@Slf4j -@CompileStatic -class LogicalPartition extends MetaSystem { - - public String id - public String name - public String type - ManagedSystem system - - LogicalPartition(String id, String name, String type, ManagedSystem system) { - this.id = id - this.name = name - this.type = type - this.system = system - } - - String toString() { - return "[${id}] ${name} (${type})" - } - - @CompileDynamic - List getAffinityScore() { - - List list = new ArrayList<>() - //Map map = new HashMap() - - HashMap tagsMap = [ - system: system.name, - partition: name, - ] - //map.put("tags", tagsMap) - log.debug("getAffinityScore() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - affinityScore: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.affinityScore, - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getAffinityScore() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement); - return list - } - - - @CompileDynamic - List getMemoryMetrics() { - - List list = new ArrayList<>() - //Map map = new HashMap() - - HashMap tagsMap = [ - system: system.name, - partition: name, - ] - //map.put("tags", tagsMap) - log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - logicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.logicalMem?.first(), - backedPhysicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.backedPhysicalMem?.first(), - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement); - - return list - } - - @CompileDynamic - List getProcessorMetrics() { - - List list = new ArrayList<>() - //Map map = new HashMap() - - HashMap tagsMap = [ - system: system.name, - partition: name, - ] - //map.put("tags", tagsMap) - log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - utilizedProcUnits: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.utilizedProcUnits?.first(), - maxVirtualProcessors: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.maxVirtualProcessors.first(), - currentVirtualProcessors: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.currentVirtualProcessors.first(), - //donatedProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.donatedProcUnits.first(), - entitledProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.entitledProcUnits.first(), - //idleProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.idleProcUnits.first(), - //maxProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.maxProcUnits.first(), - utilizedCappedProcUnits: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.utilizedCappedProcUnits?.first(), - utilizedUncappedProcUnits: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.utilizedUncappedProcUnits?.first(), - timePerInstructionExecution: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timeSpentWaitingForDispatch?.first(), - timeSpentWaitingForDispatch: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.processor?.timePerInstructionExecution?.first(), - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement); - - return list - } - - @CompileDynamic - List getVirtualEthernetAdapterMetrics() { - - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.network?.virtualEthernetAdapters?.each { - //Map map = new HashMap() - - HashMap tagsMap = [ - system: system.name, - partition: name, - sea: it.sharedEthernetAdapterId as String, - viosId: it.viosId as String, - vlanId: it.vlanId as String, - vswitchId: it.vswitchId as String, - ] - //map.put("tags", tagsMap) - log.debug("getVirtualEthernetAdapterMetrics() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - receivedPhysicalBytes: it.receivedPhysicalBytes.first(), - sentPhysicalBytes: it.sentPhysicalBytes.first(), - receivedBytes: it.receivedBytes.first(), - sentBytes: it.sentBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getVirtualEthernetAdapterMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement); - } - - return list - } - - - //PartitionVirtualFiberChannelAdapters - @CompileDynamic - List getVirtualFiberChannelAdaptersMetrics() { - - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.storage?.virtualFiberChannelAdapters?.each { - //Map map = new HashMap() - - HashMap tagsMap = [ - system: system.name, - partition: name, - viosId: it.viosId as String, - wwpn: it.wwpn, - ] - //map.put("tags", tagsMap) - log.debug("getVirtualFiberChannelAdaptersMetrics() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - transmittedBytes: it.transmittedBytes.first(), - writeBytes: it.writeBytes.first(), - readBytes: it.readBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getVirtualFiberChannelAdaptersMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement); - } - - return list - } -} diff --git a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy b/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy deleted file mode 100644 index 2238f85..0000000 --- a/src/main/groovy/biz/nellemann/hmci/ManagedSystem.groovy +++ /dev/null @@ -1,279 +0,0 @@ -/** - * Copyright 2020 Mark Nellemann - * - * 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 biz.nellemann.hmci - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j - - -@Slf4j -@CompileStatic -class ManagedSystem extends MetaSystem { - - public final String hmcId - public final String id - public final String name - public final String type - public final String model - public final String serialNumber - - - ManagedSystem(String hmcId, String id, String name, String type, String model, String serialNumber) { - this.hmcId = hmcId - this.id = id - this.name = name - this.type = type - this.model = model - this.serialNumber = serialNumber - } - - String toString() { - return "[${id}] ${name} (${type}-${model} ${serialNumber})" - } - - - @CompileDynamic - List getMemoryMetrics() { - - List list = new ArrayList<>() - //Map map = new HashMap() - - HashMap tagsMap = [ - system: name, - ] - //map.put("tags", tagsMap) - log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()) - - Map fieldsMap = [ - "totalMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.totalMem?.first(), - "availableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.availableMem?.first(), - "configurableMem": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.configurableMem?.first(), - "assignedMemToLpars": metrics.systemUtil?.utilSamples?.first()?.serverUtil?.memory?.assignedMemToLpars?.first(), - ] as HashMap - - //map.put("fields", fieldsMap) - log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement) - - return list - } - - - @CompileDynamic - List getProcessorMetrics() { - - List list = new ArrayList<>() - //Map map = new HashMap<>() - - HashMap tagsMap = [ - system: name, - ] - //map.put("tags", tagsMap) - //measurement.tags = tagsMap; - log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - availableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.totalProcUnits?.first(), - utilizedProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.utilizedProcUnits?.first(), - availableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.availableProcUnits?.first(), - configurableProcUnits: metrics.systemUtil?.utilSamples?.first()?.serverUtil?.processor?.configurableProcUnits?.first(), - ] as HashMap - //map.put("fields", fieldsMap) - //measurement.fields = fieldsMap; - log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement) - - return list - } - - - @CompileDynamic - List getSharedProcessorPools() { - - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.serverUtil?.sharedProcessorPool?.each { - //Map map = new HashMap() - - HashMap tagsMap = [ - system: name, - pool: it.name, - ] - //map.put("tags", tagsMap) - log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - assignedProcUnits: it.assignedProcUnits.first(), - availableProcUnits: it.availableProcUnits.first(), - ] as HashMap - //map.put("fields", fieldsMap) - log.debug("getSharedProcessorPools() - fields: " + fieldsMap.toString()) - - Measurement measurement = new Measurement(tagsMap, fieldsMap); - list.add(measurement) - } - - return list - } - - - @CompileDynamic - List getSystemSharedAdapters() { - - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each {vios -> - vios.network.sharedAdapters.each { - //Map map = new HashMap() - Measurement measurement = new Measurement(); - - HashMap tagsMap = [ - system: name, - type: it.type, - vios: vios.name, - ] - //map.put("tags", tagsMap) - measurement.tags = tagsMap; - log.debug("getSystemSharedAdapters() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - sentBytes: it.sentBytes.first(), - receivedBytes: it.receivedBytes.first(), - transferredBytes: it.transferredBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - measurement.fields = fieldsMap; - log.debug("getSystemSharedAdapters() - fields: " + fieldsMap.toString()) - - list.add(measurement) - } - } - - return list - } - - - @CompileDynamic - List getSystemFiberChannelAdapters() { - - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> - log.debug("getSystemFiberChannelAdapters() - VIOS: " + vios.name) - vios.storage?.fiberChannelAdapters?.each { - //HashMap map = new HashMap<>() - Measurement measurement = new Measurement(); - - HashMap tagsMap = [ - id: it.id, - system: name, - wwpn: it.wwpn, - vios: vios.name, - device: it.physicalLocation, - ] - //map.put("tags", tagsMap) - measurement.tags = tagsMap; - log.debug("getSystemFiberChannelAdapters() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - writeBytes: it.writeBytes.first(), - readBytes: it.readBytes.first(), - transmittedBytes: it.transmittedBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - measurement.fields = fieldsMap; - log.debug("getSystemFiberChannelAdapters() - fields: " + fieldsMap.toString()) - - list.add(measurement) - } - } - - return list - } - - - @CompileDynamic - List getSystemGenericPhysicalAdapters() { - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> - vios.storage?.genericPhysicalAdapters?.each { - //Map map = new HashMap() - Measurement measurement = new Measurement(); - - HashMap tagsMap = [ - id: it.id, - system: name, - vios: vios.name, - device: it.physicalLocation, - ] - //map.put("tags", tagsMap) - measurement.tags = tagsMap; - log.debug("getSystemGenericPhysicalAdapters() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - writeBytes: it.writeBytes.first(), - readBytes: it.readBytes.first(), - transmittedBytes: it.transmittedBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - measurement.fields = fieldsMap; - log.debug("getSystemGenericPhysicalAdapters() - fields: " + fieldsMap.toString()) - - list.add(measurement) - } - } - - return list - } - - - @CompileDynamic - List getSystemGenericVirtualAdapters() { - List list = new ArrayList<>() - metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios -> - vios.storage?.genericVirtualAdapters?.each { - //Map map = new HashMap() - Measurement measurement = new Measurement(); - - HashMap tagsMap = [ - id: it.id, - system: name, - vios: vios.name, - device: it.physicalLocation, - ] - //map.put("tags", tagsMap) - measurement.tags = tagsMap; - log.debug("getSystemGenericVirtualAdapters() - tags: " + tagsMap.toString()) - - HashMap fieldsMap = [ - writeBytes: it.writeBytes.first(), - readBytes: it.readBytes.first(), - transmittedBytes: it.transmittedBytes.first(), - ] as HashMap - //map.put("fields", fieldsMap) - measurement.fields = fieldsMap; - log.debug("getSystemGenericVirtualAdapters() - fields: " + fieldsMap.toString()) - - list.add(measurement); - } - } - - return list - } - -} diff --git a/src/main/java/biz/nellemann/hmci/Configuration.java b/src/main/java/biz/nellemann/hmci/Configuration.java index 215b93a..f285c3d 100644 --- a/src/main/java/biz/nellemann/hmci/Configuration.java +++ b/src/main/java/biz/nellemann/hmci/Configuration.java @@ -139,7 +139,7 @@ public class Configuration { String url; String username; String password; - Boolean unsafe; + Boolean unsafe = false; private boolean isValid = false; diff --git a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy b/src/main/java/biz/nellemann/hmci/HmcClient.java similarity index 56% rename from src/main/groovy/biz/nellemann/hmci/HmcClient.groovy rename to src/main/java/biz/nellemann/hmci/HmcClient.java index 3f53f69..34260ad 100644 --- a/src/main/groovy/biz/nellemann/hmci/HmcClient.groovy +++ b/src/main/java/biz/nellemann/hmci/HmcClient.java @@ -13,88 +13,97 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package biz.nellemann.hmci +package biz.nellemann.hmci; -import biz.nellemann.hmci.Configuration.HmcObject -import com.squareup.moshi.Moshi -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import groovy.xml.XmlSlurper -import okhttp3.* -import org.jsoup.Jsoup -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import org.jsoup.select.Elements +import biz.nellemann.hmci.Configuration.HmcObject; +import okhttp3.*; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.net.ssl.* -import java.security.SecureRandom -import java.security.cert.CertificateException -import java.security.cert.X509Certificate +import javax.net.ssl.*; +import java.io.IOException; +import java.net.URL; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; -@Slf4j -@CompileStatic class HmcClient { + private final static Logger log = LoggerFactory.getLogger(HmcClient.class); + private final MediaType MEDIA_TYPE_IBM_XML_LOGIN = MediaType.parse("application/vnd.ibm.powervm.web+xml; type=LogonRequest"); - private final String hmcId - private final String baseUrl - private final String username - private final String password - private final Boolean unsafe + private final String hmcId; + private final String baseUrl; + private final String username; + private final String password; + private final Boolean unsafe; - protected Integer responseErrors = 0 - protected String authToken - private final OkHttpClient client + protected Integer responseErrors = 0; + protected String authToken; + private final OkHttpClient client; HmcClient(HmcObject configHmc) { - this.hmcId = configHmc.name - this.baseUrl = configHmc.url - this.username = configHmc.username - this.password = configHmc.password - this.unsafe = configHmc.unsafe + this.hmcId = configHmc.name; + this.baseUrl = configHmc.url; + this.username = configHmc.username; + this.password = configHmc.password; + this.unsafe = configHmc.unsafe; if(unsafe) { - this.client = getUnsafeOkHttpClient() + this.client = getUnsafeOkHttpClient(); } else { - this.client = new OkHttpClient() + this.client = new OkHttpClient(); } } + /** + * Logon to the HMC and get an authentication token for further requests. + * @throws Exception + */ + void login() throws Exception { + this.login(false); + } + /** * Logon to the HMC and get an authentication token for further requests. - * - * @throws IOException + * @param force + * @throws Exception */ - //@CompileDynamic - void login(Boolean force = false) throws IOException { + void login(Boolean force) throws Exception { - if(authToken && !force) { - return + if(authToken != null && !force) { + return; } log.info("Connecting to HMC - " + baseUrl); - String payload = """\ - - - ${username} - ${password} -""" + StringBuilder payload = new StringBuilder(); + payload.append(""); + payload.append(""); + payload.append("").append(username).append(""); + payload.append("").append(password).append(""); + payload.append(""); - URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl)) + URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl)); Request request = new Request.Builder() .url(url) //.addHeader("Content-Type", "application/vnd.ibm.powervm.web+xml; type=LogonRequest") .addHeader("Accept", "application/vnd.ibm.powervm.web+xml; type=LogonResponse") .addHeader("X-Audit-Memento", "hmci") - .put(RequestBody.create(payload, MEDIA_TYPE_IBM_XML_LOGIN)) + .put(RequestBody.create(payload.toString(), MEDIA_TYPE_IBM_XML_LOGIN)) .build(); try { @@ -103,15 +112,15 @@ class HmcClient { // Get response body and parse String responseBody = response.body().string(); - response.body().close() + response.body().close(); - def xml = new XmlSlurper().parseText(responseBody) - authToken = xml.toString() + Document doc = Jsoup.parse(responseBody); + authToken = doc.select("X-API-Session").text(); - log.debug("login() - Auth Token: " + authToken) + log.debug("login() - Auth Token: " + authToken); } catch(Exception e) { - log.error(e.message) - throw new Exception(e) + log.error(e.getMessage()); + throw new Exception(e); } } @@ -122,13 +131,13 @@ class HmcClient { * Logoff from the HMC and remove any session * */ - void logoff() { + void logoff() throws IOException { - if(!authToken) { - return + if(authToken == null) { + return; } - URL absUrl = new URL(String.format("%s/rest/api/web/Logon", baseUrl)) + URL absUrl = new URL(String.format("%s/rest/api/web/Logon", baseUrl)); Request request = new Request.Builder() .url(absUrl) .addHeader("Content-Type", "application/vnd.ibm.powervm.web+xml; type=LogonRequest") @@ -139,8 +148,8 @@ class HmcClient { Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); - authToken = null - log.debug("logoff()") + authToken = null; + log.debug("logoff()"); } @@ -150,143 +159,158 @@ class HmcClient { * * @return */ - //@CompileDynamic - Map getManagedSystems() { - URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl)) - Response response = getResponse(url) - String responseBody = response.body().string() - Map managedSystemsMap = new HashMap() + Map getManagedSystems() throws Exception { + + URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl)); + Response response = getResponse(url); + String responseBody = Objects.requireNonNull(response.body()).string(); + Map managedSystemsMap = new HashMap(); // Do not try to parse empty response - if(responseBody.empty || responseBody.size() < 1) { - responseErrors++ - return managedSystemsMap + if(responseBody.isEmpty() || responseBody.length() <= 1) { + responseErrors++; + return managedSystemsMap; } try { Document doc = Jsoup.parse(responseBody); - Elements managedSystems = doc.select("ManagedSystem|ManagedSystem") // doc.select("img[src$=.png]"); + Elements managedSystems = doc.select("ManagedSystem|ManagedSystem"); // doc.select("img[src$=.png]"); for(Element el : managedSystems) { ManagedSystem system = new ManagedSystem( hmcId, - el.select("Metadata > Atom > AtomID").text() as String, - el.select("SystemName").text() as String, - el.select("MachineTypeModelAndSerialNumber > MachineType").text() as String, - el.select("MachineTypeModelAndSerialNumber > Model").text() as String, - el.select("MachineTypeModelAndSerialNumber > SerialNumber").text() as String, - ) - managedSystemsMap.put(system.id, system) - log.info("getManagedSystems() - Found system: " + system.toString()) + el.select("Metadata > Atom > AtomID").text(), + el.select("SystemName").text(), + el.select("MachineTypeModelAndSerialNumber > MachineType").text(), + el.select("MachineTypeModelAndSerialNumber > Model").text(), + el.select("MachineTypeModelAndSerialNumber > SerialNumber").text() + ); + managedSystemsMap.put(system.id, system); + log.info("getManagedSystems() - Found system: " + system.toString()); } } catch(Exception e) { log.warn("getManagedSystems() - xml parse error", e); } - return managedSystemsMap + return managedSystemsMap; } /** * Return Map of LogicalPartitions seen by a ManagedSystem on this HMC - - * @param UUID of managed system + * @param system * @return */ - //@CompileDynamic - Map getLogicalPartitionsForManagedSystem(ManagedSystem system) { - URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id)) - Response response = getResponse(url) - String responseBody = response.body().string() - Map partitionMap = new HashMap() {} + Map getLogicalPartitionsForManagedSystem(ManagedSystem system) throws Exception { + URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id)); + Response response = getResponse(url); + String responseBody = Objects.requireNonNull(response.body()).string(); + Map partitionMap = new HashMap() {}; // Do not try to parse empty response - if(responseBody.empty || responseBody.size() < 1) { - responseErrors++ - return partitionMap + if(responseBody.isEmpty() || responseBody.length() <= 1) { + responseErrors++; + return partitionMap; } try { Document doc = Jsoup.parse(responseBody); - Elements logicalPartitions = doc.select("LogicalPartition|LogicalPartition") // doc.select("img[src$=.png]"); + Elements logicalPartitions = doc.select("LogicalPartition|LogicalPartition"); // doc.select("img[src$=.png]"); for(Element el : logicalPartitions) { LogicalPartition logicalPartition = new LogicalPartition( - el.select("PartitionUUID").text() as String, - el.select("PartitionName").text() as String, - el.select("PartitionType").text() as String, + el.select("PartitionUUID").text(), + el.select("PartitionName").text(), + el.select("PartitionType").text(), system - ) - partitionMap.put(logicalPartition.id, logicalPartition) - log.info("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()) + ); + partitionMap.put(logicalPartition.id, logicalPartition); + log.info("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()); } } catch(Exception e) { log.warn("getLogicalPartitionsForManagedSystem() - xml parse error", e); } - return partitionMap + return partitionMap; } /** * Parse XML feed to get PCM Data in JSON format - * @param systemId + * @param system * @return */ - //@CompileDynamic - String getPcmDataForManagedSystem(ManagedSystem system) { - log.debug("getPcmDataForManagedSystem() - " + system.id) - URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, system.id)) - Response response = getResponse(url) - String responseBody = response.body().string() - String jsonBody + String getPcmDataForManagedSystem(ManagedSystem system) throws Exception { + + log.debug("getPcmDataForManagedSystem() - " + system.id); + URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, system.id)); + Response response = getResponse(url); + String responseBody = Objects.requireNonNull(response.body()).string(); + String jsonBody = null; // Do not try to parse empty response - if(responseBody.empty || responseBody.size() < 1) { - responseErrors++ - return jsonBody + if(responseBody.isEmpty() || responseBody.length() <= 1) { + responseErrors++; + log.warn("getPcmDataForManagedSystem() - empty response"); + return jsonBody; } try { Document doc = Jsoup.parse(responseBody); - Element entry = doc.select("entry").first(); + Element entry = doc.select("feed > entry").first(); Element link = entry.select("link[href]").first(); - if(link.attr("type") == "application/json") { - String href = (String) link.attr("href"); + + if(link.attr("type").equals("application/json")) { + String href = link.attr("href"); log.debug("getPcmDataForManagedSystem() - json url: " + href); jsonBody = getResponseBody(new URL(href)); } + } catch(Exception e) { log.warn("getPcmDataForManagedSystem() - xml parse error", e); } - return jsonBody + return jsonBody; } /** * Parse XML feed to get PCM Data in JSON format - * @param systemId - * @param partitionId + * @param partition * @return */ - //@CompileDynamic - String getPcmDataForLogicalPartition(LogicalPartition partition) { + String getPcmDataForLogicalPartition(LogicalPartition partition) throws Exception { - log.debug(String.format("getPcmDataForLogicalPartition() - %s @ %s", partition.id, partition.system.id)) - URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/LogicalPartition/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, partition.system.id, partition.id)) - Response response = getResponse(url) - String responseBody = response.body().string() - String jsonBody + log.debug(String.format("getPcmDataForLogicalPartition() - %s @ %s", partition.id, partition.system.id)); + URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/LogicalPartition/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, partition.system.id, partition.id)); + Response response = getResponse(url); + String responseBody = Objects.requireNonNull(response.body()).string(); + String jsonBody = null; // Do not try to parse empty response - if(responseBody.empty || responseBody.size() < 1) { - responseErrors++ - return jsonBody + if(responseBody.isEmpty() || responseBody.length() <= 1) { + responseErrors++; + log.warn("getPcmDataForLogicalPartition() - empty response"); + return jsonBody; } + try { + Document doc = Jsoup.parse(responseBody); + Element entry = doc.select("feed > entry").first(); + Element link = entry.select("link[href]").first(); + + if(link.attr("type").equals("application/json")) { + String href = link.attr("href"); + log.debug("getPcmDataForLogicalPartition() - json url: " + href); + jsonBody = getResponseBody(new URL(href)); + } + + } catch(Exception e) { + log.warn("getPcmDataForLogicalPartition() - xml parse error", e); + } + /* try { Document doc = Jsoup.parse(responseBody); Element entry = doc.select("entry").first(); @@ -298,9 +322,9 @@ class HmcClient { } } catch(Exception e) { log.warn("getPcmDataForLogicalPartition() - xml parse error", e); - } + }*/ - return jsonBody + return jsonBody; } @@ -310,28 +334,38 @@ class HmcClient { * @param url * @return */ - protected String getResponseBody(URL url) { - Response response = getResponse(url) - String body = response.body().string() - response.body().close() - return body + protected String getResponseBody(URL url) throws Exception { + Response response = getResponse(url); + String body = Objects.requireNonNull(response.body()).string(); + Objects.requireNonNull(response.body()).close(); + return body; } - /** * Return a Response from the HMC - * * @param url * @return */ - //@CompileDynamic - private Response getResponse(URL url, Integer retry = 0) { + private Response getResponse(URL url) throws Exception { + return getResponse(url, 0); + } + + + /** + * Return a Response from the HMC + * @param url + * @param retry + * @return + */ + private Response getResponse(URL url, Integer retry) throws Exception { + + log.debug("getResponse() - " + url.toString()); if(responseErrors > 2) { - responseErrors = 0 - login(true) - return getResponse(url, retry++) + responseErrors = 0; + login(true); + return getResponse(url, retry++); } Request request = new Request.Builder() @@ -343,23 +377,23 @@ class HmcClient { Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { - response.body().close() + response.body().close(); if(response.code() == 401) { - login(true) - return getResponse(url, retry++) + login(true); + return getResponse(url, retry++); } if(retry < 2) { - log.warn("getResponse() - Retrying due to unexpected response: " + response.code()) - return getResponse(url, retry++) + log.warn("getResponse() - Retrying due to unexpected response: " + response.code()); + return getResponse(url, retry++); } - log.error("getResponse() - Unexpected response: " + response.code()) - throw new IOException("getResponse() - Unexpected response: " + response.code()) + log.error("getResponse() - Unexpected response: " + response.code()); + throw new IOException("getResponse() - Unexpected response: " + response.code()); }; - return response + return response; } diff --git a/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy b/src/main/java/biz/nellemann/hmci/InfluxClient.java similarity index 97% rename from src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy rename to src/main/java/biz/nellemann/hmci/InfluxClient.java index 04a21d2..8d26f9d 100644 --- a/src/main/groovy/biz/nellemann/hmci/InfluxClient.groovy +++ b/src/main/java/biz/nellemann/hmci/InfluxClient.java @@ -15,8 +15,7 @@ */ package biz.nellemann.hmci; -import biz.nellemann.hmci.Configuration.InfluxObject -import groovy.transform.CompileStatic; +import biz.nellemann.hmci.Configuration.InfluxObject; import org.influxdb.BatchOptions; import org.influxdb.InfluxDB; import org.influxdb.InfluxDBFactory; @@ -26,10 +25,11 @@ import org.influxdb.dto.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.Instant +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; -@CompileStatic class InfluxClient { private final static Logger log = LoggerFactory.getLogger(InfluxClient.class); @@ -54,7 +54,7 @@ class InfluxClient { void login() throws Exception { if(influxDB != null) { - return + return; } try { @@ -91,7 +91,7 @@ class InfluxClient { } - void writeBatchPoints() { + void writeBatchPoints() throws Exception { log.debug("writeBatchPoints()"); try { influxDB.write(batchPoints); @@ -271,7 +271,7 @@ class InfluxClient { // Iterate fields //Map fieldsMap = m.get("fields"); m.fields.forEach((fieldName, fieldValue) -> { - log.debug("processMeasurementMap() " + measurement + " - fieldName: " + fieldName + ", fieldValue: " + fieldValue) + log.debug("processMeasurementMap() " + measurement + " - fieldName: " + fieldName + ", fieldValue: " + fieldValue); Point.Builder builder = Point.measurement(measurement) .time(timestamp.toEpochMilli(), TimeUnit.MILLISECONDS) diff --git a/src/main/java/biz/nellemann/hmci/Insights.java b/src/main/java/biz/nellemann/hmci/Insights.java new file mode 100644 index 0000000..e1dcc20 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/Insights.java @@ -0,0 +1,189 @@ +/** + * Copyright 2020 Mark Nellemann + * + * 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 biz.nellemann.hmci; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +class Insights { + + private final static Logger log = LoggerFactory.getLogger(Insights.class); + + final Configuration configuration; + + InfluxClient influxClient; + Map hmcClients = new HashMap<>(); + Map systems = new HashMap(); + Map partitions = new HashMap(); + + + Insights(Configuration configuration) { + this.configuration = configuration; + + try { + influxClient = new InfluxClient(configuration.influx); + influxClient.login(); + } catch(Exception e) { + System.exit(1); + } + + // Initial scan + discover(); + } + + + void discover() { + + configuration.hmc.forEach( configHmc -> { + if(hmcClients != null && !hmcClients.containsKey(configHmc.name)) { + log.debug("Adding HMC: " + configHmc.toString()); + HmcClient hmcClient = new HmcClient(configHmc); + hmcClients.put(configHmc.name, hmcClient); + } + }); + + hmcClients.forEach(( hmcId, hmcClient) -> { + + try { + hmcClient.login(); + hmcClient.getManagedSystems().forEach((systemId, system) -> { + + // Add to list of known systems + systems.putIfAbsent(systemId, system); + + // Get LPAR's for this system + try { + hmcClient.getLogicalPartitionsForManagedSystem(system).forEach((partitionId, partition) -> { + + // Add to list of known partitions + partitions.putIfAbsent(partitionId, partition); + }); + } catch (Exception e) { + log.error("discover()", e); + } + + }); + + } catch(Exception e) { + log.error("discover() - " + hmcId + " error: " + e.getMessage()); + //hmcClients.remove(hmcId); + } + + }); + + } + + + void getMetricsForSystems() { + + systems.forEach((systemId, system) -> { + + HmcClient hmcClient = hmcClients.get(system.hmcId); + + // Get and process metrics for this system + String tmpJsonString = null; + try { + tmpJsonString = hmcClient.getPcmDataForManagedSystem(system); + } catch (Exception e) { + log.error("getMetricsForSystems()", e); + //e.printStackTrace(); + } + + if(tmpJsonString != null && !tmpJsonString.isEmpty()) { + system.processMetrics(tmpJsonString); + } + + }); + + } + + + void getMetricsForPartitions() { + + try { + + // Get LPAR's for this system + partitions.forEach((partitionId, partition) -> { + + HmcClient hmcClient = hmcClients.get(partition.system.hmcId); + + // Get and process metrics for this partition + String tmpJsonString2 = null; + try { + tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition); + } catch (Exception e) { + log.error("getMetricsForPartitions()", e); + } + if(tmpJsonString2 != null && !tmpJsonString2.isEmpty()) { + partition.processMetrics(tmpJsonString2); + } + + }); + + } catch(Exception e) { + log.error("getMetricsForPartitions()", e); + } + } + + + void writeMetricsForManagedSystems() { + systems.forEach((systemId, system) -> { + influxClient.writeManagedSystem(system); + }); + } + + + void writeMetricsForLogicalPartitions() { + partitions.forEach((partitionId, partition) -> { + influxClient.writeLogicalPartition(partition); + }); + } + + + void run() throws InterruptedException { + + log.debug("run()"); + int executions = 0; + + while(true) { + + try { + getMetricsForSystems(); + getMetricsForPartitions(); + + writeMetricsForManagedSystems(); + writeMetricsForLogicalPartitions(); + influxClient.writeBatchPoints(); + + // Refresh HMC's + if(executions > configuration.rescan) { + executions = 0; + discover(); + } + } catch(Exception e) { + log.error("run()", e.getMessage()); + } + + executions++; + Thread.sleep(configuration.refresh * 1000); + } + + } + +} diff --git a/src/main/java/biz/nellemann/hmci/LogicalPartition.java b/src/main/java/biz/nellemann/hmci/LogicalPartition.java new file mode 100644 index 0000000..ac3a436 --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/LogicalPartition.java @@ -0,0 +1,225 @@ +/** + * Copyright 2020 Mark Nellemann + * + * 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 biz.nellemann.hmci; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class LogicalPartition extends MetaSystem { + + private final static Logger log = LoggerFactory.getLogger(LogicalPartition.class); + + public String id; + public String name; + public String type; + public ManagedSystem system; + + + LogicalPartition(String id, String name, String type, ManagedSystem system) { + this.id = id; + this.name = name; + this.type = type; + this.system = system; + } + + + public String toString() { + return String.format("[%s] %s (%s)", id, name, type); + } + + + List getAffinityScore() { + + List list = new ArrayList<>(); + //Map map = new HashMap() + + Map tagsMap = new HashMap() { + { + put("system", system.name); + put("partition", name); + } + }; + + //map.put("tags", tagsMap) + log.debug("getAffinityScore() - tags: " + tagsMap.toString()); + Map fieldsMap = new HashMap() { + { + put("affinityScore", metrics.systemUtil.sample.lparsUtil.affinityScore); + } + }; + + //map.put("fields", fieldsMap) + log.debug("getAffinityScore() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + return list; + } + + + List getMemoryMetrics() { + + List list = new ArrayList<>(); + //Map map = new HashMap() + + Map tagsMap = new HashMap() { + { + put("system", system.name); + put("partition", name); + } + }; + + //map.put("tags", tagsMap) + log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()); + + Map fieldsMap = new HashMap() { + { + put("logicalMem", metrics.systemUtil.sample.lparsUtil.memory.logicalMem); + put("backedPhysicalMem", metrics.systemUtil.sample.lparsUtil.memory.backedPhysicalMem); + } + }; + + + //map.put("fields", fieldsMap) + log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + + return list; + } + + //@CompileDynamic + List getProcessorMetrics() { + + List list = new ArrayList<>(); + //Map map = new HashMap() + + HashMap tagsMap = new HashMap() { + { + put("system", system.name); + put("partition", name); + } + }; + + //map.put("tags", tagsMap) + log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("utilizedProcUnits", metrics.systemUtil.sample.lparsUtil.processor.utilizedProcUnits); + put("maxVirtualProcessors", metrics.systemUtil.sample.lparsUtil.processor.maxVirtualProcessors); + put("currentVirtualProcessors", metrics.systemUtil.sample.lparsUtil.processor.currentVirtualProcessors); + //donatedProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.donatedProcUnits.first(), + put("entitledProcUnits", metrics.systemUtil.sample.lparsUtil.processor.entitledProcUnits); + //idleProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.idleProcUnits.first(), + //maxProcUnits: metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.maxProcUnits.first(), + put("utilizedCappedProcUnits", metrics.systemUtil.sample.lparsUtil.processor.utilizedCappedProcUnits); + put("utilizedUncappedProcUnits", metrics.systemUtil.sample.lparsUtil.processor.utilizedUncappedProcUnits); + put("timePerInstructionExecution", metrics.systemUtil.sample.lparsUtil.processor.timeSpentWaitingForDispatch); + put("timeSpentWaitingForDispatch", metrics.systemUtil.sample.lparsUtil.processor.timePerInstructionExecution); + } + }; + + //map.put("fields", fieldsMap) + log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + + return list; + } + + //@CompileDynamic + List getVirtualEthernetAdapterMetrics() { + + List list = new ArrayList<>(); + metrics.systemUtil.sample.lparsUtil.network.virtualEthernetAdapters.forEach( adapter -> { + + HashMap tagsMap = new HashMap() { + { + put("system", system.name); + put("partition", name); + put("sea", adapter.sharedEthernetAdapterId); + put("viosId", adapter.viosId.toString()); + put("vlanId", adapter.vlanId.toString()); + put("vswitchId", adapter.vswitchId.toString()); + } + }; + log.debug("getVirtualEthernetAdapterMetrics() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("receivedPhysicalBytes", adapter.receivedPhysicalBytes); + put("sentPhysicalBytes", adapter.sentPhysicalBytes); + put("receivedBytes", adapter.receivedBytes); + put("sentBytes", adapter.sentBytes); + } + }; + log.debug("getVirtualEthernetAdapterMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + }); + + return list; + } + + + //PartitionVirtualFiberChannelAdapters + //@CompileDynamic + List getVirtualFiberChannelAdaptersMetrics() { + + List list = new ArrayList<>(); + metrics.systemUtil.sample.lparsUtil.storage.virtualFiberChannelAdapters.forEach( adapter -> { + //Map map = new HashMap() + + HashMap tagsMap = new HashMap() { + { + put("system", system.name); + put("partition", name); + put("viosId", adapter.viosId.toString()); + put("wwpn", adapter.wwpn); + } + }; + + //map.put("tags", tagsMap) + log.debug("getVirtualFiberChannelAdaptersMetrics() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("transmittedBytes", adapter.transmittedBytes.get(0)); + put("writeBytes", adapter.writeBytes.get(0)); + put("readBytes", adapter.readBytes.get(0)); + } + }; + + //map.put("fields", fieldsMap) + log.debug("getVirtualFiberChannelAdaptersMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + }); + + return list; + } + +} diff --git a/src/main/groovy/biz/nellemann/hmci/Main.groovy b/src/main/java/biz/nellemann/hmci/Main.java similarity index 83% rename from src/main/groovy/biz/nellemann/hmci/Main.groovy rename to src/main/java/biz/nellemann/hmci/Main.java index 0994d74..82d0487 100644 --- a/src/main/groovy/biz/nellemann/hmci/Main.groovy +++ b/src/main/java/biz/nellemann/hmci/Main.java @@ -13,16 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -package biz.nellemann.hmci +package biz.nellemann.hmci; -import groovy.transform.CompileStatic; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine; import picocli.CommandLine.Command; + +import java.io.File; +import java.io.IOException; import java.util.concurrent.Callable; -@CompileStatic @Command(name = "hmci", mixinStandardHelpOptions = true, description = "HMC Insights.", @@ -31,7 +32,7 @@ public class Main implements Callable { private final static Logger log = LoggerFactory.getLogger(Main.class); - @CommandLine.Option(names = ["-c", "--conf"], description = "Configuration file [default: '/etc/hmci.toml'].") + @CommandLine.Option(names = { "-c", "--conf" }, description = "Configuration file [default: '/etc/hmci.toml'].") private String configurationFile = "/etc/hmci.toml"; public static void main(String... args) { @@ -51,7 +52,11 @@ public class Main implements Callable { Configuration configuration = new Configuration(configurationFile); Insights insights = new Insights(configuration); - insights.run(); + try { + insights.run(); + } catch (InterruptedException e) { + log.error(e.getMessage()); + } return 0; } diff --git a/src/main/java/biz/nellemann/hmci/ManagedSystem.java b/src/main/java/biz/nellemann/hmci/ManagedSystem.java new file mode 100644 index 0000000..84c1a3d --- /dev/null +++ b/src/main/java/biz/nellemann/hmci/ManagedSystem.java @@ -0,0 +1,326 @@ +/** + * Copyright 2020 Mark Nellemann + * + * 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 biz.nellemann.hmci; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class ManagedSystem extends MetaSystem { + + private final static Logger log = LoggerFactory.getLogger(ManagedSystem.class); + + public final String hmcId; + public final String id; + public final String name; + public final String type; + public final String model; + public final String serialNumber; + + + ManagedSystem(String hmcId, String id, String name, String type, String model, String serialNumber) { + this.hmcId = hmcId; + this.id = id; + this.name = name; + this.type = type; + this.model = model; + this.serialNumber = serialNumber; + } + + public String toString() { + return String.format("[%s] %s (%s-%s %s)", id, name, type, model, serialNumber); + } + + + List getMemoryMetrics() { + + List list = new ArrayList<>(); + //Map map = new HashMap() + + HashMap tagsMap = new HashMap() { + { + put("system", name); + } + }; + + //map.put("tags", tagsMap) + log.debug("getMemoryMetrics() - tags: " + tagsMap.toString()); + + Map fieldsMap = new HashMap() { + { + put("totalMem", metrics.systemUtil.sample.serverUtil.memory.totalMem); + put("availableMem", metrics.systemUtil.sample.serverUtil.memory.availableMem); + put("configurableMem", metrics.systemUtil.sample.serverUtil.memory.configurableMem); + put("assignedMemToLpars", metrics.systemUtil.sample.serverUtil.memory.assignedMemToLpars); + } + }; + + //map.put("fields", fieldsMap) + log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + + return list; + } + + + List getProcessorMetrics() { + + List list = new ArrayList<>(); + //Map map = new HashMap<>() + + HashMap tagsMap = new HashMap() { + { + put("system", name); + } + }; + + //map.put("tags", tagsMap) + //measurement.tags = tagsMap; + log.debug("getProcessorMetrics() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.totalProcUnits); + put("utilizedProcUnits", metrics.systemUtil.sample.serverUtil.processor.utilizedProcUnits); + put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.availableProcUnits); + put("configurableProcUnits", metrics.systemUtil.sample.serverUtil.processor.configurableProcUnits); + } + }; + //map.put("fields", fieldsMap) + //measurement.fields = fieldsMap; + log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + + return list; + } + + + List getSharedProcessorPools() { + + List list = new ArrayList<>(); + metrics.systemUtil.sample.serverUtil.sharedProcessorPool.forEach(adapter -> { + //Map map = new HashMap() + + HashMap tagsMap = new HashMap() { + { + put("system", name); + put("pool", adapter.name); + } + }; + + //map.put("tags", tagsMap) + log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("assignedProcUnits", adapter.assignedProcUnits); + put("availableProcUnits", adapter.availableProcUnits); + } + }; + + //map.put("fields", fieldsMap) + log.debug("getSharedProcessorPools() - fields: " + fieldsMap.toString()); + + Measurement measurement = new Measurement(tagsMap, fieldsMap); + list.add(measurement); + }); + + return list; + } + + + List getSystemSharedAdapters() { + + List list = new ArrayList<>(); + metrics.systemUtil.sample.viosUtil.forEach(vios -> { + + vios.network.sharedAdapters.forEach(adapter -> { + //Map map = new HashMap() + Measurement measurement = new Measurement(); + + HashMap tagsMap = new HashMap() { + { + put("system", name); + put("type", adapter.type); + put("vios", vios.name); + } + }; + + //map.put("tags", tagsMap) + measurement.tags = tagsMap; + log.debug("getSystemSharedAdapters() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("sentBytes", adapter.sentBytes); + put("receivedBytes", adapter.receivedBytes); + put("transferredBytes", adapter.transferredBytes); + } + }; + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; + log.debug("getSystemSharedAdapters() - fields: " + fieldsMap.toString()); + + list.add(measurement); + }); + + }); + + return list; + } + + + List getSystemFiberChannelAdapters() { + + List list = new ArrayList<>(); + metrics.systemUtil.sample.viosUtil.forEach( vios -> { + log.debug("getSystemFiberChannelAdapters() - VIOS: " + vios.name); + + vios.storage.fiberChannelAdapters.forEach( adapter -> { + //HashMap map = new HashMap<>() + Measurement measurement = new Measurement(); + + HashMap tagsMap = new HashMap() { + { + put("id", adapter.id); + put("system", name); + put("wwpn", adapter.wwpn); + put("vios", vios.name); + put("device", adapter.physicalLocation); + } + }; + + //map.put("tags", tagsMap) + measurement.tags = tagsMap; + log.debug("getSystemFiberChannelAdapters() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("writeBytes", adapter.writeBytes); + put("readBytes", adapter.readBytes); + put("transmittedBytes", adapter.transmittedBytes); + } + }; + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; + log.debug("getSystemFiberChannelAdapters() - fields: " + fieldsMap.toString()); + + list.add(measurement); + }); + + }); + + return list; + } + + + List getSystemGenericPhysicalAdapters() { + + List list = new ArrayList<>(); + + metrics.systemUtil.sample.viosUtil.forEach( vios -> { + + vios.storage.genericPhysicalAdapters.forEach( adapter -> { + //Map map = new HashMap() + Measurement measurement = new Measurement(); + + HashMap tagsMap = new HashMap() { + { + put("id", adapter.id); + put("system", name); + put("vios", vios.name); + put("device", adapter.physicalLocation); + } + }; + + //map.put("tags", tagsMap) + measurement.tags = tagsMap; + log.debug("getSystemGenericPhysicalAdapters() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("writeBytes", adapter.writeBytes); + put("readBytes", adapter.readBytes); + put("transmittedBytes", adapter.transmittedBytes); + } + }; + + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; + log.debug("getSystemGenericPhysicalAdapters() - fields: " + fieldsMap.toString()); + + list.add(measurement); + }); + + }); + + return list; + } + + + List getSystemGenericVirtualAdapters() { + + List list = new ArrayList<>(); + + metrics.systemUtil.sample.viosUtil.forEach( vios -> { + + vios.storage.genericVirtualAdapters.forEach( adapter -> { + + //Map map = new HashMap() + Measurement measurement = new Measurement(); + + HashMap tagsMap = new HashMap() { + { + put("id", adapter.id); + put("system", name); + put("vios", vios.name); + put("device", adapter.physicalLocation); + } + }; + + //map.put("tags", tagsMap) + measurement.tags = tagsMap; + log.debug("getSystemGenericVirtualAdapters() - tags: " + tagsMap.toString()); + + HashMap fieldsMap = new HashMap() { + { + put("writeBytes", adapter.writeBytes); + put("readBytes", adapter.readBytes); + put("transmittedBytes", adapter.transmittedBytes); + } + }; + + //map.put("fields", fieldsMap) + measurement.fields = fieldsMap; + log.debug("getSystemGenericVirtualAdapters() - fields: " + fieldsMap.toString()); + + list.add(measurement); + }); + + }); + + return list; + } + +} diff --git a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy b/src/main/java/biz/nellemann/hmci/MetaSystem.java similarity index 67% rename from src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy rename to src/main/java/biz/nellemann/hmci/MetaSystem.java index 6f50bb9..4176e09 100644 --- a/src/main/groovy/biz/nellemann/hmci/MetaSystem.groovy +++ b/src/main/java/biz/nellemann/hmci/MetaSystem.java @@ -13,35 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package biz.nellemann.hmci +package biz.nellemann.hmci; -import biz.nellemann.hmci.pcm.PcmData -import com.squareup.moshi.FromJson -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.Moshi -import com.squareup.moshi.ToJson -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j +import biz.nellemann.hmci.pcm.PcmData; +import com.serjltt.moshi.adapters.FirstElement; +import com.squareup.moshi.FromJson; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.ToJson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.time.Instant -import java.time.format.DateTimeFormatter -import java.time.format.DateTimeParseException +import java.math.BigDecimal; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; -@Slf4j -@CompileStatic abstract class MetaSystem { - private final Moshi moshi; + private final static Logger log = LoggerFactory.getLogger(MetaSystem.class); + private final JsonAdapter jsonAdapter; - protected PcmData metrics + protected PcmData metrics; MetaSystem() { try { - moshi = new Moshi.Builder().add(new NumberAdapter()).add(new BigDecimalAdapter())build(); + Moshi moshi = new Moshi.Builder().add(new NumberAdapter()).add(new BigDecimalAdapter()).add(FirstElement.ADAPTER_FACTORY).build(); jsonAdapter = moshi.adapter(PcmData.class); } catch(Exception e) { - log.warn("MetaSystem() error", e) + log.warn("MetaSystem() error", e); throw new ExceptionInInitializerError(e); } } @@ -52,7 +53,7 @@ abstract class MetaSystem { try { metrics = jsonAdapter.fromJson(json); } catch(Exception e) { - log.warn("processMetrics() error", e) + log.warn("processMetrics() error", e); } //Map pcmMap = new JsonSlurper().parseText(json) as Map @@ -62,22 +63,22 @@ abstract class MetaSystem { //@CompileDynamic Instant getTimestamp() { - String timestamp = metrics.systemUtil.utilSamples.first().sampleInfo.timeStamp - Instant instant = null + String timestamp = metrics.systemUtil.sample.sampleInfo.timeStamp; + Instant instant = Instant.now(); try { - log.debug("getTimeStamp() - PMC Timestamp: " + timestamp) + log.debug("getTimeStamp() - PMC Timestamp: " + timestamp); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[XXX][X]"); - instant = Instant.from(dateTimeFormatter.parse(timestamp)) - log.debug("getTimestamp() - Instant: " + instant.toString()) + instant = Instant.from(dateTimeFormatter.parse(timestamp)); + log.debug("getTimestamp() - Instant: " + instant.toString()); } catch(DateTimeParseException e) { - log.warn("getTimestamp() - parse error: " + timestamp) + log.warn("getTimestamp() - parse error: " + timestamp); } - return instant ?: Instant.now() + return instant; } - class BigDecimalAdapter { + static class BigDecimalAdapter { @FromJson BigDecimal fromJson(String string) { @@ -90,7 +91,7 @@ abstract class MetaSystem { } } - class NumberAdapter { + static class NumberAdapter { @FromJson Number fromJson(String string) { diff --git a/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java index d91235c..e705870 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java @@ -1,18 +1,32 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; + import java.util.List; public class FiberChannelAdapter { - String id; - String wwpn; - String physicalLocation; - Integer numOfPorts; - List numOfReads; - List numOfWrites; - List readBytes; - List writeBytes; - List runningSpeed; - List transmittedBytes; + public String id; + public String wwpn; + public String physicalLocation; + public Integer numOfPorts; + + @FirstElement + public Number numOfReads; + + @FirstElement + public Number numOfWrites; + + @FirstElement + public Number readBytes; + + @FirstElement + public Number writeBytes; + + @FirstElement + public Number runningSpeed; + + @FirstElement + public Number transmittedBytes; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java index c2dbeea..382512e 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericAdapter.java @@ -4,14 +4,14 @@ import java.util.List; public class GenericAdapter { - String id; - String type; - String physicalLocation; - List receivedPackets; - List sentPackets; - List droppedPackets; - List sentBytes; - List receivedBytes; - List transferredBytes; + public String id; + public String type; + public String physicalLocation; + public List receivedPackets; + public List sentPackets; + public List droppedPackets; + public List sentBytes; + public List receivedBytes; + public List transferredBytes; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java index 008c716..2ec8a35 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java @@ -1,16 +1,28 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; + import java.util.List; public class GenericPhysicalAdapters { - String id; - String type; - String physicalLocation; - List numOfReads; - List numOfWrites; - List readBytes; - List writeBytes; - List transmittedBytes; + public String id; + public String type; + public String physicalLocation; + + @FirstElement + public Number numOfReads; + + @FirstElement + public Number numOfWrites; + + @FirstElement + public Number readBytes; + + @FirstElement + public Number writeBytes; + + @FirstElement + public Number transmittedBytes; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java index cff608a..9fe11d6 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericVirtualAdapter.java @@ -1,17 +1,28 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; + public class GenericVirtualAdapter { - String id; - String type; - Integer viosId; - String physicalLocation; - List numOfReads; - List numOfWrites; - List readBytes; - List writeBytes; - List transmittedBytes; + public String id; + public String type; + public Integer viosId; + public String physicalLocation; + + @FirstElement + public Number numOfReads; + + @FirstElement + public Number numOfWrites; + + @FirstElement + public Number readBytes; + + @FirstElement + public Number writeBytes; + + @FirstElement + public Number transmittedBytes; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java b/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java index 025022f..1ab35f0 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java +++ b/src/main/java/biz/nellemann/hmci/pcm/LparMemory.java @@ -1,10 +1,13 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; public class LparMemory { - List logicalMem; - List backedPhysicalMem; + @FirstElement + public Number logicalMem; + + @FirstElement + public Number backedPhysicalMem; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java index d6e18a3..89fe88f 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java +++ b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java @@ -1,22 +1,46 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; + import java.util.List; public class LparProcessor { - Integer poolId; - Integer weight; - String mode; - List maxVirtualProcessors; - List currentVirtualProcessors; - List maxProcUnits; - List entitledProcUnits; - List utilizedProcUnits; - List utilizedCappedProcUnits; - List utilizedUncappedProcUnits; - List idleProcUnits; - List donatedProcUnits; - List timeSpentWaitingForDispatch; - List timePerInstructionExecution; + public Integer poolId; + public Integer weight; + public String mode; + + @FirstElement + public Number maxVirtualProcessors; + + @FirstElement + public Number currentVirtualProcessors; + + @FirstElement + public Number maxProcUnits; + + @FirstElement + public Number entitledProcUnits; + + @FirstElement + public Number utilizedProcUnits; + + @FirstElement + public Number utilizedCappedProcUnits; + + @FirstElement + public Number utilizedUncappedProcUnits; + + @FirstElement + public Number idleProcUnits; + + @FirstElement + public Number donatedProcUnits; + + @FirstElement + public Number timeSpentWaitingForDispatch; + + @FirstElement + public Number timePerInstructionExecution; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java b/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java index ffa50af..9e2f918 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java +++ b/src/main/java/biz/nellemann/hmci/pcm/LparUtil.java @@ -2,17 +2,17 @@ package biz.nellemann.hmci.pcm; public class LparUtil { - Integer id; - String uuid; - String name; - String state; - String type; - String osType; - Integer affinityScore; + public Integer id; + public String uuid; + public String name; + public String state; + public String type; + public String osType; + public Number affinityScore; - LparMemory memory; - LparProcessor processor; - Network network; - Storage storage; + public LparMemory memory; + public LparProcessor processor; + public Network network = new Network(); + public Storage storage = new Storage(); } diff --git a/src/main/java/biz/nellemann/hmci/pcm/Network.java b/src/main/java/biz/nellemann/hmci/pcm/Network.java index 053c148..dd2df78 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/Network.java +++ b/src/main/java/biz/nellemann/hmci/pcm/Network.java @@ -1,11 +1,12 @@ package biz.nellemann.hmci.pcm; +import java.util.ArrayList; import java.util.List; public class Network { - List genericAdapters; - List sharedAdapters; - List virtualEthernetAdapters; + public List genericAdapters = new ArrayList<>(); + public List sharedAdapters = new ArrayList<>(); + public List virtualEthernetAdapters = new ArrayList<>(); } diff --git a/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java b/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java index 443c661..09082cd 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java +++ b/src/main/java/biz/nellemann/hmci/pcm/PhysicalProcessorPool.java @@ -4,10 +4,10 @@ import java.util.List; public class PhysicalProcessorPool { - List assignedProcUnits; - List utilizedProcUnits; - List availableProcUnits; - List configuredProcUnits; - List borrowedProcUnits; + public List assignedProcUnits; + public List utilizedProcUnits; + public List availableProcUnits; + public List configuredProcUnits; + public List borrowedProcUnits; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java b/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java index d5a2fcc..2665d51 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java +++ b/src/main/java/biz/nellemann/hmci/pcm/SampleInfo.java @@ -3,6 +3,6 @@ package biz.nellemann.hmci.pcm; public class SampleInfo { public String timeStamp; - Integer status; + public Integer status; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java index b835a0d..f8d1f72 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java @@ -1,12 +1,22 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; +import com.squareup.moshi.Json; + import java.util.List; public class ServerMemory { - List totalMem; - List availableMem; - List configurableMem; - List assignedMemToLpars; + @FirstElement + public Number totalMem; + + @FirstElement + public Number availableMem; + + @FirstElement + public Number configurableMem; + + @FirstElement + public Number assignedMemToLpars; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java b/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java index 0da20ae..47ffe57 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerProcessor.java @@ -1,12 +1,19 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; public class ServerProcessor { - List totalProcUnits; - List utilizedProcUnits; - List availableProcUnits; - List configurableProcUnits; + @FirstElement + public Number totalProcUnits; + + @FirstElement + public Number utilizedProcUnits; + + @FirstElement + public Number availableProcUnits; + + @FirstElement + public Number configurableProcUnits; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java b/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java index 2b027b6..ea6778f 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerUtil.java @@ -4,9 +4,9 @@ import java.util.List; public class ServerUtil { - ServerProcessor processor; - ServerMemory memory; - PhysicalProcessorPool physicalProcessorPool; - List sharedProcessorPool; + public ServerProcessor processor; + public ServerMemory memory; + public PhysicalProcessorPool physicalProcessorPool; + public List sharedProcessorPool; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java index 5ba0e07..5a481e9 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/SharedAdapter.java @@ -1,18 +1,32 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; public class SharedAdapter { - String id; - String type; - String physicalLocation; - List receivedPackets; - List sentPackets; - List droppedPackets; - List sentBytes; - List receivedBytes; - List transferredBytes; - List bridgedAdapters; + public String id; + public String type; + public String physicalLocation; + + @FirstElement + public Number receivedPackets; + + @FirstElement + public Number sentPackets; + + @FirstElement + public Number droppedPackets; + + @FirstElement + public Number sentBytes; + + @FirstElement + public Number receivedBytes; + + @FirstElement + public Number transferredBytes; + + @FirstElement + public String bridgedAdapters; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java b/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java index 5d86d38..6947081 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java +++ b/src/main/java/biz/nellemann/hmci/pcm/SharedProcessorPool.java @@ -1,15 +1,25 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; public class SharedProcessorPool { - String id; - String name; - List assignedProcUnits; - List utilizedProcUnits; - List availableProcUnits; - List configuredProcUnits; - List borrowedProcUnits; + public String id; + public String name; + + @FirstElement + public Number assignedProcUnits; + + @FirstElement + public Number utilizedProcUnits; + + @FirstElement + public Number availableProcUnits; + + @FirstElement + public Number configuredProcUnits; + + @FirstElement + public Number borrowedProcUnits; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/Storage.java b/src/main/java/biz/nellemann/hmci/pcm/Storage.java index 8c854ac..66c6c85 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/Storage.java +++ b/src/main/java/biz/nellemann/hmci/pcm/Storage.java @@ -1,13 +1,15 @@ package biz.nellemann.hmci.pcm; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; public class Storage { - List clientLpars; - List genericPhysicalAdapters; - List genericVirtualAdapters; - List fiberChannelAdapters; - List virtualFiberChannelAdapters; + public List clientLpars = new ArrayList<>(); + public List genericPhysicalAdapters = new ArrayList<>(); + public List genericVirtualAdapters = new ArrayList<>(); + public List fiberChannelAdapters = new ArrayList<>(); + public List virtualFiberChannelAdapters = new ArrayList<>(); } diff --git a/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java b/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java index f2eedb6..783cb93 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java +++ b/src/main/java/biz/nellemann/hmci/pcm/SystemUtil.java @@ -1,10 +1,14 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; +import com.squareup.moshi.Json; public class SystemUtil { - UtilInfo utilInfo; - public List utilSamples; + public UtilInfo utilInfo; + + @FirstElement + @Json(name = "utilSamples") + public UtilSample sample; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java b/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java index b8ceaa2..8a3271a 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java +++ b/src/main/java/biz/nellemann/hmci/pcm/UtilInfo.java @@ -4,14 +4,14 @@ import java.util.List; public class UtilInfo { - String version; - String metricType; - Integer frequency; - String startTimeStamp; - String endTimeStamp; - String mtms; - String name; - String uuid; - List metricArrayOrder; + public String version; + public String metricType; + public Integer frequency; + public String startTimeStamp; + public String endTimeStamp; + public String mtms; + public String name; + public String uuid; + public List metricArrayOrder; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java b/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java index 6298c6c..5652644 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java +++ b/src/main/java/biz/nellemann/hmci/pcm/UtilSample.java @@ -1,13 +1,28 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; + +import java.util.ArrayList; import java.util.List; public class UtilSample { - String sampleType; + public String sampleType; public SampleInfo sampleInfo; - ServerUtil serverUtil; - List viosUtil; - List lparsUtil; + public ServerUtil serverUtil; + public List viosUtil = new ArrayList<>(); + + @FirstElement + public LparUtil lparsUtil; + + /* + public LparUtil getLparsUtil() { + if(lparsUtil == null || lparsUtil.isEmpty()) { + return new LparUtil(); + } else { + return lparsUtil.get(0); + } + }*/ + } diff --git a/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java b/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java index 449299d..8643321 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ViosMemory.java @@ -1,10 +1,13 @@ package biz.nellemann.hmci.pcm; -import java.util.List; +import com.serjltt.moshi.adapters.FirstElement; public class ViosMemory { - List assignedMem; - List utilizedMem; + @FirstElement + public Number assignedMem; + + @FirstElement + public Number utilizedMem; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java b/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java index ff5fce3..178b39e 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ViosUtil.java @@ -2,15 +2,15 @@ package biz.nellemann.hmci.pcm; public class ViosUtil { - String id; - String uuid; - String name; - String state; - Integer affinityScore; + public String id; + public String uuid; + public String name; + public String state; + public Integer affinityScore; - ViosMemory memory; - LparProcessor processor; - Network network; - Storage storage; + public ViosMemory memory; + public LparProcessor processor; + public Network network; + public Storage storage; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java index f1498a4..910e39b 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java @@ -1,26 +1,52 @@ package biz.nellemann.hmci.pcm; +import com.serjltt.moshi.adapters.FirstElement; + import java.util.List; public class VirtualEthernetAdapter { - String physicalLocation; - Integer vlanId; - Integer vswitchId; - Boolean isPortVlanId; - Integer viosId; - String sharedEthernetAdapterId; - List receivedPackets; - List sentPackets; - List droppedPackets; - List sentBytes; - List receivedBytes; - List receivedPhysicalPackets; - List sentPhysicalPackets; - List droppedPhysicalPackets; - List sentPhysicalBytes; - List receivedPhysicalBytes; - List transferredBytes; - List transferredPhysicalBytes; + public String physicalLocation; + public Integer vlanId; + public Integer vswitchId; + public Boolean isPortVlanId; + public Integer viosId; + public String sharedEthernetAdapterId; + + @FirstElement + public Number receivedPackets; + + @FirstElement + public Number sentPackets; + + @FirstElement + public Number droppedPackets; + + @FirstElement + public Number sentBytes; + + @FirstElement + public Number receivedBytes; + + @FirstElement + public Number receivedPhysicalPackets; + + @FirstElement + public Number sentPhysicalPackets; + + @FirstElement + public Number droppedPhysicalPackets; + + @FirstElement + public Number sentPhysicalBytes; + + @FirstElement + public Number receivedPhysicalBytes; + + @FirstElement + public Number transferredBytes; + + @FirstElement + public Number transferredPhysicalBytes; } diff --git a/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java index df3192a..3a3066c 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/VirtualFiberChannelAdapter.java @@ -4,16 +4,16 @@ import java.util.List; public class VirtualFiberChannelAdapter { - String wwpn; - String wwpn2; - String physicalLocation; - String physicalPortWWPN; - Integer viosId; - List numOfReads; - List numOfWrites; - List readBytes; - List writeBytes; - List runningSpeed; - List transmittedBytes; + public String wwpn; + public String wwpn2; + public String physicalLocation; + public String physicalPortWWPN; + public Integer viosId; + public List numOfReads; + public List numOfWrites; + public List readBytes; + public List writeBytes; + public List runningSpeed; + public List transmittedBytes; } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index c394543..cee78fd 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -3,7 +3,7 @@ - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{12} - %msg%n + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n diff --git a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy index 3445c82..9089ee7 100644 --- a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy @@ -17,9 +17,9 @@ class LogicalPartitionTest extends Specification { lpar.processMetrics(testJson) then: - lpar.metrics.systemUtil.utilSamples.first().lparsUtil.first().memory.logicalMem.first() == 8192.000 - lpar.metrics.systemUtil.utilSamples.first().lparsUtil.first().processor.utilizedProcUnits.first() == 0.001 - lpar.metrics.systemUtil.utilSamples.first().lparsUtil.first().network.virtualEthernetAdapters.first().receivedBytes.first() == 276.467 + lpar.metrics.systemUtil.sample.lparsUtil.memory.logicalMem == 8192.000 + lpar.metrics.systemUtil.sample.lparsUtil.processor.utilizedProcUnits == 0.001 + lpar.metrics.systemUtil.sample.lparsUtil.network.virtualEthernetAdapters.first().receivedBytes == 276.467 } diff --git a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy index 9f58ffc..6643322 100644 --- a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy @@ -15,12 +15,12 @@ class ManagedSystemTest extends Specification { system.processMetrics(testJson) then: - system.metrics.systemUtil.utilSamples.first().serverUtil.memory.assignedMemToLpars.first() == 40960.000 - system.metrics.systemUtil.utilSamples.first().serverUtil.processor.totalProcUnits.first() == 24.000 - system.metrics.systemUtil.utilSamples.first().viosUtil.first().name == "VIOS1" - system.metrics.systemUtil.utilSamples.first().viosUtil.first().memory.assignedMem.first() == 8192.000 - system.metrics.systemUtil.utilSamples.first().viosUtil.first().storage.genericPhysicalAdapters.first().transmittedBytes.first() == 9966.933 - system.metrics.systemUtil.utilSamples.first().viosUtil.first().storage.fiberChannelAdapters.first().numOfPorts == 3 + system.metrics.systemUtil.sample.serverUtil.memory.assignedMemToLpars == 40960.000 + system.metrics.systemUtil.sample.serverUtil.processor.totalProcUnits == 24.000 + system.metrics.systemUtil.sample.viosUtil.first().name == "VIOS1" + system.metrics.systemUtil.sample.viosUtil.first().memory.assignedMem == 8192.0 + system.metrics.systemUtil.sample.viosUtil.first().storage.genericPhysicalAdapters.first().transmittedBytes == 9966.933 + system.metrics.systemUtil.sample.viosUtil.first().storage.fiberChannelAdapters.first().numOfPorts == 3 } From 3474ee17906f349c42332bf8d68ac270a49d3ff4 Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Mon, 12 Oct 2020 10:15:53 +0200 Subject: [PATCH 4/4] More refactoring work, cleanup and improvements. --- build.gradle | 2 +- gradle.properties | 2 +- .../biz/nellemann/hmci/Configuration.java | 43 +++++++-- .../java/biz/nellemann/hmci/HmcClient.java | 90 ++++++++----------- .../java/biz/nellemann/hmci/InfluxClient.java | 2 +- .../java/biz/nellemann/hmci/Insights.java | 33 ++++--- .../biz/nellemann/hmci/LogicalPartition.java | 10 +-- src/main/java/biz/nellemann/hmci/Main.java | 1 + .../biz/nellemann/hmci/ManagedSystem.java | 4 +- .../java/biz/nellemann/hmci/MetaSystem.java | 2 +- .../hmci/pcm/FiberChannelAdapter.java | 2 - .../hmci/pcm/GenericPhysicalAdapters.java | 2 - .../biz/nellemann/hmci/pcm/LparProcessor.java | 2 - .../biz/nellemann/hmci/pcm/ServerMemory.java | 3 - .../java/biz/nellemann/hmci/pcm/Storage.java | 1 - .../hmci/pcm/VirtualEthernetAdapter.java | 2 - .../nellemann/hmci/ConfigurationTest.groovy | 4 +- .../biz/nellemann/hmci/HmcClientTest.groovy | 14 +-- .../nellemann/hmci/InfluxClientTest.groovy | 2 +- 19 files changed, 111 insertions(+), 110 deletions(-) diff --git a/build.gradle b/build.gradle index cd4aa0a..b1ae0e2 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ ospackage { buildRpm { dependsOn startShadowScripts - os = LINUX + os = "LINUX" } buildDeb { diff --git a/gradle.properties b/gradle.properties index a1e7b9a..5077ec8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ id = hmci group = biz.nellemann.hmci -version = 1.0.10 +version = 0.2.1 diff --git a/src/main/java/biz/nellemann/hmci/Configuration.java b/src/main/java/biz/nellemann/hmci/Configuration.java index f285c3d..967c026 100644 --- a/src/main/java/biz/nellemann/hmci/Configuration.java +++ b/src/main/java/biz/nellemann/hmci/Configuration.java @@ -26,18 +26,17 @@ public class Configuration { Path source = Paths.get(configurationFile); TomlParseResult result = Toml.parse(source); result.errors().forEach(error -> System.err.println(error.toString())); - //System.out.println(result.toJson()); if(result.contains("refresh")) { refresh = result.getLong("refresh"); } else { - refresh = 15l; + refresh = 15L; } if(result.contains("rescan")) { rescan = result.getLong("rescan"); } else { - rescan = 60l; + rescan = 60L; } hmc = getHmc(result); @@ -52,6 +51,9 @@ public class Configuration { if(result.contains("hmc") && result.isTable("hmc")) { TomlTable hmcTable = result.getTable("hmc"); + if(hmcTable == null) { + return list; + } for(String key : hmcTable.keySet()) { HmcObject c = new HmcObject(); @@ -119,17 +121,30 @@ public class Configuration { String password = ""; String database = "hmci"; - private boolean isValid = false; + private boolean validated = false; + + InfluxObject() { } + + InfluxObject(String url, String username, String password, String database) { + this.url = url; + this.username = username; + this.password = password; + this.database = database; + } Boolean isValid() { - return isValid(); + return validated; } // TODO: Fixme void validate() { - isValid = true; + validated = true; } + @Override + public String toString() { + return url; + } } @@ -141,15 +156,25 @@ public class Configuration { String password; Boolean unsafe = false; - private boolean isValid = false; + private boolean validated = false; + + HmcObject() { } + + HmcObject(String url, String username, String password, Boolean unsafe) { + this.url = url; + this.username = username; + this.password = password; + this.unsafe = unsafe; + } + Boolean isValid() { - return isValid(); + return validated; } // TODO: Fixme void validate() { - isValid = true; + validated = true; } @Override diff --git a/src/main/java/biz/nellemann/hmci/HmcClient.java b/src/main/java/biz/nellemann/hmci/HmcClient.java index 34260ad..453509f 100644 --- a/src/main/java/biz/nellemann/hmci/HmcClient.java +++ b/src/main/java/biz/nellemann/hmci/HmcClient.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import javax.net.ssl.*; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; import java.security.SecureRandom; import java.security.cert.CertificateException; @@ -44,7 +45,6 @@ class HmcClient { private final String baseUrl; private final String username; private final String password; - private final Boolean unsafe; protected Integer responseErrors = 0; protected String authToken; @@ -57,7 +57,7 @@ class HmcClient { this.baseUrl = configHmc.url; this.username = configHmc.username; this.password = configHmc.password; - this.unsafe = configHmc.unsafe; + Boolean unsafe = configHmc.unsafe; if(unsafe) { this.client = getUnsafeOkHttpClient(); @@ -70,7 +70,6 @@ class HmcClient { /** * Logon to the HMC and get an authentication token for further requests. - * @throws Exception */ void login() throws Exception { this.login(false); @@ -80,7 +79,6 @@ class HmcClient { /** * Logon to the HMC and get an authentication token for further requests. * @param force - * @throws Exception */ void login(Boolean force) throws Exception { @@ -97,8 +95,9 @@ class HmcClient { payload.append("").append(password).append(""); payload.append(""); - URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl)); - Request request = new Request.Builder() + try { + URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl)); + Request request = new Request.Builder() .url(url) //.addHeader("Content-Type", "application/vnd.ibm.powervm.web+xml; type=LogonRequest") .addHeader("Accept", "application/vnd.ibm.powervm.web+xml; type=LogonResponse") @@ -106,21 +105,23 @@ class HmcClient { .put(RequestBody.create(payload.toString(), MEDIA_TYPE_IBM_XML_LOGIN)) .build(); - try { Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); // Get response body and parse - String responseBody = response.body().string(); - response.body().close(); + String responseBody = Objects.requireNonNull(response.body()).string(); + Objects.requireNonNull(response.body()).close(); Document doc = Jsoup.parse(responseBody); authToken = doc.select("X-API-Session").text(); log.debug("login() - Auth Token: " + authToken); + } catch (MalformedURLException e) { + log.error("login() - url error", e); + throw new Exception(new Throwable("Login URL Error: " + e.getMessage())); } catch(Exception e) { - log.error(e.getMessage()); - throw new Exception(e); + log.error("login() - general error", e); + throw new Exception(new Throwable("Login General Error: " + e.getMessage())); } } @@ -157,14 +158,14 @@ class HmcClient { /** * Return Map of ManagedSystems seen by this HMC * - * @return + * @return Map of system-id and ManagedSystem */ Map getManagedSystems() throws Exception { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl)); Response response = getResponse(url); String responseBody = Objects.requireNonNull(response.body()).string(); - Map managedSystemsMap = new HashMap(); + Map managedSystemsMap = new HashMap<>(); // Do not try to parse empty response if(responseBody.isEmpty() || responseBody.length() <= 1) { @@ -185,7 +186,7 @@ class HmcClient { el.select("MachineTypeModelAndSerialNumber > SerialNumber").text() ); managedSystemsMap.put(system.id, system); - log.info("getManagedSystems() - Found system: " + system.toString()); + log.debug("getManagedSystems() - Found system: " + system.toString()); } } catch(Exception e) { @@ -199,8 +200,8 @@ class HmcClient { /** * Return Map of LogicalPartitions seen by a ManagedSystem on this HMC - * @param system - * @return + * @param system a valid ManagedSystem + * @return Map of partition-id and LogicalPartition */ Map getLogicalPartitionsForManagedSystem(ManagedSystem system) throws Exception { URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id)); @@ -225,7 +226,7 @@ class HmcClient { system ); partitionMap.put(logicalPartition.id, logicalPartition); - log.info("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()); + log.debug("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString()); } } catch(Exception e) { @@ -239,8 +240,8 @@ class HmcClient { /** * Parse XML feed to get PCM Data in JSON format - * @param system - * @return + * @param system a valid ManagedSystem + * @return JSON string with PCM data for this ManagedSystem */ String getPcmDataForManagedSystem(ManagedSystem system) throws Exception { @@ -254,7 +255,7 @@ class HmcClient { if(responseBody.isEmpty() || responseBody.length() <= 1) { responseErrors++; log.warn("getPcmDataForManagedSystem() - empty response"); - return jsonBody; + return null; } try { @@ -278,8 +279,8 @@ class HmcClient { /** * Parse XML feed to get PCM Data in JSON format - * @param partition - * @return + * @param partition a valid LogicalPartition + * @return JSON string with PCM data for this LogicalPartition */ String getPcmDataForLogicalPartition(LogicalPartition partition) throws Exception { @@ -293,7 +294,7 @@ class HmcClient { if(responseBody.isEmpty() || responseBody.length() <= 1) { responseErrors++; log.warn("getPcmDataForLogicalPartition() - empty response"); - return jsonBody; + return null; } try { @@ -310,19 +311,6 @@ class HmcClient { } catch(Exception e) { log.warn("getPcmDataForLogicalPartition() - xml parse error", e); } - /* - try { - Document doc = Jsoup.parse(responseBody); - Element entry = doc.select("entry").first(); - Element link = entry.select("link[href]").first(); - if(link.attr("type") == "application/json") { - String href = (String) link.attr("href"); - log.debug("getPcmDataForLogicalPartition() - json url: " + href); - jsonBody = getResponseBody(new URL(href)); - } - } catch(Exception e) { - log.warn("getPcmDataForLogicalPartition() - xml parse error", e); - }*/ return jsonBody; } @@ -331,8 +319,8 @@ class HmcClient { /** * Return body text from a HTTP response from the HMC * - * @param url - * @return + * @param url URL to get response body as String + * @return String with http reponse body */ protected String getResponseBody(URL url) throws Exception { Response response = getResponse(url); @@ -344,8 +332,8 @@ class HmcClient { /** * Return a Response from the HMC - * @param url - * @return + * @param url to get Response from + * @return Response object */ private Response getResponse(URL url) throws Exception { return getResponse(url, 0); @@ -354,9 +342,9 @@ class HmcClient { /** * Return a Response from the HMC - * @param url - * @param retry - * @return + * @param url to get Response from + * @param retry number of retries for this call + * @return Response object */ private Response getResponse(URL url, Integer retry) throws Exception { @@ -377,7 +365,7 @@ class HmcClient { Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { - response.body().close(); + Objects.requireNonNull(response.body()).close(); if(response.code() == 401) { login(true); @@ -391,7 +379,7 @@ class HmcClient { log.error("getResponse() - Unexpected response: " + response.code()); throw new IOException("getResponse() - Unexpected response: " + response.code()); - }; + } return response; } @@ -432,15 +420,9 @@ class HmcClient { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]); - builder.hostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }); + builder.hostnameVerifier((hostname, session) -> true); - OkHttpClient okHttpClient = builder.build(); - return okHttpClient; + return builder.build(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/biz/nellemann/hmci/InfluxClient.java b/src/main/java/biz/nellemann/hmci/InfluxClient.java index 8d26f9d..39c3519 100644 --- a/src/main/java/biz/nellemann/hmci/InfluxClient.java +++ b/src/main/java/biz/nellemann/hmci/InfluxClient.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/main/java/biz/nellemann/hmci/Insights.java b/src/main/java/biz/nellemann/hmci/Insights.java index e1dcc20..fa02b8b 100644 --- a/src/main/java/biz/nellemann/hmci/Insights.java +++ b/src/main/java/biz/nellemann/hmci/Insights.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,9 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import static java.lang.Thread.*; class Insights { @@ -28,9 +31,9 @@ class Insights { final Configuration configuration; InfluxClient influxClient; - Map hmcClients = new HashMap<>(); - Map systems = new HashMap(); - Map partitions = new HashMap(); + final Map hmcClients = new HashMap<>(); + final Map systems = new HashMap<>(); + final Map partitions = new HashMap<>(); Insights(Configuration configuration) { @@ -52,7 +55,6 @@ class Insights { configuration.hmc.forEach( configHmc -> { if(hmcClients != null && !hmcClients.containsKey(configHmc.name)) { - log.debug("Adding HMC: " + configHmc.toString()); HmcClient hmcClient = new HmcClient(configHmc); hmcClients.put(configHmc.name, hmcClient); } @@ -82,7 +84,6 @@ class Insights { } catch(Exception e) { log.error("discover() - " + hmcId + " error: " + e.getMessage()); - //hmcClients.remove(hmcId); } }); @@ -102,7 +103,6 @@ class Insights { tmpJsonString = hmcClient.getPcmDataForManagedSystem(system); } catch (Exception e) { log.error("getMetricsForSystems()", e); - //e.printStackTrace(); } if(tmpJsonString != null && !tmpJsonString.isEmpty()) { @@ -128,7 +128,7 @@ class Insights { try { tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition); } catch (Exception e) { - log.error("getMetricsForPartitions()", e); + log.error("getMetricsForPartitions() - getPcmDataForLogicalPartition", e); } if(tmpJsonString2 != null && !tmpJsonString2.isEmpty()) { partition.processMetrics(tmpJsonString2); @@ -160,8 +160,12 @@ class Insights { log.debug("run()"); int executions = 0; + AtomicBoolean keepRunning = new AtomicBoolean(true); - while(true) { + Thread shutdownHook = new Thread(() -> keepRunning.set(false)); + Runtime.getRuntime().addShutdownHook(shutdownHook); + + do { try { getMetricsForSystems(); @@ -172,17 +176,18 @@ class Insights { influxClient.writeBatchPoints(); // Refresh HMC's - if(executions > configuration.rescan) { + if (executions > configuration.rescan) { executions = 0; discover(); } - } catch(Exception e) { - log.error("run()", e.getMessage()); + } catch (Exception e) { + log.error("run()", e); } executions++; - Thread.sleep(configuration.refresh * 1000); - } + sleep(configuration.refresh * 1000); + + } while (keepRunning.get()); } diff --git a/src/main/java/biz/nellemann/hmci/LogicalPartition.java b/src/main/java/biz/nellemann/hmci/LogicalPartition.java index ac3a436..3e64f45 100644 --- a/src/main/java/biz/nellemann/hmci/LogicalPartition.java +++ b/src/main/java/biz/nellemann/hmci/LogicalPartition.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,10 +27,10 @@ class LogicalPartition extends MetaSystem { private final static Logger log = LoggerFactory.getLogger(LogicalPartition.class); - public String id; - public String name; - public String type; - public ManagedSystem system; + public final String id; + public final String name; + public final String type; + public final ManagedSystem system; LogicalPartition(String id, String name, String type, ManagedSystem system) { diff --git a/src/main/java/biz/nellemann/hmci/Main.java b/src/main/java/biz/nellemann/hmci/Main.java index 82d0487..00e002d 100644 --- a/src/main/java/biz/nellemann/hmci/Main.java +++ b/src/main/java/biz/nellemann/hmci/Main.java @@ -32,6 +32,7 @@ public class Main implements Callable { private final static Logger log = LoggerFactory.getLogger(Main.class); + @SuppressWarnings("FieldMayBeFinal") @CommandLine.Option(names = { "-c", "--conf" }, description = "Configuration file [default: '/etc/hmci.toml'].") private String configurationFile = "/etc/hmci.toml"; diff --git a/src/main/java/biz/nellemann/hmci/ManagedSystem.java b/src/main/java/biz/nellemann/hmci/ManagedSystem.java index 84c1a3d..0a19ebc 100644 --- a/src/main/java/biz/nellemann/hmci/ManagedSystem.java +++ b/src/main/java/biz/nellemann/hmci/ManagedSystem.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,7 +99,7 @@ class ManagedSystem extends MetaSystem { HashMap fieldsMap = new HashMap() { { - put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.totalProcUnits); + put("totalProcUnits", metrics.systemUtil.sample.serverUtil.processor.totalProcUnits); put("utilizedProcUnits", metrics.systemUtil.sample.serverUtil.processor.utilizedProcUnits); put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.availableProcUnits); put("configurableProcUnits", metrics.systemUtil.sample.serverUtil.processor.configurableProcUnits); diff --git a/src/main/java/biz/nellemann/hmci/MetaSystem.java b/src/main/java/biz/nellemann/hmci/MetaSystem.java index 4176e09..70a7575 100644 --- a/src/main/java/biz/nellemann/hmci/MetaSystem.java +++ b/src/main/java/biz/nellemann/hmci/MetaSystem.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2020 Mark Nellemann * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java index e705870..77902b2 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/FiberChannelAdapter.java @@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm; import com.serjltt.moshi.adapters.FirstElement; -import java.util.List; - public class FiberChannelAdapter { public String id; diff --git a/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java index 2ec8a35..a3766f3 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java +++ b/src/main/java/biz/nellemann/hmci/pcm/GenericPhysicalAdapters.java @@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm; import com.serjltt.moshi.adapters.FirstElement; -import java.util.List; - public class GenericPhysicalAdapters { public String id; diff --git a/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java index 89fe88f..5ed252a 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java +++ b/src/main/java/biz/nellemann/hmci/pcm/LparProcessor.java @@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm; import com.serjltt.moshi.adapters.FirstElement; -import java.util.List; - public class LparProcessor { public Integer poolId; diff --git a/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java index f8d1f72..cc78c83 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java +++ b/src/main/java/biz/nellemann/hmci/pcm/ServerMemory.java @@ -1,9 +1,6 @@ package biz.nellemann.hmci.pcm; import com.serjltt.moshi.adapters.FirstElement; -import com.squareup.moshi.Json; - -import java.util.List; public class ServerMemory { diff --git a/src/main/java/biz/nellemann/hmci/pcm/Storage.java b/src/main/java/biz/nellemann/hmci/pcm/Storage.java index 66c6c85..7dd9240 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/Storage.java +++ b/src/main/java/biz/nellemann/hmci/pcm/Storage.java @@ -2,7 +2,6 @@ package biz.nellemann.hmci.pcm; import java.util.ArrayList; import java.util.List; -import java.util.Optional; public class Storage { diff --git a/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java index 910e39b..87333d8 100644 --- a/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java +++ b/src/main/java/biz/nellemann/hmci/pcm/VirtualEthernetAdapter.java @@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm; import com.serjltt.moshi.adapters.FirstElement; -import java.util.List; - public class VirtualEthernetAdapter { public String physicalLocation; diff --git a/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy b/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy index b88eb18..5725185 100644 --- a/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/ConfigurationTest.groovy @@ -10,7 +10,7 @@ class ConfigurationTest extends Specification { void "test parsing"() { when: - Configuration conf = new Configuration(testConfigurationFile); + Configuration conf = new Configuration(testConfigurationFile) then: conf != null @@ -20,7 +20,7 @@ class ConfigurationTest extends Specification { void "test lookup influx"() { when: - Configuration conf = new Configuration(testConfigurationFile); + Configuration conf = new Configuration(testConfigurationFile) then: conf != null diff --git a/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy b/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy index 49f265b..8a3eb21 100644 --- a/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/HmcClientTest.groovy @@ -7,11 +7,11 @@ import spock.lang.Specification class HmcClientTest extends Specification { HmcClient hmc - MockWebServer mockServer = new MockWebServer(); + MockWebServer mockServer = new MockWebServer() def setup() { - mockServer.start(); + mockServer.start() Configuration.HmcObject configHmc = new Configuration.HmcObject() configHmc.name = "site1" configHmc.url = mockServer.url("/").toString() @@ -29,7 +29,7 @@ class HmcClientTest extends Specification { void "test against empty xml"() { setup: def testXml = "" - mockServer.enqueue(new MockResponse().setBody(testXml)); + mockServer.enqueue(new MockResponse().setBody(testXml)) when: Map systems = hmc.getManagedSystems() @@ -43,7 +43,7 @@ class HmcClientTest extends Specification { setup: def testFile = new File(getClass().getResource('/managed-systems.xml').toURI()) def testXml = testFile.getText('UTF-8') - mockServer.enqueue(new MockResponse().setBody(testXml)); + mockServer.enqueue(new MockResponse().setBody(testXml)) when: Map systems = hmc.getManagedSystems() @@ -58,7 +58,7 @@ class HmcClientTest extends Specification { setup: def testFile = new File(getClass().getResource('/logical-partitions.xml').toURI()) def testXml = testFile.getText('UTF-8') - mockServer.enqueue(new MockResponse().setBody(testXml)); + mockServer.enqueue(new MockResponse().setBody(testXml)) when: ManagedSystem system = new ManagedSystem("site1", "e09834d1-c930-3883-bdad-405d8e26e166", "Test Name","Test Type", "Test Model", "Test S/N") @@ -75,7 +75,7 @@ class HmcClientTest extends Specification { setup: def testFile = new File(getClass().getResource('/pcm-data-managed-system.json').toURI()) def testJson = testFile.getText('UTF-8') - mockServer.enqueue(new MockResponse().setBody(testJson)); + mockServer.enqueue(new MockResponse().setBody(testJson)) when: String jsonString = hmc.getResponseBody(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/ManagedSystem_e09834d1-c930-3883-bdad-405d8e26e166_20200807T122600+0200_20200807T122600+0200_30.json") as String)) @@ -89,7 +89,7 @@ class HmcClientTest extends Specification { setup: def testFile = new File(getClass().getResource('/pcm-data-logical-partition.json').toURI()) def testJson = testFile.getText('UTF-8') - mockServer.enqueue(new MockResponse().setBody(testJson)); + mockServer.enqueue(new MockResponse().setBody(testJson)) when: String jsonString = hmc.getResponseBody(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/LogicalPartition_2DE05DB6-8AD5-448F-8327-0F488D287E82_20200807T123730+0200_20200807T123730+0200_30.json") as String)) diff --git a/src/test/groovy/biz/nellemann/hmci/InfluxClientTest.groovy b/src/test/groovy/biz/nellemann/hmci/InfluxClientTest.groovy index c350134..c55bcc0 100644 --- a/src/test/groovy/biz/nellemann/hmci/InfluxClientTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/InfluxClientTest.groovy @@ -9,7 +9,7 @@ class InfluxClientTest extends Specification { InfluxClient influxClient def setup() { - influxClient = new InfluxClient("http://localhost:8086", "root", "", "hmci") + influxClient = new InfluxClient(new Configuration.InfluxObject("http://localhost:8086", "root", "", "hmci")) influxClient.login() }