From 9d29266907f5c53448cf29feb8217a7d4bc61a2b Mon Sep 17 00:00:00 2001 From: "Michael N. Lipp" Date: Thu, 14 Sep 2023 18:59:18 +0200 Subject: [PATCH] Report current RAM usage in status. --- .../vmoperator/runner/qemu/StatusUpdater.java | 128 +++++++++++------- .../qemu/events/BalloonChangeEvent.java | 47 +++++++ .../runner/qemu/events/MonitorEvent.java | 5 +- 3 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/BalloonChangeEvent.java diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java index e45b5e6..3523af9 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/StatusUpdater.java @@ -19,6 +19,8 @@ package org.jdrupes.vmoperator.runner.qemu; import com.google.gson.JsonObject; +import io.kubernetes.client.custom.Quantity; +import io.kubernetes.client.custom.Quantity.Format; import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.apis.ApiextensionsV1Api; import io.kubernetes.client.openapi.models.V1CustomResourceDefinitionVersion; @@ -26,6 +28,7 @@ import io.kubernetes.client.util.Config; import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesApi; import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesObject; import java.io.IOException; +import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; @@ -33,11 +36,13 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.logging.Level; +import org.jdrupes.vmoperator.runner.qemu.events.BalloonChangeEvent; import org.jdrupes.vmoperator.runner.qemu.events.RunnerConfigurationUpdate; import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange; import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.State; import static org.jdrupes.vmoperator.util.Constants.VM_OP_CRD_NAME; import static org.jdrupes.vmoperator.util.Constants.VM_OP_GROUP; +import org.jdrupes.vmoperator.util.GsonPtr; import org.jgrapes.core.Channel; import org.jgrapes.core.Component; import org.jgrapes.core.annotation.Handler; @@ -161,55 +166,6 @@ public class StatusUpdater extends Component { return vmCr.getRaw().getAsJsonObject("status").deepCopy(); } - /** - * On runner state changed. - * - * @param event the event - 8 * @throws ApiException the api exception - */ - @Handler - public void onRunnerStateChanged(RunnerStateChange event) - throws ApiException { - if (vmCrApi == null) { - return; - } - var vmCr = vmCrApi.get(namespace, vmName) - .throwsApiException().getObject(); - vmCrApi.updateStatus(vmCr, from -> { - JsonObject status = currentStatus(from); - status.getAsJsonArray("conditions").asList().stream() - .map(cond -> (JsonObject) cond) - .forEach(cond -> { - if ("Running".equals(cond.get("type").getAsString())) { - updateRunningCondition(event, from, cond); - } - }); - return status; - }); - } - - private void updateRunningCondition(RunnerStateChange event, - DynamicKubernetesObject from, JsonObject cond) { - boolean reportedRunning - = "True".equals(cond.get("status").getAsString()); - if (RUNNING_STATES.contains(event.state()) - && !reportedRunning) { - cond.addProperty("status", "True"); - cond.addProperty("lastTransitionTime", - Instant.now().toString()); - } - if (!RUNNING_STATES.contains(event.state()) - && reportedRunning) { - cond.addProperty("status", "False"); - cond.addProperty("lastTransitionTime", - Instant.now().toString()); - } - cond.addProperty("reason", event.reason()); - cond.addProperty("message", event.message()); - cond.addProperty("observedGeneration", - from.getMetadata().getGeneration()); - } - /** * On runner configuration update. * @@ -241,4 +197,78 @@ public class StatusUpdater extends Component { }); } + /** + * On runner state changed. + * + * @param event the event + * @throws ApiException the api exception + */ + @Handler + public void onRunnerStateChanged(RunnerStateChange event) + throws ApiException { + if (vmCrApi == null) { + return; + } + var vmCr = vmCrApi.get(namespace, vmName) + .throwsApiException().getObject(); + vmCrApi.updateStatus(vmCr, from -> { + JsonObject status = currentStatus(from); + status.getAsJsonArray("conditions").asList().stream() + .map(cond -> (JsonObject) cond) + .forEach(cond -> { + if ("Running".equals(cond.get("type").getAsString())) { + updateRunningCondition(event, from, cond); + } + }); + if (event.state() == State.STARTING) { + status.addProperty("ram", GsonPtr.to(from.getRaw()) + .getAsString("spec", "vm", "maximumRam").orElse("0")); + } + return status; + }); + } + + private void updateRunningCondition(RunnerStateChange event, + DynamicKubernetesObject from, JsonObject cond) { + boolean reportedRunning + = "True".equals(cond.get("status").getAsString()); + if (RUNNING_STATES.contains(event.state()) + && !reportedRunning) { + cond.addProperty("status", "True"); + cond.addProperty("lastTransitionTime", + Instant.now().toString()); + } + if (!RUNNING_STATES.contains(event.state()) + && reportedRunning) { + cond.addProperty("status", "False"); + cond.addProperty("lastTransitionTime", + Instant.now().toString()); + } + cond.addProperty("reason", event.reason()); + cond.addProperty("message", event.message()); + cond.addProperty("observedGeneration", + from.getMetadata().getGeneration()); + } + + /** + * On ballon change. + * + * @param event the event + * @throws ApiException + */ + @Handler + public void onBallonChange(BalloonChangeEvent event) throws ApiException { + if (vmCrApi == null) { + return; + } + var vmCr + = vmCrApi.get(namespace, vmName).throwsApiException().getObject(); + vmCrApi.updateStatus(vmCr, from -> { + JsonObject status = currentStatus(from); + status.addProperty("ram", + new Quantity(new BigDecimal(event.size()), Format.BINARY_SI) + .toSuffixedString()); + return status; + }); + } } diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/BalloonChangeEvent.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/BalloonChangeEvent.java new file mode 100644 index 0000000..9cc67c8 --- /dev/null +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/BalloonChangeEvent.java @@ -0,0 +1,47 @@ +/* + * VM-Operator + * Copyright (C) 2023 Michael N. Lipp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jdrupes.vmoperator.runner.qemu.events; + +import com.fasterxml.jackson.databind.JsonNode; +import java.math.BigInteger; + +/** + * Signals a change of the balloon. + */ +public class BalloonChangeEvent extends MonitorEvent { + + /** + * Instantiates a new tray moved. + * + * @param kind the kind + * @param data the data + */ + public BalloonChangeEvent(Kind kind, JsonNode data) { + super(kind, data); + } + + /** + * Returns the actual value. + * + * @return the actual value + */ + public BigInteger size() { + return new BigInteger(data().get("actual").asText()); + } +} diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/MonitorEvent.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/MonitorEvent.java index 28d2e4c..72647a1 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/MonitorEvent.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/events/MonitorEvent.java @@ -32,7 +32,7 @@ public class MonitorEvent extends Event { * The kind of monitor event. */ public enum Kind { - READY, POWERDOWN, DEVICE_TRAY_MOVED + READY, POWERDOWN, DEVICE_TRAY_MOVED, BALLOON_CHANGE } private final Kind kind; @@ -55,6 +55,9 @@ public class MonitorEvent extends Event { case DEVICE_TRAY_MOVED: return Optional .of(new TrayMovedEvent(kind, response.get("data"))); + case BALLOON_CHANGE: + return Optional + .of(new BalloonChangeEvent(kind, response.get("data"))); default: return Optional .of(new MonitorEvent(kind, response.get("data")));