diff --git a/org.jdrupes.vmoperator.common/src/org/jdrupes/vmoperator/common/K8sGenericStub.java b/org.jdrupes.vmoperator.common/src/org/jdrupes/vmoperator/common/K8sGenericStub.java index 688f43f..2af4d1b 100644 --- a/org.jdrupes.vmoperator.common/src/org/jdrupes/vmoperator/common/K8sGenericStub.java +++ b/org.jdrupes.vmoperator.common/src/org/jdrupes/vmoperator/common/K8sGenericStub.java @@ -196,51 +196,52 @@ public class K8sGenericStub updateStatus(O object, Function status) + public Optional updateStatus(O object, Function updater) throws ApiException { - return K8s.optional(api.updateStatus(object, status)); + return K8s.optional(api.updateStatus(object, updater)); } /** * Gets the object and updates the status. In case of conflict, retries * up to `retries` times. * - * @param status the status + * @param updater the function updating the status * @param retries the retries in case of conflict * @return the updated model or empty if the object was not found * @throws ApiException the api exception */ @SuppressWarnings({ "PMD.AssignmentInOperand", "PMD.UnusedAssignment" }) - public Optional updateStatus(Function status, int retries) + public Optional updateStatus(Function updater, int retries) throws ApiException { - try { - return updateStatus(api.get(namespace, name).throwsApiException() - .getObject(), status); - } catch (ApiException e) { - if (HttpURLConnection.HTTP_CONFLICT != e.getCode() - || retries-- <= 0) { - throw e; + while (true) { + try { + return updateStatus(api.get(namespace, name) + .throwsApiException().getObject(), updater); + } catch (ApiException e) { + if (HttpURLConnection.HTTP_CONFLICT != e.getCode() + || retries-- <= 0) { + throw e; + } } } - return Optional.empty(); } /** - * Updates the status. + * Updates the status. In case of conflict, retries up to 16 times. * - * @param status the status + * @param updater the function updating the status * @return the kubernetes api response * the updated model or empty if not successful * @throws ApiException the api exception */ - public Optional updateStatus(Function status) + public Optional updateStatus(Function updater) throws ApiException { - return updateStatus(status, 16); + return updateStatus(updater, 16); } /** diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/ConsoleTracker.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/ConsoleTracker.java index b91b5df..7956fa1 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/ConsoleTracker.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/ConsoleTracker.java @@ -106,10 +106,9 @@ public class ConsoleTracker extends VmDefUpdater { mainChannelClientHost = event.clientHost(); mainChannelClientPort = event.clientPort(); vmStub.updateStatus(from -> { - JsonObject status = from.statusJson(); + JsonObject status = updateCondition(from, "ConsoleConnected", true, + "Connected", "Connection from " + event.clientHost()); status.addProperty("consoleClient", event.clientHost()); - updateCondition(from, status, "ConsoleConnected", true, "Connected", - "Connection from " + event.clientHost()); return status; }); @@ -141,10 +140,9 @@ public class ConsoleTracker extends VmDefUpdater { return; } vmStub.updateStatus(from -> { - JsonObject status = from.statusJson(); - status.addProperty("consoleClient", ""); - updateCondition(from, status, "ConsoleConnected", false, + JsonObject status = updateCondition(from, "ConsoleConnected", false, "Disconnected", event.clientHost() + " has disconnected"); + status.addProperty("consoleClient", ""); return status; }); 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 eeee5ac..b4608b3 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 @@ -154,7 +154,7 @@ public class StatusUpdater extends VmDefUpdater { "displayPasswordSerial").getAsInt() == -1)) { return; } - vmStub.updateStatus(vmDef.get(), from -> { + vmStub.updateStatus(from -> { JsonObject status = from.statusJson(); if (!event.configuration().hasDisplayPassword) { status.addProperty("displayPasswordSerial", -1); @@ -183,12 +183,11 @@ public class StatusUpdater extends VmDefUpdater { if (vmStub == null || (vmDef = vmStub.model().orElse(null)) == null) { return; } - vmStub.updateStatus(vmDef, from -> { - JsonObject status = from.statusJson(); + vmStub.updateStatus(from -> { boolean running = event.runState().vmRunning(); - updateCondition(vmDef, vmDef.statusJson(), "Running", running, - event.reason(), event.message()); - updateCondition(vmDef, vmDef.statusJson(), "Booted", + updateCondition(vmDef, "Running", running, event.reason(), + event.message()); + JsonObject status = updateCondition(vmDef, "Booted", event.runState() == RunState.BOOTED, event.reason(), event.message()); if (event.runState() == RunState.STARTING) { @@ -203,13 +202,13 @@ public class StatusUpdater extends VmDefUpdater { if (!running) { // In case console connection was still present status.addProperty("consoleClient", ""); - updateCondition(from, status, "ConsoleConnected", false, - "VmStopped", "The VM is not running"); + updateCondition(from, "ConsoleConnected", false, "VmStopped", + "The VM is not running"); // In case we had an irregular shutdown status.remove("osinfo"); - updateCondition(vmDef, vmDef.statusJson(), "VmopAgentConnected", - false, "VmStopped", "The VM is not running"); + updateCondition(vmDef, "VmopAgentConnected", false, "VmStopped", + "The VM is not running"); } return status; }); @@ -340,10 +339,8 @@ public class StatusUpdater extends VmDefUpdater { return; } vmStub.updateStatus(from -> { - JsonObject status = from.statusJson(); - updateCondition(vmDef, status, "VmopAgentConnected", + return updateCondition(vmDef, "VmopAgentConnected", true, "VmopAgentStarted", "The VM operator agent is running"); - return status; }); } diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmDefUpdater.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmDefUpdater.java index f04b478..50017c1 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmDefUpdater.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/VmDefUpdater.java @@ -31,6 +31,7 @@ import java.util.Optional; import java.util.logging.Level; import java.util.stream.Collectors; import org.jdrupes.vmoperator.common.K8sClient; +import org.jdrupes.vmoperator.common.K8sGenericStub; import org.jdrupes.vmoperator.common.VmDefinition; import org.jdrupes.vmoperator.runner.qemu.events.Exit; import org.jgrapes.core.Channel; @@ -109,17 +110,21 @@ public class VmDefUpdater extends Component { } /** - * Update condition. + * Update condition. The `from` VM definition is used to determine the + * observed generation and the current status. This method is intended + * to be called in the function passed to + * {@link K8sGenericStub#updateStatus}. * * @param from the VM definition - * @param status the current status * @param type the condition type * @param state the new state * @param reason the reason for the change * @param message the message + * @return the updated status */ - protected void updateCondition(VmDefinition from, JsonObject status, - String type, boolean state, String reason, String message) { + protected JsonObject updateCondition(VmDefinition from, String type, + boolean state, String reason, String message) { + JsonObject status = from.statusJson(); // Optimize, as we can get this several times var current = status.getAsJsonArray("conditions").asList().stream() .map(cond -> (JsonObject) cond) @@ -127,7 +132,7 @@ public class VmDefUpdater extends Component { .findFirst() .map(cond -> "True".equals(cond.get("status").getAsString())); if (current.isPresent() && current.get() == state) { - return; + return status; } // Do update @@ -150,5 +155,6 @@ public class VmDefUpdater extends Component { newConds.addAll(toReplace); status.add("conditions", apiClient.getJSON().getGson().toJsonTree(newConds)); + return status; } }