More refactoring work, from Groovy to plain Java.
This commit is contained in:
parent
3f71aabd4e
commit
b005376941
|
@ -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 :)
|
||||
|
||||
|
|
12
build.gradle
12
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')
|
||||
|
|
|
@ -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
31
doc/hmci.toml
Normal 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
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -139,7 +139,7 @@ public class Configuration {
|
|||
String url;
|
||||
String username;
|
||||
String password;
|
||||
Boolean unsafe;
|
||||
Boolean unsafe = false;
|
||||
|
||||
private boolean isValid = false;
|
||||
|
||||
|
|
|
@ -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 IOException
|
||||
* @throws Exception
|
||||
*/
|
||||
//@CompileDynamic
|
||||
void login(Boolean force = false) throws IOException {
|
||||
void login() throws Exception {
|
||||
this.login(false);
|
||||
}
|
||||
|
||||
if(authToken && !force) {
|
||||
return
|
||||
|
||||
/**
|
||||
* Logon to the HMC and get an authentication token for further requests.
|
||||
* @param force
|
||||
* @throws Exception
|
||||
*/
|
||||
void login(Boolean force) throws Exception {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
189
src/main/java/biz/nellemann/hmci/Insights.java
Normal file
189
src/main/java/biz/nellemann/hmci/Insights.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
225
src/main/java/biz/nellemann/hmci/LogicalPartition.java
Normal file
225
src/main/java/biz/nellemann/hmci/LogicalPartition.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
try {
|
||||
insights.run();
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
326
src/main/java/biz/nellemann/hmci/ManagedSystem.java
Normal file
326
src/main/java/biz/nellemann/hmci/ManagedSystem.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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<>();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ package biz.nellemann.hmci.pcm;
|
|||
public class SampleInfo {
|
||||
|
||||
public String timeStamp;
|
||||
Integer status;
|
||||
public Integer status;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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<>();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue