More refactoring work, cleanup and improvements.

This commit is contained in:
Mark Nellemann 2020-10-12 10:15:53 +02:00
parent b005376941
commit 3474ee1790
19 changed files with 111 additions and 110 deletions

View File

@ -72,7 +72,7 @@ ospackage {
buildRpm {
dependsOn startShadowScripts
os = LINUX
os = "LINUX"
}
buildDeb {

View File

@ -1,3 +1,3 @@
id = hmci
group = biz.nellemann.hmci
version = 1.0.10
version = 0.2.1

View File

@ -26,18 +26,17 @@ public class Configuration {
Path source = Paths.get(configurationFile);
TomlParseResult result = Toml.parse(source);
result.errors().forEach(error -> System.err.println(error.toString()));
//System.out.println(result.toJson());
if(result.contains("refresh")) {
refresh = result.getLong("refresh");
} else {
refresh = 15l;
refresh = 15L;
}
if(result.contains("rescan")) {
rescan = result.getLong("rescan");
} else {
rescan = 60l;
rescan = 60L;
}
hmc = getHmc(result);
@ -52,6 +51,9 @@ public class Configuration {
if(result.contains("hmc") && result.isTable("hmc")) {
TomlTable hmcTable = result.getTable("hmc");
if(hmcTable == null) {
return list;
}
for(String key : hmcTable.keySet()) {
HmcObject c = new HmcObject();
@ -119,17 +121,30 @@ public class Configuration {
String password = "";
String database = "hmci";
private boolean isValid = false;
private boolean validated = false;
InfluxObject() { }
InfluxObject(String url, String username, String password, String database) {
this.url = url;
this.username = username;
this.password = password;
this.database = database;
}
Boolean isValid() {
return isValid();
return validated;
}
// TODO: Fixme
void validate() {
isValid = true;
validated = true;
}
@Override
public String toString() {
return url;
}
}
@ -141,15 +156,25 @@ public class Configuration {
String password;
Boolean unsafe = false;
private boolean isValid = false;
private boolean validated = false;
HmcObject() { }
HmcObject(String url, String username, String password, Boolean unsafe) {
this.url = url;
this.username = username;
this.password = password;
this.unsafe = unsafe;
}
Boolean isValid() {
return isValid();
return validated;
}
// TODO: Fixme
void validate() {
isValid = true;
validated = true;
}
@Override

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
@ -44,7 +45,6 @@ class HmcClient {
private final String baseUrl;
private final String username;
private final String password;
private final Boolean unsafe;
protected Integer responseErrors = 0;
protected String authToken;
@ -57,7 +57,7 @@ class HmcClient {
this.baseUrl = configHmc.url;
this.username = configHmc.username;
this.password = configHmc.password;
this.unsafe = configHmc.unsafe;
Boolean unsafe = configHmc.unsafe;
if(unsafe) {
this.client = getUnsafeOkHttpClient();
@ -70,7 +70,6 @@ class HmcClient {
/**
* Logon to the HMC and get an authentication token for further requests.
* @throws Exception
*/
void login() throws Exception {
this.login(false);
@ -80,7 +79,6 @@ class HmcClient {
/**
* Logon to the HMC and get an authentication token for further requests.
* @param force
* @throws Exception
*/
void login(Boolean force) throws Exception {
@ -97,8 +95,9 @@ class HmcClient {
payload.append("<Password>").append(password).append("</Password>");
payload.append("</LogonRequest>");
URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl));
Request request = new Request.Builder()
try {
URL url = new URL(String.format("%s/rest/api/web/Logon", baseUrl));
Request request = new Request.Builder()
.url(url)
//.addHeader("Content-Type", "application/vnd.ibm.powervm.web+xml; type=LogonRequest")
.addHeader("Accept", "application/vnd.ibm.powervm.web+xml; type=LogonResponse")
@ -106,21 +105,23 @@ class HmcClient {
.put(RequestBody.create(payload.toString(), MEDIA_TYPE_IBM_XML_LOGIN))
.build();
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// Get response body and parse
String responseBody = response.body().string();
response.body().close();
String responseBody = Objects.requireNonNull(response.body()).string();
Objects.requireNonNull(response.body()).close();
Document doc = Jsoup.parse(responseBody);
authToken = doc.select("X-API-Session").text();
log.debug("login() - Auth Token: " + authToken);
} catch (MalformedURLException e) {
log.error("login() - url error", e);
throw new Exception(new Throwable("Login URL Error: " + e.getMessage()));
} catch(Exception e) {
log.error(e.getMessage());
throw new Exception(e);
log.error("login() - general error", e);
throw new Exception(new Throwable("Login General Error: " + e.getMessage()));
}
}
@ -157,14 +158,14 @@ class HmcClient {
/**
* Return Map of ManagedSystems seen by this HMC
*
* @return
* @return Map of system-id and ManagedSystem
*/
Map<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>();
Map<String,ManagedSystem> managedSystemsMap = new HashMap<>();
// Do not try to parse empty response
if(responseBody.isEmpty() || responseBody.length() <= 1) {
@ -185,7 +186,7 @@ class HmcClient {
el.select("MachineTypeModelAndSerialNumber > SerialNumber").text()
);
managedSystemsMap.put(system.id, system);
log.info("getManagedSystems() - Found system: " + system.toString());
log.debug("getManagedSystems() - Found system: " + system.toString());
}
} catch(Exception e) {
@ -199,8 +200,8 @@ class HmcClient {
/**
* Return Map of LogicalPartitions seen by a ManagedSystem on this HMC
* @param system
* @return
* @param system a valid ManagedSystem
* @return Map of partition-id and LogicalPartition
*/
Map<String, LogicalPartition> getLogicalPartitionsForManagedSystem(ManagedSystem system) throws Exception {
URL url = new URL(String.format("%s/rest/api/uom/ManagedSystem/%s/LogicalPartition", baseUrl, system.id));
@ -225,7 +226,7 @@ class HmcClient {
system
);
partitionMap.put(logicalPartition.id, logicalPartition);
log.info("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString());
log.debug("getLogicalPartitionsForManagedSystem() - Found partition: " + logicalPartition.toString());
}
} catch(Exception e) {
@ -239,8 +240,8 @@ class HmcClient {
/**
* Parse XML feed to get PCM Data in JSON format
* @param system
* @return
* @param system a valid ManagedSystem
* @return JSON string with PCM data for this ManagedSystem
*/
String getPcmDataForManagedSystem(ManagedSystem system) throws Exception {
@ -254,7 +255,7 @@ class HmcClient {
if(responseBody.isEmpty() || responseBody.length() <= 1) {
responseErrors++;
log.warn("getPcmDataForManagedSystem() - empty response");
return jsonBody;
return null;
}
try {
@ -278,8 +279,8 @@ class HmcClient {
/**
* Parse XML feed to get PCM Data in JSON format
* @param partition
* @return
* @param partition a valid LogicalPartition
* @return JSON string with PCM data for this LogicalPartition
*/
String getPcmDataForLogicalPartition(LogicalPartition partition) throws Exception {
@ -293,7 +294,7 @@ class HmcClient {
if(responseBody.isEmpty() || responseBody.length() <= 1) {
responseErrors++;
log.warn("getPcmDataForLogicalPartition() - empty response");
return jsonBody;
return null;
}
try {
@ -310,19 +311,6 @@ class HmcClient {
} catch(Exception e) {
log.warn("getPcmDataForLogicalPartition() - xml parse error", e);
}
/*
try {
Document doc = Jsoup.parse(responseBody);
Element entry = doc.select("entry").first();
Element link = entry.select("link[href]").first();
if(link.attr("type") == "application/json") {
String href = (String) link.attr("href");
log.debug("getPcmDataForLogicalPartition() - json url: " + href);
jsonBody = getResponseBody(new URL(href));
}
} catch(Exception e) {
log.warn("getPcmDataForLogicalPartition() - xml parse error", e);
}*/
return jsonBody;
}
@ -331,8 +319,8 @@ class HmcClient {
/**
* Return body text from a HTTP response from the HMC
*
* @param url
* @return
* @param url URL to get response body as String
* @return String with http reponse body
*/
protected String getResponseBody(URL url) throws Exception {
Response response = getResponse(url);
@ -344,8 +332,8 @@ class HmcClient {
/**
* Return a Response from the HMC
* @param url
* @return
* @param url to get Response from
* @return Response object
*/
private Response getResponse(URL url) throws Exception {
return getResponse(url, 0);
@ -354,9 +342,9 @@ class HmcClient {
/**
* Return a Response from the HMC
* @param url
* @param retry
* @return
* @param url to get Response from
* @param retry number of retries for this call
* @return Response object
*/
private Response getResponse(URL url, Integer retry) throws Exception {
@ -377,7 +365,7 @@ class HmcClient {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
response.body().close();
Objects.requireNonNull(response.body()).close();
if(response.code() == 401) {
login(true);
@ -391,7 +379,7 @@ class HmcClient {
log.error("getResponse() - Unexpected response: " + response.code());
throw new IOException("getResponse() - Unexpected response: " + response.code());
};
}
return response;
}
@ -432,15 +420,9 @@ class HmcClient {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
builder.hostnameVerifier((hostname, session) -> true);
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
return builder.build();
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,6 +20,9 @@ import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.lang.Thread.*;
class Insights {
@ -28,9 +31,9 @@ class Insights {
final Configuration configuration;
InfluxClient influxClient;
Map<String, HmcClient> hmcClients = new HashMap<>();
Map<String,ManagedSystem> systems = new HashMap<String, ManagedSystem>();
Map<String, LogicalPartition> partitions = new HashMap<String, LogicalPartition>();
final Map<String, HmcClient> hmcClients = new HashMap<>();
final Map<String,ManagedSystem> systems = new HashMap<>();
final Map<String, LogicalPartition> partitions = new HashMap<>();
Insights(Configuration configuration) {
@ -52,7 +55,6 @@ class Insights {
configuration.hmc.forEach( configHmc -> {
if(hmcClients != null && !hmcClients.containsKey(configHmc.name)) {
log.debug("Adding HMC: " + configHmc.toString());
HmcClient hmcClient = new HmcClient(configHmc);
hmcClients.put(configHmc.name, hmcClient);
}
@ -82,7 +84,6 @@ class Insights {
} catch(Exception e) {
log.error("discover() - " + hmcId + " error: " + e.getMessage());
//hmcClients.remove(hmcId);
}
});
@ -102,7 +103,6 @@ class Insights {
tmpJsonString = hmcClient.getPcmDataForManagedSystem(system);
} catch (Exception e) {
log.error("getMetricsForSystems()", e);
//e.printStackTrace();
}
if(tmpJsonString != null && !tmpJsonString.isEmpty()) {
@ -128,7 +128,7 @@ class Insights {
try {
tmpJsonString2 = hmcClient.getPcmDataForLogicalPartition(partition);
} catch (Exception e) {
log.error("getMetricsForPartitions()", e);
log.error("getMetricsForPartitions() - getPcmDataForLogicalPartition", e);
}
if(tmpJsonString2 != null && !tmpJsonString2.isEmpty()) {
partition.processMetrics(tmpJsonString2);
@ -160,8 +160,12 @@ class Insights {
log.debug("run()");
int executions = 0;
AtomicBoolean keepRunning = new AtomicBoolean(true);
while(true) {
Thread shutdownHook = new Thread(() -> keepRunning.set(false));
Runtime.getRuntime().addShutdownHook(shutdownHook);
do {
try {
getMetricsForSystems();
@ -172,17 +176,18 @@ class Insights {
influxClient.writeBatchPoints();
// Refresh HMC's
if(executions > configuration.rescan) {
if (executions > configuration.rescan) {
executions = 0;
discover();
}
} catch(Exception e) {
log.error("run()", e.getMessage());
} catch (Exception e) {
log.error("run()", e);
}
executions++;
Thread.sleep(configuration.refresh * 1000);
}
sleep(configuration.refresh * 1000);
} while (keepRunning.get());
}

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -27,10 +27,10 @@ class LogicalPartition extends MetaSystem {
private final static Logger log = LoggerFactory.getLogger(LogicalPartition.class);
public String id;
public String name;
public String type;
public ManagedSystem system;
public final String id;
public final String name;
public final String type;
public final ManagedSystem system;
LogicalPartition(String id, String name, String type, ManagedSystem system) {

View File

@ -32,6 +32,7 @@ public class Main implements Callable<Integer> {
private final static Logger log = LoggerFactory.getLogger(Main.class);
@SuppressWarnings("FieldMayBeFinal")
@CommandLine.Option(names = { "-c", "--conf" }, description = "Configuration file [default: '/etc/hmci.toml'].")
private String configurationFile = "/etc/hmci.toml";

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -99,7 +99,7 @@ class ManagedSystem extends MetaSystem {
HashMap<String, Number> fieldsMap = new HashMap<String, Number>() {
{
put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.totalProcUnits);
put("totalProcUnits", metrics.systemUtil.sample.serverUtil.processor.totalProcUnits);
put("utilizedProcUnits", metrics.systemUtil.sample.serverUtil.processor.utilizedProcUnits);
put("availableProcUnits", metrics.systemUtil.sample.serverUtil.processor.availableProcUnits);
put("configurableProcUnits", metrics.systemUtil.sample.serverUtil.processor.configurableProcUnits);

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2020 Mark Nellemann <mark.nellemann@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm;
import com.serjltt.moshi.adapters.FirstElement;
import java.util.List;
public class FiberChannelAdapter {
public String id;

View File

@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm;
import com.serjltt.moshi.adapters.FirstElement;
import java.util.List;
public class GenericPhysicalAdapters {
public String id;

View File

@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm;
import com.serjltt.moshi.adapters.FirstElement;
import java.util.List;
public class LparProcessor {
public Integer poolId;

View File

@ -1,9 +1,6 @@
package biz.nellemann.hmci.pcm;
import com.serjltt.moshi.adapters.FirstElement;
import com.squareup.moshi.Json;
import java.util.List;
public class ServerMemory {

View File

@ -2,7 +2,6 @@ package biz.nellemann.hmci.pcm;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class Storage {

View File

@ -2,8 +2,6 @@ package biz.nellemann.hmci.pcm;
import com.serjltt.moshi.adapters.FirstElement;
import java.util.List;
public class VirtualEthernetAdapter {
public String physicalLocation;

View File

@ -10,7 +10,7 @@ class ConfigurationTest extends Specification {
void "test parsing"() {
when:
Configuration conf = new Configuration(testConfigurationFile);
Configuration conf = new Configuration(testConfigurationFile)
then:
conf != null
@ -20,7 +20,7 @@ class ConfigurationTest extends Specification {
void "test lookup influx"() {
when:
Configuration conf = new Configuration(testConfigurationFile);
Configuration conf = new Configuration(testConfigurationFile)
then:
conf != null

View File

@ -7,11 +7,11 @@ import spock.lang.Specification
class HmcClientTest extends Specification {
HmcClient hmc
MockWebServer mockServer = new MockWebServer();
MockWebServer mockServer = new MockWebServer()
def setup() {
mockServer.start();
mockServer.start()
Configuration.HmcObject configHmc = new Configuration.HmcObject()
configHmc.name = "site1"
configHmc.url = mockServer.url("/").toString()
@ -29,7 +29,7 @@ class HmcClientTest extends Specification {
void "test against empty xml"() {
setup:
def testXml = ""
mockServer.enqueue(new MockResponse().setBody(testXml));
mockServer.enqueue(new MockResponse().setBody(testXml))
when:
Map<String, ManagedSystem> systems = hmc.getManagedSystems()
@ -43,7 +43,7 @@ class HmcClientTest extends Specification {
setup:
def testFile = new File(getClass().getResource('/managed-systems.xml').toURI())
def testXml = testFile.getText('UTF-8')
mockServer.enqueue(new MockResponse().setBody(testXml));
mockServer.enqueue(new MockResponse().setBody(testXml))
when:
Map<String, ManagedSystem> systems = hmc.getManagedSystems()
@ -58,7 +58,7 @@ class HmcClientTest extends Specification {
setup:
def testFile = new File(getClass().getResource('/logical-partitions.xml').toURI())
def testXml = testFile.getText('UTF-8')
mockServer.enqueue(new MockResponse().setBody(testXml));
mockServer.enqueue(new MockResponse().setBody(testXml))
when:
ManagedSystem system = new ManagedSystem("site1", "e09834d1-c930-3883-bdad-405d8e26e166", "Test Name","Test Type", "Test Model", "Test S/N")
@ -75,7 +75,7 @@ class HmcClientTest extends Specification {
setup:
def testFile = new File(getClass().getResource('/pcm-data-managed-system.json').toURI())
def testJson = testFile.getText('UTF-8')
mockServer.enqueue(new MockResponse().setBody(testJson));
mockServer.enqueue(new MockResponse().setBody(testJson))
when:
String jsonString = hmc.getResponseBody(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/ManagedSystem_e09834d1-c930-3883-bdad-405d8e26e166_20200807T122600+0200_20200807T122600+0200_30.json") as String))
@ -89,7 +89,7 @@ class HmcClientTest extends Specification {
setup:
def testFile = new File(getClass().getResource('/pcm-data-logical-partition.json').toURI())
def testJson = testFile.getText('UTF-8')
mockServer.enqueue(new MockResponse().setBody(testJson));
mockServer.enqueue(new MockResponse().setBody(testJson))
when:
String jsonString = hmc.getResponseBody(new URL(mockServer.url("/rest/api/pcm/ProcessedMetrics/LogicalPartition_2DE05DB6-8AD5-448F-8327-0F488D287E82_20200807T123730+0200_20200807T123730+0200_30.json") as String))

View File

@ -9,7 +9,7 @@ class InfluxClientTest extends Specification {
InfluxClient influxClient
def setup() {
influxClient = new InfluxClient("http://localhost:8086", "root", "", "hmci")
influxClient = new InfluxClient(new Configuration.InfluxObject("http://localhost:8086", "root", "", "hmci"))
influxClient.login()
}