Use process exit as termination confirmation.

This commit is contained in:
Michael Lipp 2025-03-13 10:25:32 +01:00
parent 72e1b8a580
commit f493a2c582
4 changed files with 38 additions and 23 deletions

View file

@ -21,8 +21,8 @@
# Defaults for namespace (VM domain) # Defaults for namespace (VM domain)
handlers=java.util.logging.ConsoleHandler handlers=java.util.logging.ConsoleHandler
#org.jgrapes.level=FINE org.jgrapes.level=FINE
#org.jgrapes.core.handlerTracking.level=FINER org.jgrapes.core.handlerTracking.level=FINER
org.jdrupes.vmoperator.runner.qemu.level=FINEST org.jdrupes.vmoperator.runner.qemu.level=FINEST

View file

@ -242,7 +242,7 @@ public abstract class QemuConnector extends Component {
*/ */
@Handler @Handler
public void onClosed(Closed<?> event, SocketIOChannel channel) { public void onClosed(Closed<?> event, SocketIOChannel channel) {
channel.associated(this, getClass()).ifPresent(qm -> { channel.associated(this, getClass()).ifPresent(qc -> {
qemuChannel = null; qemuChannel = null;
}); });
} }

View file

@ -42,6 +42,7 @@ import org.jgrapes.core.Components.Timer;
import org.jgrapes.core.annotation.Handler; import org.jgrapes.core.annotation.Handler;
import org.jgrapes.core.events.Stop; import org.jgrapes.core.events.Stop;
import org.jgrapes.io.events.Closed; import org.jgrapes.io.events.Closed;
import org.jgrapes.io.events.ProcessExited;
import org.jgrapes.net.SocketIOChannel; import org.jgrapes.net.SocketIOChannel;
import org.jgrapes.util.events.ConfigurationUpdate; import org.jgrapes.util.events.ConfigurationUpdate;
@ -136,24 +137,12 @@ public class QemuMonitor extends QemuConnector {
* @param event the event * @param event the event
*/ */
@Handler @Handler
@SuppressWarnings({ "PMD.AvoidSynchronizedStatement",
"PMD.AvoidDuplicateLiterals" })
public void onClosed(Closed<?> event, SocketIOChannel channel) { public void onClosed(Closed<?> event, SocketIOChannel channel) {
channel.associated(this, getClass()).ifPresent(qm -> {
super.onClosed(event, channel); super.onClosed(event, channel);
logger.finer(() -> "QMP socket closed."); logger.finer(() -> "QMP socket closed.");
monitorReady = false; monitorReady = false;
channel.associated(this, getClass()).ifPresent(qm -> {
synchronized (this) {
if (powerdownTimer != null) {
powerdownTimer.cancel();
}
if (suspendedStop != null) {
suspendedStop.resumeHandling();
suspendedStop = null;
}
}
}); });
logger.finer(() -> "QMP socket closed.");
} }
/** /**
@ -163,7 +152,8 @@ public class QemuMonitor extends QemuConnector {
* @throws IOException * @throws IOException
*/ */
@Handler @Handler
@SuppressWarnings("PMD.AvoidSynchronizedStatement") @SuppressWarnings({ "PMD.AvoidSynchronizedStatement",
"PMD.AvoidDuplicateLiterals" })
public void onMonitorCommand(MonitorCommand event) throws IOException { public void onMonitorCommand(MonitorCommand event) throws IOException {
// Check prerequisites // Check prerequisites
if (!monitorReady && !(event.command() instanceof QmpCapabilities)) { if (!monitorReady && !(event.command() instanceof QmpCapabilities)) {
@ -228,7 +218,9 @@ public class QemuMonitor extends QemuConnector {
} }
/** /**
* On powerdown event. * When the powerdown event is confirmed, wait for termination
* or timeout. Termination is detected by the qemu process exiting
* (see {@link #onProcessExited(ProcessExited)}).
* *
* @param event the event * @param event the event
*/ */
@ -258,6 +250,29 @@ public class QemuMonitor extends QemuConnector {
} }
} }
/**
* On process exited.
*
* @param event the event
*/
@Handler
@SuppressWarnings("PMD.AvoidSynchronizedStatement")
public void onProcessExited(ProcessExited event) {
if (!event.startedBy().associated(CommandDefinition.class)
.map(cd -> Runner.QEMU.equals(cd.name())).orElse(false)) {
return;
}
synchronized (this) {
if (powerdownTimer != null) {
powerdownTimer.cancel();
}
if (suspendedStop != null) {
suspendedStop.resumeHandling();
suspendedStop = null;
}
}
}
/** /**
* On configure qemu. * On configure qemu.
* *

View file

@ -195,9 +195,9 @@ import org.jgrapes.util.events.WatchFile;
"PMD.CouplingBetweenObjects", "PMD.TooManyFields" }) "PMD.CouplingBetweenObjects", "PMD.TooManyFields" })
public class Runner extends Component { public class Runner extends Component {
private static final String QEMU = "qemu"; public static final String QEMU = "qemu";
private static final String SWTPM = "swtpm"; public static final String SWTPM = "swtpm";
private static final String CLOUD_INIT_IMG = "cloudInitImg"; public static final String CLOUD_INIT_IMG = "cloudInitImg";
private static final String TEMPLATE_DIR private static final String TEMPLATE_DIR
= "/opt/" + APP_NAME.replace("-", "") + "/templates"; = "/opt/" + APP_NAME.replace("-", "") + "/templates";
private static final String DEFAULT_TEMPLATE private static final String DEFAULT_TEMPLATE