More refactoring work, from Groovy to plain Java.

This commit is contained in:
Mark Nellemann 2020-10-11 12:25:55 +02:00
parent 3f71aabd4e
commit b005376941
41 changed files with 1337 additions and 1060 deletions

View File

@ -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 :)

View File

@ -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')

View File

@ -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
}
*/
}

31
doc/hmci.toml Normal file
View File

@ -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

View File

@ -1,176 +0,0 @@
/**
* Copyright 2020 Mark Nellemann <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 groovy.util.logging.Slf4j;
@Slf4j
@CompileStatic
class Insights {
final Configuration configuration;
InfluxClient influxClient;
Map<String, HmcClient> hmcClients = new HashMap<>();
Map<String,ManagedSystem> systems = new HashMap<String, ManagedSystem>();
Map<String, LogicalPartition> partitions = new HashMap<String, LogicalPartition>();
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)
}
}
}

View File

@ -1,194 +0,0 @@
/**
* Copyright 2020 Mark Nellemann <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.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<Measurement> getAffinityScore() {
List<Measurement> list = new ArrayList<>()
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = [
system: system.name,
partition: name,
]
//map.put("tags", tagsMap)
log.debug("getAffinityScore() - tags: " + tagsMap.toString())
HashMap<String, Number> fieldsMap = [
affinityScore: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.affinityScore,
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
log.debug("getAffinityScore() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement);
return list
}
@CompileDynamic
List<Measurement> getMemoryMetrics() {
List<Measurement> list = new ArrayList<>()
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = [
system: system.name,
partition: name,
]
//map.put("tags", tagsMap)
log.debug("getMemoryMetrics() - tags: " + tagsMap.toString())
HashMap<String, Number> fieldsMap = [
logicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.logicalMem?.first(),
backedPhysicalMem: metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.memory?.backedPhysicalMem?.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement);
return list
}
@CompileDynamic
List<Measurement> getProcessorMetrics() {
List<Measurement> list = new ArrayList<>()
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = [
system: system.name,
partition: name,
]
//map.put("tags", tagsMap)
log.debug("getProcessorMetrics() - tags: " + tagsMap.toString())
HashMap<String, Number> 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<String, Number>
//map.put("fields", fieldsMap)
log.debug("getProcessorMetrics() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement);
return list
}
@CompileDynamic
List<Measurement> getVirtualEthernetAdapterMetrics() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.network?.virtualEthernetAdapters?.each {
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> 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<String, Number> fieldsMap = [
receivedPhysicalBytes: it.receivedPhysicalBytes.first(),
sentPhysicalBytes: it.sentPhysicalBytes.first(),
receivedBytes: it.receivedBytes.first(),
sentBytes: it.sentBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
log.debug("getVirtualEthernetAdapterMetrics() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement);
}
return list
}
//PartitionVirtualFiberChannelAdapters
@CompileDynamic
List<Measurement> getVirtualFiberChannelAdaptersMetrics() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.lparsUtil?.first()?.storage?.virtualFiberChannelAdapters?.each {
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> 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<String, Number> fieldsMap = [
transmittedBytes: it.transmittedBytes.first(),
writeBytes: it.writeBytes.first(),
readBytes: it.readBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
log.debug("getVirtualFiberChannelAdaptersMetrics() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement);
}
return list
}
}

View File

@ -1,279 +0,0 @@
/**
* Copyright 2020 Mark Nellemann <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.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<Measurement> getMemoryMetrics() {
List<Measurement> list = new ArrayList<>()
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = [
system: name,
]
//map.put("tags", tagsMap)
log.debug("getMemoryMetrics() - tags: " + tagsMap.toString())
Map<String, Number> 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<String, Number>
//map.put("fields", fieldsMap)
log.debug("getMemoryMetrics() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement)
return list
}
@CompileDynamic
List<Measurement> getProcessorMetrics() {
List<Measurement> list = new ArrayList<>()
//Map<String, Map> map = new HashMap<>()
HashMap<String, String> tagsMap = [
system: name,
]
//map.put("tags", tagsMap)
//measurement.tags = tagsMap;
log.debug("getProcessorMetrics() - tags: " + tagsMap.toString())
HashMap<String, Number> 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<String, Number>
//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<Measurement> getSharedProcessorPools() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.serverUtil?.sharedProcessorPool?.each {
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = [
system: name,
pool: it.name,
]
//map.put("tags", tagsMap)
log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString())
HashMap<String, Number> fieldsMap = [
assignedProcUnits: it.assignedProcUnits.first(),
availableProcUnits: it.availableProcUnits.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
log.debug("getSharedProcessorPools() - fields: " + fieldsMap.toString())
Measurement measurement = new Measurement(tagsMap, fieldsMap);
list.add(measurement)
}
return list
}
@CompileDynamic
List<Measurement> getSystemSharedAdapters() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each {vios ->
vios.network.sharedAdapters.each {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> tagsMap = [
system: name,
type: it.type,
vios: vios.name,
]
//map.put("tags", tagsMap)
measurement.tags = tagsMap;
log.debug("getSystemSharedAdapters() - tags: " + tagsMap.toString())
HashMap<String, Number> fieldsMap = [
sentBytes: it.sentBytes.first(),
receivedBytes: it.receivedBytes.first(),
transferredBytes: it.transferredBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
measurement.fields = fieldsMap;
log.debug("getSystemSharedAdapters() - fields: " + fieldsMap.toString())
list.add(measurement)
}
}
return list
}
@CompileDynamic
List<Measurement> getSystemFiberChannelAdapters() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios ->
log.debug("getSystemFiberChannelAdapters() - VIOS: " + vios.name)
vios.storage?.fiberChannelAdapters?.each {
//HashMap<String, Map> map = new HashMap<>()
Measurement measurement = new Measurement();
HashMap<String, String> 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<String, Number> fieldsMap = [
writeBytes: it.writeBytes.first(),
readBytes: it.readBytes.first(),
transmittedBytes: it.transmittedBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
measurement.fields = fieldsMap;
log.debug("getSystemFiberChannelAdapters() - fields: " + fieldsMap.toString())
list.add(measurement)
}
}
return list
}
@CompileDynamic
List<Measurement> getSystemGenericPhysicalAdapters() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios ->
vios.storage?.genericPhysicalAdapters?.each {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> 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<String, Number> fieldsMap = [
writeBytes: it.writeBytes.first(),
readBytes: it.readBytes.first(),
transmittedBytes: it.transmittedBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
measurement.fields = fieldsMap;
log.debug("getSystemGenericPhysicalAdapters() - fields: " + fieldsMap.toString())
list.add(measurement)
}
}
return list
}
@CompileDynamic
List<Measurement> getSystemGenericVirtualAdapters() {
List<Measurement> list = new ArrayList<>()
metrics.systemUtil?.utilSamples?.first()?.viosUtil?.each { vios ->
vios.storage?.genericVirtualAdapters?.each {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> 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<String, Number> fieldsMap = [
writeBytes: it.writeBytes.first(),
readBytes: it.readBytes.first(),
transmittedBytes: it.transmittedBytes.first(),
] as HashMap<String, Number>
//map.put("fields", fieldsMap)
measurement.fields = fieldsMap;
log.debug("getSystemGenericVirtualAdapters() - fields: " + fieldsMap.toString())
list.add(measurement);
}
}
return list
}
}

View File

@ -139,7 +139,7 @@ public class Configuration {
String url;
String username;
String password;
Boolean unsafe;
Boolean unsafe = false;
private boolean isValid = false;

View File

@ -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 = """\
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LogonRequest xmlns="http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/" schemaVersion="V1_0">
<UserID>${username}</UserID>
<Password>${password}</Password>
</LogonRequest>"""
StringBuilder payload = new StringBuilder();
payload.append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
payload.append("<LogonRequest xmlns='http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/' schemaVersion='V1_0'>");
payload.append("<UserID>").append(username).append("</UserID>");
payload.append("<Password>").append(password).append("</Password>");
payload.append("</LogonRequest>");
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<String, ManagedSystem> getManagedSystems() {
URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl))
Response response = getResponse(url)
String responseBody = response.body().string()
Map<String,ManagedSystem> managedSystemsMap = new HashMap<String, ManagedSystem>()
Map<String, ManagedSystem> 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<String,ManagedSystem> managedSystemsMap = new HashMap<String, ManagedSystem>();
// 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<String, LogicalPartition> 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<String, LogicalPartition> partitionMap = new HashMap<String, LogicalPartition>() {}
Map<String, LogicalPartition> 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<String, LogicalPartition> partitionMap = new HashMap<String, LogicalPartition>() {};
// 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;
}

View File

@ -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<String, BigDecimal> 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)

View File

@ -0,0 +1,189 @@
/**
* Copyright 2020 Mark Nellemann <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 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<String, HmcClient> hmcClients = new HashMap<>();
Map<String,ManagedSystem> systems = new HashMap<String, ManagedSystem>();
Map<String, LogicalPartition> partitions = new HashMap<String, LogicalPartition>();
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);
}
}
}

View File

@ -0,0 +1,225 @@
/**
* Copyright 2020 Mark Nellemann <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 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<Measurement> getAffinityScore() {
List<Measurement> list = new ArrayList<>();
//Map<String, Map> map = new HashMap<String, Map>()
Map<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", system.name);
put("partition", name);
}
};
//map.put("tags", tagsMap)
log.debug("getAffinityScore() - tags: " + tagsMap.toString());
Map<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getMemoryMetrics() {
List<Measurement> list = new ArrayList<>();
//Map<String, Map> map = new HashMap<String, Map>()
Map<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", system.name);
put("partition", name);
}
};
//map.put("tags", tagsMap)
log.debug("getMemoryMetrics() - tags: " + tagsMap.toString());
Map<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getProcessorMetrics() {
List<Measurement> list = new ArrayList<>();
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", system.name);
put("partition", name);
}
};
//map.put("tags", tagsMap)
log.debug("getProcessorMetrics() - tags: " + tagsMap.toString());
HashMap<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getVirtualEthernetAdapterMetrics() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.lparsUtil.network.virtualEthernetAdapters.forEach( adapter -> {
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getVirtualFiberChannelAdaptersMetrics() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.lparsUtil.storage.virtualFiberChannelAdapters.forEach( adapter -> {
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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;
}
}

View File

@ -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<Integer> {
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<Integer> {
Configuration configuration = new Configuration(configurationFile);
Insights insights = new Insights(configuration);
insights.run();
try {
insights.run();
} catch (InterruptedException e) {
log.error(e.getMessage());
}
return 0;
}

View File

@ -0,0 +1,326 @@
/**
* Copyright 2020 Mark Nellemann <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 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<Measurement> getMemoryMetrics() {
List<Measurement> list = new ArrayList<>();
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", name);
}
};
//map.put("tags", tagsMap)
log.debug("getMemoryMetrics() - tags: " + tagsMap.toString());
Map<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getProcessorMetrics() {
List<Measurement> list = new ArrayList<>();
//Map<String, Map> map = new HashMap<>()
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", name);
}
};
//map.put("tags", tagsMap)
//measurement.tags = tagsMap;
log.debug("getProcessorMetrics() - tags: " + tagsMap.toString());
HashMap<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getSharedProcessorPools() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.serverUtil.sharedProcessorPool.forEach(adapter -> {
//Map<String, Map> map = new HashMap<String, Map>()
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
put("system", name);
put("pool", adapter.name);
}
};
//map.put("tags", tagsMap)
log.debug("getSharedProcessorPools() - tags: " + tagsMap.toString());
HashMap<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getSystemSharedAdapters() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.viosUtil.forEach(vios -> {
vios.network.sharedAdapters.forEach(adapter -> {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getSystemFiberChannelAdapters() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.viosUtil.forEach( vios -> {
log.debug("getSystemFiberChannelAdapters() - VIOS: " + vios.name);
vios.storage.fiberChannelAdapters.forEach( adapter -> {
//HashMap<String, Map> map = new HashMap<>()
Measurement measurement = new Measurement();
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getSystemGenericPhysicalAdapters() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.viosUtil.forEach( vios -> {
vios.storage.genericPhysicalAdapters.forEach( adapter -> {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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<Measurement> getSystemGenericVirtualAdapters() {
List<Measurement> list = new ArrayList<>();
metrics.systemUtil.sample.viosUtil.forEach( vios -> {
vios.storage.genericVirtualAdapters.forEach( adapter -> {
//Map<String, Map> map = new HashMap<String, Map>()
Measurement measurement = new Measurement();
HashMap<String, String> tagsMap = new HashMap<String, String>() {
{
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<String, Number> fieldsMap = new HashMap<String, Number>() {
{
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;
}
}

View File

@ -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<PcmData> 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) {

View File

@ -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<Number> numOfReads;
List<Number> numOfWrites;
List<Number> readBytes;
List<Number> writeBytes;
List<Number> runningSpeed;
List<Number> 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;
}

View File

@ -4,14 +4,14 @@ import java.util.List;
public class GenericAdapter {
String id;
String type;
String physicalLocation;
List<Number> receivedPackets;
List<Number> sentPackets;
List<Number> droppedPackets;
List<Number> sentBytes;
List<Number> receivedBytes;
List<Number> transferredBytes;
public String id;
public String type;
public String physicalLocation;
public List<Number> receivedPackets;
public List<Number> sentPackets;
public List<Number> droppedPackets;
public List<Number> sentBytes;
public List<Number> receivedBytes;
public List<Number> transferredBytes;
}

View File

@ -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<Number> numOfReads;
List<Number> numOfWrites;
List<Number> readBytes;
List<Number> writeBytes;
List<Number> 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;
}

View File

@ -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<Number> numOfReads;
List<Number> numOfWrites;
List<Number> readBytes;
List<Number> writeBytes;
List<Number> 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;
}

View File

@ -1,10 +1,13 @@
package biz.nellemann.hmci.pcm;
import java.util.List;
import com.serjltt.moshi.adapters.FirstElement;
public class LparMemory {
List<Number> logicalMem;
List<Number> backedPhysicalMem;
@FirstElement
public Number logicalMem;
@FirstElement
public Number backedPhysicalMem;
}

View File

@ -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<Number> maxVirtualProcessors;
List<Number> currentVirtualProcessors;
List<Number> maxProcUnits;
List<Number> entitledProcUnits;
List<Number> utilizedProcUnits;
List<Number> utilizedCappedProcUnits;
List<Number> utilizedUncappedProcUnits;
List<Number> idleProcUnits;
List<Number> donatedProcUnits;
List<Number> timeSpentWaitingForDispatch;
List<Number> 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;
}

View File

@ -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();
}

View File

@ -1,11 +1,12 @@
package biz.nellemann.hmci.pcm;
import java.util.ArrayList;
import java.util.List;
public class Network {
List<GenericAdapter> genericAdapters;
List<SharedAdapter> sharedAdapters;
List<VirtualEthernetAdapter> virtualEthernetAdapters;
public List<GenericAdapter> genericAdapters = new ArrayList<>();
public List<SharedAdapter> sharedAdapters = new ArrayList<>();
public List<VirtualEthernetAdapter> virtualEthernetAdapters = new ArrayList<>();
}

View File

@ -4,10 +4,10 @@ import java.util.List;
public class PhysicalProcessorPool {
List<Number> assignedProcUnits;
List<Number> utilizedProcUnits;
List<Number> availableProcUnits;
List<Number> configuredProcUnits;
List<Number> borrowedProcUnits;
public List<Number> assignedProcUnits;
public List<Number> utilizedProcUnits;
public List<Number> availableProcUnits;
public List<Number> configuredProcUnits;
public List<Number> borrowedProcUnits;
}

View File

@ -3,6 +3,6 @@ package biz.nellemann.hmci.pcm;
public class SampleInfo {
public String timeStamp;
Integer status;
public Integer status;
}

View File

@ -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<Number> totalMem;
List<Number> availableMem;
List<Number> configurableMem;
List<Number> assignedMemToLpars;
@FirstElement
public Number totalMem;
@FirstElement
public Number availableMem;
@FirstElement
public Number configurableMem;
@FirstElement
public Number assignedMemToLpars;
}

View File

@ -1,12 +1,19 @@
package biz.nellemann.hmci.pcm;
import java.util.List;
import com.serjltt.moshi.adapters.FirstElement;
public class ServerProcessor {
List<Number> totalProcUnits;
List<Number> utilizedProcUnits;
List<Number> availableProcUnits;
List<Number> configurableProcUnits;
@FirstElement
public Number totalProcUnits;
@FirstElement
public Number utilizedProcUnits;
@FirstElement
public Number availableProcUnits;
@FirstElement
public Number configurableProcUnits;
}

View File

@ -4,9 +4,9 @@ import java.util.List;
public class ServerUtil {
ServerProcessor processor;
ServerMemory memory;
PhysicalProcessorPool physicalProcessorPool;
List<SharedProcessorPool> sharedProcessorPool;
public ServerProcessor processor;
public ServerMemory memory;
public PhysicalProcessorPool physicalProcessorPool;
public List<SharedProcessorPool> sharedProcessorPool;
}

View File

@ -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<Number> receivedPackets;
List<Number> sentPackets;
List<Number> droppedPackets;
List<Number> sentBytes;
List<Number> receivedBytes;
List<Number> transferredBytes;
List<String> 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;
}

View File

@ -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<Number> assignedProcUnits;
List<Number> utilizedProcUnits;
List<Number> availableProcUnits;
List<Number> configuredProcUnits;
List<Number> 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;
}

View File

@ -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<String> clientLpars;
List<GenericPhysicalAdapters> genericPhysicalAdapters;
List<GenericVirtualAdapter> genericVirtualAdapters;
List<FiberChannelAdapter> fiberChannelAdapters;
List<VirtualFiberChannelAdapter> virtualFiberChannelAdapters;
public List<String> clientLpars = new ArrayList<>();
public List<GenericPhysicalAdapters> genericPhysicalAdapters = new ArrayList<>();
public List<GenericVirtualAdapter> genericVirtualAdapters = new ArrayList<>();
public List<FiberChannelAdapter> fiberChannelAdapters = new ArrayList<>();
public List<VirtualFiberChannelAdapter> virtualFiberChannelAdapters = new ArrayList<>();
}

View File

@ -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<UtilSample> utilSamples;
public UtilInfo utilInfo;
@FirstElement
@Json(name = "utilSamples")
public UtilSample sample;
}

View File

@ -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<String> 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<String> metricArrayOrder;
}

View File

@ -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> viosUtil;
List<LparUtil> lparsUtil;
public ServerUtil serverUtil;
public List<ViosUtil> viosUtil = new ArrayList<>();
@FirstElement
public LparUtil lparsUtil;
/*
public LparUtil getLparsUtil() {
if(lparsUtil == null || lparsUtil.isEmpty()) {
return new LparUtil();
} else {
return lparsUtil.get(0);
}
}*/
}

View File

@ -1,10 +1,13 @@
package biz.nellemann.hmci.pcm;
import java.util.List;
import com.serjltt.moshi.adapters.FirstElement;
public class ViosMemory {
List<Number> assignedMem;
List<Number> utilizedMem;
@FirstElement
public Number assignedMem;
@FirstElement
public Number utilizedMem;
}

View File

@ -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;
}

View File

@ -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<Number> receivedPackets;
List<Number> sentPackets;
List<Number> droppedPackets;
List<Number> sentBytes;
List<Number> receivedBytes;
List<Number> receivedPhysicalPackets;
List<Number> sentPhysicalPackets;
List<Number> droppedPhysicalPackets;
List<Number> sentPhysicalBytes;
List<Number> receivedPhysicalBytes;
List<Number> transferredBytes;
List<Number> 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;
}

View File

@ -4,16 +4,16 @@ import java.util.List;
public class VirtualFiberChannelAdapter {
String wwpn;
String wwpn2;
String physicalLocation;
String physicalPortWWPN;
Integer viosId;
List<Number> numOfReads;
List<Number> numOfWrites;
List<Number> readBytes;
List<Number> writeBytes;
List<Number> runningSpeed;
List<Number> transmittedBytes;
public String wwpn;
public String wwpn2;
public String physicalLocation;
public String physicalPortWWPN;
public Integer viosId;
public List<Number> numOfReads;
public List<Number> numOfWrites;
public List<Number> readBytes;
public List<Number> writeBytes;
public List<Number> runningSpeed;
public List<Number> transmittedBytes;
}

View File

@ -3,7 +3,7 @@
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{12} - %msg%n</pattern>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n</pattern>
</encoder>
</appender>

View File

@ -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
}

View File

@ -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
}