Make powerdown timeout configurable.

This commit is contained in:
Michael Lipp 2023-06-04 13:31:13 +02:00
parent 7a9ed262c1
commit 62cdea852c
4 changed files with 49 additions and 40 deletions

View file

@ -42,6 +42,11 @@
# * secure
# "bootMode": "uefi"
# When terminating, a graceful powerdown is attempted. If it
# doesn't succeed within the given timeout (seconds) SIGTERM
# is sent to Qemu.
# "powerdownTimeout": 60
# RAM settings
# "maximumRam": "1G"
# "currentRam": "1G"

View file

@ -69,6 +69,7 @@ class Configuration implements Dto {
public String accelerator = "kvm";
public String rtcBase = "utc";
public String rtcClock = "rt";
public int powerdownTimeout = 60;
public Drive[] drives;
public Spice spice;
}

View file

@ -67,9 +67,8 @@ public class QemuMonitor extends Component {
"powerdown", "{ \"execute\": \"system_powerdown\" }"));
private Path socketPath;
private int powerdownTimeout;
private SocketIOChannel monitorChannel;
private Stop suspendedStop;
/**
@ -88,9 +87,11 @@ public class QemuMonitor extends Component {
* {@link Runner} instead.
*
* @param socketPath the socket path
* @param powerdownTimeout
*/
/* default */ void configure(Path socketPath) {
/* default */ void configure(Path socketPath, int powerdownTimeout) {
this.socketPath = socketPath;
this.powerdownTimeout = powerdownTimeout;
}
/**
@ -245,7 +246,7 @@ public class QemuMonitor extends Component {
suspendedStop = null;
}
}
}, Duration.ofMillis(5000));
}, Duration.ofSeconds(powerdownTimeout));
}
}
}

View file

@ -200,35 +200,6 @@ public class Runner extends Component {
// Invalid configuration, not used, problems already logged.
config = null;
}
// Forward some values to child components
qemuMonitor.configure(config.monitorSocket);
} catch (IllegalArgumentException e) {
logger.log(Level.SEVERE, e, () -> "Invalid configuration: "
+ e.getMessage());
// Don't use default configuration
config = null;
}
}
/**
* Handle the start event.
*
* @param event the event
*/
@Handler
public void onStart(Start event) {
try {
if (config == null) {
// Missing configuration, fail
fire(new Stop());
return;
}
// Store process id
try (var pidFile = Files.newBufferedWriter(
Path.of(config.runtimeDir, "runner.pid"))) {
pidFile.write(ProcessHandle.current().pid() + "\n");
}
// Prepare firmware files and add to config
setFirmwarePaths();
@ -240,13 +211,14 @@ public class Runner extends Component {
qemuDefinition = Optional.ofNullable(tplData.get("qemu"))
.map(d -> new CommandDefinition("qemu", d)).orElse(null);
// Files to watch for
Files.deleteIfExists(config.swtpmSocket);
fire(new WatchFile(config.swtpmSocket));
} catch (IOException | TemplateException e) {
logger.log(Level.SEVERE, e,
() -> "Cannot configure runner: " + e.getMessage());
fire(new Stop());
// Forward some values to child components
qemuMonitor.configure(config.monitorSocket,
config.vm.powerdownTimeout);
} catch (IllegalArgumentException | IOException | TemplateException e) {
logger.log(Level.SEVERE, e, () -> "Invalid configuration: "
+ e.getMessage());
// Don't use default configuration
config = null;
}
}
@ -314,6 +286,36 @@ public class Runner extends Component {
return mapper.readValue(out.toString(), JsonNode.class);
}
/**
* Handle the start event.
*
* @param event the event
*/
@Handler
public void onStart(Start event) {
try {
if (config == null) {
// Missing configuration, fail
fire(new Stop());
return;
}
// Store process id
try (var pidFile = Files.newBufferedWriter(
Path.of(config.runtimeDir, "runner.pid"))) {
pidFile.write(ProcessHandle.current().pid() + "\n");
}
// Files to watch for
Files.deleteIfExists(config.swtpmSocket);
fire(new WatchFile(config.swtpmSocket));
} catch (IOException e) {
logger.log(Level.SEVERE, e,
() -> "Cannot start runner: " + e.getMessage());
fire(new Stop());
}
}
/**
* Handle the started event.
*