From bdfa535b75c1b49370891d82c348899afecf08ef Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Thu, 10 Aug 2023 11:02:53 +0200 Subject: [PATCH] Work on avoiding lingering sessions on the HMC. --- build.gradle | 14 ++++++------- doc/readme-hmc.md | 4 ++-- gradle.properties | 2 +- .../java/biz/nellemann/hmci/InfluxClient.java | 4 ++-- .../java/biz/nellemann/hmci/RestClient.java | 20 +++++++++++++++++++ .../nellemann/hmci/dto/json/PowerUtil.java | 2 +- .../hmci/LogicalPartitionTest.groovy | 1 + .../nellemann/hmci/ManagedSystemTest.groovy | 1 + 8 files changed, 35 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 57476aa..af8e1d2 100644 --- a/build.gradle +++ b/build.gradle @@ -17,15 +17,15 @@ group = projectGroup version = projectVersion dependencies { - annotationProcessor 'info.picocli:picocli-codegen:4.7.3' - implementation 'info.picocli:picocli:4.7.3' + annotationProcessor 'info.picocli:picocli-codegen:4.7.4' + implementation 'info.picocli:picocli:4.7.4' implementation 'org.slf4j:slf4j-api:2.0.7' implementation 'org.slf4j:slf4j-simple:2.0.7' - implementation 'com.squareup.okhttp3:okhttp:4.10.0' // Also used by InfluxDB Client - implementation 'com.influxdb:influxdb-client-java:6.8.0' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.3' - implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.3' - implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.14.3' + implementation 'com.squareup.okhttp3:okhttp:4.11.0' // Also used by InfluxDB Client + implementation 'com.influxdb:influxdb-client-java:6.10.0' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2' testImplementation 'junit:junit:4.13.2' testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' diff --git a/doc/readme-hmc.md b/doc/readme-hmc.md index 610c6be..6b889fe 100644 --- a/doc/readme-hmc.md +++ b/doc/readme-hmc.md @@ -11,9 +11,9 @@ Ensure you have **correct date/time** and NTPd running to keep it accurate! - Navigate to *Users and Security* - Create a new read-only/viewer **hmci** user, which will be used to connect to the HMC. - Click *Manage User Profiles and Access*, edit the newly created *hmci* user and click *User Properties*: - - Set *Session timeout minutes* to **60** + - Set *Session timeout minutes* to **120** (or at least 61 minutes) - Set *Verify timeout minutes* to **15** - - Set *Idle timeout minutes* to **90** + - Set *Idle timeout minutes* to **15** - Set *Minimum time in days between password changes* to **0** - **Enable** *Allow remote access via the web* - Navigate to *HMC Management* and *Console Settings* diff --git a/gradle.properties b/gradle.properties index 91253d0..842f543 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ projectId = hmci projectGroup = biz.nellemann.hmci -projectVersion = 1.4.4 +projectVersion = 1.4.5 diff --git a/src/main/java/biz/nellemann/hmci/InfluxClient.java b/src/main/java/biz/nellemann/hmci/InfluxClient.java index 90803b7..f1972f5 100644 --- a/src/main/java/biz/nellemann/hmci/InfluxClient.java +++ b/src/main/java/biz/nellemann/hmci/InfluxClient.java @@ -83,10 +83,10 @@ public final class InfluxClient { Runtime.getRuntime().addShutdownHook(new Thread(influxDBClient::close)); // Todo: Handle events - https://github.com/influxdata/influxdb-client-java/tree/master/client#handle-the-events - //writeApi = influxDBClient.makeWriteApi(); writeApi = influxDBClient.makeWriteApi( WriteOptions.builder() - .bufferLimit(20_000) + .batchSize(15_000) + .bufferLimit(500_000) .flushInterval(5_000) .build()); diff --git a/src/main/java/biz/nellemann/hmci/RestClient.java b/src/main/java/biz/nellemann/hmci/RestClient.java index 3a3567b..0848a97 100644 --- a/src/main/java/biz/nellemann/hmci/RestClient.java +++ b/src/main/java/biz/nellemann/hmci/RestClient.java @@ -16,6 +16,8 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -38,6 +40,9 @@ public class RestClient { protected final String username; protected final String password; + private final static int MAX_MINUTES_BETWEEN_AUTHENTICATION = 60; // TODO: Make configurable and match HMC timeout settings + private Instant lastAuthenticationTimestamp; + public RestClient(String baseUrl, String username, String password, Boolean trustAll) { this.baseUrl = baseUrl; @@ -63,6 +68,8 @@ public class RestClient { log.error("ManagementConsole() - trace error: " + e.getMessage()); } }*/ + Thread shutdownHook = new Thread(this::logoff); + Runtime.getRuntime().addShutdownHook(shutdownHook); } @@ -70,6 +77,9 @@ public class RestClient { * Logon to the HMC and get an authentication token for further requests. */ public synchronized void login() { + if(authToken != null) { + logoff(); + } log.info("Connecting to HMC - {} @ {}", username, baseUrl); StringBuilder payload = new StringBuilder(); @@ -102,10 +112,12 @@ public class RestClient { LogonResponse logonResponse = xmlMapper.readValue(responseBody, LogonResponse.class); authToken = logonResponse.getToken(); + lastAuthenticationTimestamp = Instant.now(); log.debug("logon() - auth token: {}", authToken); } catch (Exception e) { log.warn("logon() - error: {}", e.getMessage()); + lastAuthenticationTimestamp = null; } } @@ -136,6 +148,7 @@ public class RestClient { log.warn("logoff() error: {}", e.getMessage()); } finally { authToken = null; + lastAuthenticationTimestamp = null; } } catch (MalformedURLException e) { @@ -164,6 +177,9 @@ public class RestClient { public synchronized String getRequest(URL url) throws IOException { log.debug("getRequest() - URL: {}", url.toString()); + if (lastAuthenticationTimestamp == null || lastAuthenticationTimestamp.plus(MAX_MINUTES_BETWEEN_AUTHENTICATION, ChronoUnit.MINUTES).isBefore(Instant.now())) { + login(); + } Request request = new Request.Builder() .url(url) @@ -222,6 +238,10 @@ public class RestClient { public synchronized String postRequest(URL url, String payload) throws IOException { log.debug("sendPostRequest() - URL: {}", url.toString()); + if (lastAuthenticationTimestamp == null || lastAuthenticationTimestamp.plus(MAX_MINUTES_BETWEEN_AUTHENTICATION, ChronoUnit.MINUTES).isBefore(Instant.now())) { + login(); + } + RequestBody requestBody; if(payload != null) { requestBody = RequestBody.create(payload, MEDIA_TYPE_IBM_XML_POST); diff --git a/src/main/java/biz/nellemann/hmci/dto/json/PowerUtil.java b/src/main/java/biz/nellemann/hmci/dto/json/PowerUtil.java index ab028eb..f77f9aa 100644 --- a/src/main/java/biz/nellemann/hmci/dto/json/PowerUtil.java +++ b/src/main/java/biz/nellemann/hmci/dto/json/PowerUtil.java @@ -5,6 +5,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public final class PowerUtil { - public Number powerReading = 0.0; + public float powerReading = 0.0F; } diff --git a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy index 6367cfc..92c4866 100644 --- a/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/LogicalPartitionTest.groovy @@ -52,6 +52,7 @@ class LogicalPartitionTest extends Specification { } def cleanupSpec() { + serviceClient.logoff() mockServer.stop() } diff --git a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy index 88f1cdc..3cf0ca6 100644 --- a/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy +++ b/src/test/groovy/biz/nellemann/hmci/ManagedSystemTest.groovy @@ -42,6 +42,7 @@ class ManagedSystemTest extends Specification { } def cleanupSpec() { + serviceClient.logoff() mockServer.stop() }