Skip to content

Commit

Permalink
Merge branch 'feature/booted-status' into testing
Browse files Browse the repository at this point in the history
  • Loading branch information
mnlipp committed Feb 18, 2025
2 parents be07468 + 777ae73 commit b310165
Show file tree
Hide file tree
Showing 16 changed files with 701 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.jdrupes.vmoperator.runner.qemu.commands.QmpCommand;
import org.jdrupes.vmoperator.runner.qemu.commands.QmpGuestGetOsinfo;
import org.jdrupes.vmoperator.runner.qemu.events.GuestAgentCommand;
import org.jdrupes.vmoperator.runner.qemu.events.MonitorReady;
import org.jdrupes.vmoperator.runner.qemu.events.OsinfoEvent;
import org.jdrupes.vmoperator.runner.qemu.events.VserportChangeEvent;
import org.jgrapes.core.Channel;
Expand Down Expand Up @@ -188,10 +187,6 @@ private void processGuestAgentInput(String line)
logger.fine(() -> "guest agent(in): " + line);
try {
var response = mapper.readValue(line, ObjectNode.class);
if (response.has("QMP")) {
rep.fire(new MonitorReady());
return;
}
if (response.has("return") || response.has("error")) {
QmpCommand executed = executing.poll();
logger.fine(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import org.jdrupes.vmoperator.runner.qemu.events.ConfigureQemu;
import org.jdrupes.vmoperator.runner.qemu.events.Exit;
import org.jdrupes.vmoperator.runner.qemu.events.MonitorCommand;
import org.jdrupes.vmoperator.runner.qemu.events.OsinfoEvent;
import org.jdrupes.vmoperator.runner.qemu.events.QmpConfigured;
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange;
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.RunState;
Expand Down Expand Up @@ -619,8 +620,8 @@ public void onInput(Input<?> event, ProcessChannel channel) {
}

/**
* On monitor ready.
*
* When the monitor is ready, send QEMU its initial configuration.
*
* @param event the event
*/
@Handler
Expand All @@ -629,34 +630,50 @@ public void onQmpConfigured(QmpConfigured event) {
}

/**
* On configure qemu.
* Whenever a new QEMU configuration is available, check if it
* is supposed to trigger a reset.
*
* @param event the event
*/
@Handler
public void onConfigureQemu(ConfigureQemu event) {
if (state.vmActive()) {
if (resetCounter != null
&& event.configuration().resetCounter != null
&& event.configuration().resetCounter > resetCounter) {
fire(new MonitorCommand(new QmpReset()));
}
resetCounter = event.configuration().resetCounter;
}
}

/**
* As last step when handling a new configuration, check if
* QEMU is suspended after startup and should be continued.
*
* @param event the event
*/
@Handler(priority = -1000)
public void onConfigureQemuFinal(ConfigureQemu event) {
if (state == RunState.STARTING) {
state = RunState.BOOTING;
fire(new MonitorCommand(new QmpCont()));
state = RunState.RUNNING;
rep.fire(new RunnerStateChange(state, "VmStarted",
"Qemu has been configured and is continuing"));
}
}

/**
* On configure qemu.
* Receiving the OSinfo means that the OS has been booted.
*
* @param event the event
*/
@Handler
public void onConfigureQemu(ConfigureQemu event) {
if (state == RunState.RUNNING) {
if (resetCounter != null
&& event.configuration().resetCounter != null
&& event.configuration().resetCounter > resetCounter) {
fire(new MonitorCommand(new QmpReset()));
}
resetCounter = event.configuration().resetCounter;
public void onOsinfo(OsinfoEvent event) {
if (state == RunState.BOOTING) {
state = RunState.BOOTED;
rep.fire(new RunnerStateChange(state, "VmBooted",
"The VM has started the guest agent."));
}
}

Expand All @@ -675,6 +692,7 @@ public void onProcessExited(ProcessExited event, ProcessChannel channel) {
mayBeStartQemu(QemuPreps.CloudInit);
return;
}

// No other process(es) may exit during startup
if (state == RunState.STARTING) {
logger.severe(() -> "Process " + procDef.name
Expand All @@ -683,7 +701,9 @@ public void onProcessExited(ProcessExited event, ProcessChannel channel) {
rep.fire(new Stop());
return;
}
if (procDef.equals(qemuDefinition) && state == RunState.RUNNING) {

// No processes may exit while the VM is running normally
if (procDef.equals(qemuDefinition) && state.vmActive()) {
rep.fire(new Exit(event.exitValue()));
}
logger.info(() -> "Process " + procDef.name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* VM-Operator
* Copyright (C) 2023,2024 Michael N. Lipp
* Copyright (C) 2023,2025 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
Expand Down Expand Up @@ -31,7 +31,6 @@
import io.kubernetes.client.openapi.models.EventsV1Event;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Set;
import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP;
Expand Down Expand Up @@ -66,9 +65,6 @@ public class StatusUpdater extends VmDefUpdater {
private static final ObjectMapper objectMapper
= new ObjectMapper().registerModule(new JavaTimeModule());

private static final Set<RunState> RUNNING_STATES
= Set.of(RunState.RUNNING, RunState.TERMINATING);

private long observedGeneration;
private boolean guestShutdownStops;
private boolean shutdownByGuest;
Expand Down Expand Up @@ -186,16 +182,23 @@ public void onRunnerStateChanged(RunnerStateChange event)
}
vmStub.updateStatus(vmDef, from -> {
JsonObject status = from.statusJson();
boolean running = RUNNING_STATES.contains(event.runState());
boolean running = event.runState().vmRunning();
updateCondition(vmDef, vmDef.statusJson(), "Running", running,
event.reason(), event.message());
updateCondition(vmDef, vmDef.statusJson(), "Booted",
event.runState() == RunState.BOOTED, event.reason(),
event.message());
if (event.runState() == RunState.STARTING) {
status.addProperty("ram", GsonPtr.to(from.data())
.getAsString("spec", "vm", "maximumRam").orElse("0"));
status.addProperty("cpus", 1);

// In case we had an irregular shutdown
status.remove("osinfo");
} else if (event.runState() == RunState.STOPPED) {
status.addProperty("ram", "0");
status.addProperty("cpus", 0);
status.remove("osinfo");
}

// In case console connection was still present
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.jdrupes.vmoperator.runner.qemu.events;

import java.util.EnumSet;
import org.jgrapes.core.Channel;
import org.jgrapes.core.Components;
import org.jgrapes.core.Event;
Expand All @@ -29,10 +30,28 @@
public class RunnerStateChange extends Event<Void> {

/**
* The state.
* The states.
*/
public enum RunState {
INITIALIZING, STARTING, RUNNING, TERMINATING, STOPPED
INITIALIZING, STARTING, BOOTING, BOOTED, TERMINATING, STOPPED;

/**
* Checks if the state is one of the states in which the VM is running.
*
* @return true, if is running
*/
public boolean vmRunning() {
return EnumSet.of(BOOTING, BOOTED, TERMINATING).contains(this);
}

/**
* Checks if the state is one of the states in which the VM is active.
*
* @return true, if is active
*/
public boolean vmActive() {
return EnumSet.of(BOOTING, BOOTED).contains(this);
}
}

private final RunState state;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
almalinux.svg:
Source: https://commons.wikimedia.org/wiki/File:AlmaLinux_Icon_Logo.svg
License: https://github.com/AlmaLinux/wiki/blob/master/LICENSE

archlinux.svg:
Source: https://commons.wikimedia.org/wiki/File:Arch_Linux_%22Crystal%22_icon.svghttps://commons.wikimedia.org/wiki/File:Arch_Linux_%22Crystal%22_icon.svg
License: GPL v2 or later

debian.svg:
Source: https://commons.wikimedia.org/wiki/File:Openlogo-debianV2.svg
License : LGPL

tux.svg:
Source: https://commons.wikimedia.org/wiki/File:Tux.svghttps://commons.wikimedia.org/wiki/File:Tux.svg
License: Creative Commons CC0 1.0 Universal Public Domain Dedication. Creative Commons CC0 1.0 Universal Public Domain Dedication.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b310165

Please sign in to comment.