commit
30f1f71a95
|
@ -6,7 +6,7 @@ Metrics includes:
|
|||
- *Managed Systems* - the physical Power servers
|
||||
- *Logical Partitions* - the virtualized servers running AIX, Linux and IBM-i (AS/400)
|
||||
- *Virtual I/O Servers* - the i/o partition(s) taking care of network and storage
|
||||
- *Energy* - power consumption and temperatures
|
||||
- *Energy* - power consumption and temperatures (needs to be enabled and not available for E880, E980)
|
||||
|
||||
![architecture](https://bitbucket.org/mnellemann/hmci/downloads/HMCi.png)
|
||||
|
||||
|
@ -57,7 +57,7 @@ Below are screenshots of the provided Grafana dashboards (found in the **doc/**
|
|||
|
||||
### Naming collision
|
||||
|
||||
You can't have partitions on different HMC's with the same name, as these cannot be distinguished when metrics are
|
||||
You can't have partitions (or Virtual I/O Servers) on different Systems with the same name, as these cannot be distinguished when metrics are
|
||||
written to InfluxDB (which uses the name as key).
|
||||
|
||||
### Renaming partitions
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
Description=HMC Insights Service
|
||||
|
||||
[Service]
|
||||
#User=nobody
|
||||
#Group=nogroup
|
||||
TimeoutStartSec=0
|
||||
Restart=always
|
||||
ExecStart=/opt/hmci/bin/hmci
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id = hmci
|
||||
group = biz.nellemann.hmci
|
||||
version = 1.1.2
|
||||
version = 1.1.3
|
||||
|
|
|
@ -110,6 +110,8 @@ class HmcInstance implements Runnable {
|
|||
|
||||
log.debug("discover() - " + hmcId);
|
||||
|
||||
Map<String, LogicalPartition> tmpPartitions = new HashMap<>();
|
||||
|
||||
try {
|
||||
hmcRestClient.logoff();
|
||||
hmcRestClient.login();
|
||||
|
@ -119,19 +121,16 @@ class HmcInstance implements Runnable {
|
|||
if(!systems.containsKey(systemId)) {
|
||||
systems.put(systemId, system);
|
||||
log.info("discover() - Found ManagedSystem: " + system + " @" + hmcId);
|
||||
hmcRestClient.enableEnergyMonitoring(system);
|
||||
}
|
||||
|
||||
// Get LPAR's for this system
|
||||
try {
|
||||
hmcRestClient.getLogicalPartitionsForManagedSystem(system).forEach((partitionId, partition) -> {
|
||||
|
||||
// Add to list of known partitions
|
||||
if(!partitions.containsKey(partitionId)) {
|
||||
partitions.put(partitionId, partition);
|
||||
log.info("discover() - Found LogicalPartition: " + partition + " @" + hmcId);
|
||||
}
|
||||
|
||||
});
|
||||
hmcRestClient.getLogicalPartitionsForManagedSystem(system).forEach(tmpPartitions::put);
|
||||
if(!tmpPartitions.isEmpty()) {
|
||||
partitions.clear();
|
||||
tmpPartitions.forEach(partitions::put);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("discover() - getLogicalPartitions", e);
|
||||
}
|
||||
|
@ -142,6 +141,7 @@ class HmcInstance implements Runnable {
|
|||
log.warn("discover() - getManagedSystems: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ import okhttp3.*;
|
|||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Entities;
|
||||
import org.jsoup.parser.Parser;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -160,7 +162,7 @@ public class HmcRestClient {
|
|||
Map<String, ManagedSystem> getManagedSystems() throws Exception {
|
||||
|
||||
URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem", baseUrl));
|
||||
String responseBody = getResponse(url);
|
||||
String responseBody = sendGetRequest(url);
|
||||
Map<String,ManagedSystem> managedSystemsMap = new HashMap<>();
|
||||
|
||||
// Do not try to parse empty response
|
||||
|
@ -200,7 +202,7 @@ public class HmcRestClient {
|
|||
*/
|
||||
Map<String, LogicalPartition> getLogicalPartitionsForManagedSystem(ManagedSystem system) throws Exception {
|
||||
URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id));
|
||||
String responseBody = getResponse(url);
|
||||
String responseBody = sendGetRequest(url);
|
||||
Map<String, LogicalPartition> partitionMap = new HashMap<>();
|
||||
|
||||
// Do not try to parse empty response
|
||||
|
@ -240,7 +242,7 @@ public class HmcRestClient {
|
|||
|
||||
log.debug("getPcmDataForManagedSystem() - " + system.id);
|
||||
URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?NoOfSamples=1", baseUrl, system.id));
|
||||
String responseBody = getResponse(url);
|
||||
String responseBody = sendGetRequest(url);
|
||||
String jsonBody = null;
|
||||
|
||||
// Do not try to parse empty response
|
||||
|
@ -258,7 +260,7 @@ public class HmcRestClient {
|
|||
if(link.attr("type").equals("application/json")) {
|
||||
String href = link.attr("href");
|
||||
log.debug("getPcmDataForManagedSystem() - json url: " + href);
|
||||
jsonBody = getResponse(new URL(href));
|
||||
jsonBody = sendGetRequest(new URL(href));
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
|
@ -278,7 +280,7 @@ public class HmcRestClient {
|
|||
|
||||
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));
|
||||
String responseBody = getResponse(url);
|
||||
String responseBody = sendGetRequest(url);
|
||||
String jsonBody = null;
|
||||
|
||||
// Do not try to parse empty response
|
||||
|
@ -296,7 +298,7 @@ public class HmcRestClient {
|
|||
if(link.attr("type").equals("application/json")) {
|
||||
String href = link.attr("href");
|
||||
log.debug("getPcmDataForLogicalPartition() - json url: " + href);
|
||||
jsonBody = getResponse(new URL(href));
|
||||
jsonBody = sendGetRequest(new URL(href));
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
|
@ -317,7 +319,7 @@ public class HmcRestClient {
|
|||
|
||||
log.debug("getPcmDataForEnergy() - " + systemEnergy.system.id);
|
||||
URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/ProcessedMetrics?Type=Energy&NoOfSamples=1", baseUrl, systemEnergy.system.id));
|
||||
String responseBody = getResponse(url);
|
||||
String responseBody = sendGetRequest(url);
|
||||
String jsonBody = null;
|
||||
//log.info(responseBody);
|
||||
|
||||
|
@ -336,7 +338,7 @@ public class HmcRestClient {
|
|||
if(link.attr("type").equals("application/json")) {
|
||||
String href = link.attr("href");
|
||||
log.debug("getPcmDataForEnergy() - json url: " + href);
|
||||
jsonBody = getResponse(new URL(href));
|
||||
jsonBody = sendGetRequest(new URL(href));
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
|
@ -347,12 +349,64 @@ public class HmcRestClient {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set EnergyMonitorEnabled preference to true, if possible.
|
||||
* @param system
|
||||
*/
|
||||
void enableEnergyMonitoring(ManagedSystem system) {
|
||||
|
||||
log.debug("enableEnergyMonitoring() - " + system.id);
|
||||
try {
|
||||
URL url = new URL(String.format("%s/rest/api/pcm/ManagedSystem/%s/preferences", baseUrl, system.id));
|
||||
String responseBody = sendGetRequest(url);
|
||||
String jsonBody = null;
|
||||
|
||||
// Do not try to parse empty response
|
||||
if(responseBody == null || responseBody.isEmpty() || responseBody.length() <= 1) {
|
||||
responseErrors++;
|
||||
log.warn("enableEnergyMonitoring() - empty response");
|
||||
return;
|
||||
}
|
||||
|
||||
Document doc = Jsoup.parse(responseBody, "", Parser.xmlParser());
|
||||
doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
|
||||
doc.outputSettings().prettyPrint(false);
|
||||
doc.outputSettings().charset("US-ASCII");
|
||||
Element entry = doc.select("feed > entry").first();
|
||||
Element link1 = entry.select("EnergyMonitoringCapable").first();
|
||||
Element link2 = entry.select("EnergyMonitorEnabled").first();
|
||||
|
||||
if(link1.text().equals("true")) {
|
||||
log.debug("enableEnergyMonitoring() - EnergyMonitoringCapable == true");
|
||||
if(link2.text().equals("false")) {
|
||||
//log.warn("enableEnergyMonitoring() - EnergyMonitorEnabled == false");
|
||||
link2.text("true");
|
||||
|
||||
Document content = Jsoup.parse(doc.select("Content").first().html(), "", Parser.xmlParser());
|
||||
content.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
|
||||
content.outputSettings().prettyPrint(false);
|
||||
content.outputSettings().charset("UTF-8");
|
||||
String updateXml = content.outerHtml();
|
||||
|
||||
sendPostRequest(url, updateXml);
|
||||
}
|
||||
} else {
|
||||
log.warn("enableEnergyMonitoring() - EnergyMonitoringCapable == false");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("enableEnergyMonitoring() - Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a Response from the HMC
|
||||
* @param url to get Response from
|
||||
* @return Response body string
|
||||
*/
|
||||
private String getResponse(URL url) throws Exception {
|
||||
private String sendGetRequest(URL url) throws Exception {
|
||||
|
||||
log.debug("getResponse() - " + url.toString());
|
||||
|
||||
|
@ -384,6 +438,47 @@ public class HmcRestClient {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a POST request with a payload (can be null) to the HMC
|
||||
* @param url
|
||||
* @param payload
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String sendPostRequest(URL url, String payload) throws Exception {
|
||||
|
||||
log.debug("sendPostRequest() - " + url.toString());
|
||||
|
||||
RequestBody requestBody;
|
||||
if(payload != null) {
|
||||
//log.debug("sendPostRequest() - payload: " + payload);
|
||||
requestBody = RequestBody.create(payload, MediaType.get("application/xml"));
|
||||
} else {
|
||||
requestBody = RequestBody.create("", null);
|
||||
}
|
||||
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
//.addHeader("Content-Type", "application/xml")
|
||||
.addHeader("content-type", "application/xml")
|
||||
.addHeader("X-API-Session", authToken)
|
||||
.post(requestBody).build();
|
||||
|
||||
Response response = client.newCall(request).execute();
|
||||
String body = Objects.requireNonNull(response.body()).string();
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
response.close();
|
||||
log.warn(body);
|
||||
log.error("sendPostRequest() - Unexpected response: " + response.code());
|
||||
throw new IOException("sendPostRequest() - Unexpected response: " + response.code());
|
||||
}
|
||||
|
||||
log.debug("sendPostRequest() - response: " + body);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide an unsafe (ignoring SSL problems) OkHttpClient
|
||||
|
|
|
@ -73,7 +73,7 @@ class HmcRestClientTest extends Specification {
|
|||
mockServer.enqueue(new MockResponse().setBody(testJson))
|
||||
|
||||
when:
|
||||
String jsonString = hmc.getResponse(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/ManagedSystem_e09834d1-c930-3883-bdad-405d8e26e166_20200807T122600+0200_20200807T122600+0200_30.json") as String))
|
||||
String jsonString = hmc.sendGetRequest(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/ManagedSystem_e09834d1-c930-3883-bdad-405d8e26e166_20200807T122600+0200_20200807T122600+0200_30.json") as String))
|
||||
|
||||
then:
|
||||
jsonString.contains('"uuid": "e09834d1-c930-3883-bdad-405d8e26e166"')
|
||||
|
@ -87,7 +87,7 @@ class HmcRestClientTest extends Specification {
|
|||
mockServer.enqueue(new MockResponse().setBody(testJson))
|
||||
|
||||
when:
|
||||
String jsonString = hmc.getResponse(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/LogicalPartition_2DE05DB6-8AD5-448F-8327-0F488D287E82_20200807T123730+0200_20200807T123730+0200_30.json") as String))
|
||||
String jsonString = hmc.sendGetRequest(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/LogicalPartition_2DE05DB6-8AD5-448F-8327-0F488D287E82_20200807T123730+0200_20200807T123730+0200_30.json") as String))
|
||||
|
||||
then:
|
||||
jsonString.contains('"uuid": "b597e4da-2aab-3f52-8616-341d62153559"')
|
||||
|
|
42
src/test/resources/system-preferences.xml
Normal file
42
src/test/resources/system-preferences.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:ns2="http://a9.com/-/spec/opensearch/1.1/" xmlns:ns3="http://www.w3.org/1999/xhtml">
|
||||
<id>d93d97ab-757a-38ed-afe7-013c51cf60c9</id>
|
||||
<title type="text">Performance and Capacity Monitoring Preferences</title>
|
||||
<subtitle type="text"/>
|
||||
<link rel="self" href="https://10.32.64.40:12443/rest/api/pcm/ManagedSystem/d93d97ab-757a-38ed-afe7-013c51cf60c9/preferences"/>
|
||||
<generator uri="IBM Power Systems Management Console" version="1"/>
|
||||
<entry>
|
||||
<id>e40c41c0-4aff-472d-85f2-715e11ed1a74</id>
|
||||
<updated>2021-01-28T13:13:23.636+01:00</updated>
|
||||
<title type="text">Performance and Capacity Monitoring Preferences</title>
|
||||
<published>2021-01-28T13:13:23.636+01:00</published>
|
||||
<author>
|
||||
<name>IBM Power Systems Management Console</name>
|
||||
</author>
|
||||
<content type="application/xml">
|
||||
<ManagedSystemPcmPreference:ManagedSystemPcmPreference xmlns:ManagedSystemPcmPreference="http://www.ibm.com/xmlns/systems/power/firmware/pcm/mc/2012_10/" xmlns="http://www.ibm.com/xmlns/systems/power/firmware/pcm/mc/2012_10/" xmlns:ns2="http://www.w3.org/XML/1998/namespace/k2" schemaVersion="V1_5_3">
|
||||
<Metadata>
|
||||
<Atom>
|
||||
<AtomID>d93d97ab-757a-38ed-afe7-013c51cf60c9</AtomID>
|
||||
<AtomCreated>1611836003635</AtomCreated>
|
||||
</Atom>
|
||||
</Metadata>
|
||||
<SystemName kxe="false" kb="ROR">P750-8408-E8D-SN211D04V</SystemName>
|
||||
<MachineTypeModelSerialNumber kb="ROR" kxe="false" schemaVersion="V1_5_3">
|
||||
<Metadata>
|
||||
<Atom/>
|
||||
</Metadata>
|
||||
<MachineType kb="ROR" kxe="false">8408</MachineType>
|
||||
<Model kxe="false" kb="ROR">E8D</Model>
|
||||
<SerialNumber kxe="false" kb="ROR">211D04V</SerialNumber>
|
||||
</MachineTypeModelSerialNumber>
|
||||
<EnergyMonitoringCapable kxe="false" kb="ROO">false</EnergyMonitoringCapable>
|
||||
<LongTermMonitorEnabled kb="UOD" kxe="false">true</LongTermMonitorEnabled>
|
||||
<AggregationEnabled kxe="false" kb="UOD">true</AggregationEnabled>
|
||||
<ShortTermMonitorEnabled kb="UOD" kxe="false">false</ShortTermMonitorEnabled>
|
||||
<ComputeLTMEnabled ksv="V1_1_0" kxe="false" kb="UOD">true</ComputeLTMEnabled>
|
||||
<EnergyMonitorEnabled kb="UOD" kxe="false">false</EnergyMonitorEnabled>
|
||||
<AssociatedManagedSystem kxe="false" kb="ROO" href="https://127.0.0.1:13443/rest/api/uom/ManagedSystem/d93d97ab-757a-38ed-afe7-013c51cf60c9" rel="related"/>
|
||||
</ManagedSystemPcmPreference:ManagedSystemPcmPreference>
|
||||
</content>
|
||||
</entry>
|
||||
</feed>
|
Loading…
Reference in a new issue