Merged in enableThermal (pull request #14)

EnableThermal
This commit is contained in:
Mark Nellemann 2021-01-29 10:22:11 +00:00
commit 30f1f71a95
7 changed files with 162 additions and 23 deletions

View file

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

View file

@ -2,6 +2,8 @@
Description=HMC Insights Service
[Service]
#User=nobody
#Group=nogroup
TimeoutStartSec=0
Restart=always
ExecStart=/opt/hmci/bin/hmci

View file

@ -1,3 +1,3 @@
id = hmci
group = biz.nellemann.hmci
version = 1.1.2
version = 1.1.3

View file

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

View file

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

View file

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

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