From: Lennart Poettering Date: Mon, 16 Jun 2025 08:49:25 +0000 (+0200) Subject: vmspawn: introduce --notify-ready= switch X-Git-Tag: v258-rc1~79^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f820b275653c0315e31ca9c2100f2280b5582e17;p=thirdparty%2Fsystemd.git vmspawn: introduce --notify-ready= switch This mimics the switch of the same name from nspawn: it controls whether we expect a READY=1 message from the payload or not. Previously we'd always expect that. This makes it configurable, just like it is in nspawn. There's one fundamental difference in behaviour though: in nspawn it defaults to off, in vmspawn it defaults to on. (for historical reasons, ideally we'd default to on in both cases, but changing is quite a compat break both directly and indirectly: since timeouts might get triggered). --- diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index d9d0de918ba..d7d7d17f663 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -651,13 +651,15 @@ Configures support for notifications from the container's init process. - takes a boolean ( and ). - With option systemd-nspawn notifies systemd - with a READY=1 message when the init process is created. - With option systemd-nspawn waits for the - READY=1 message from the init process in the container - before sending its own to systemd. For more details about notifications - see sd_notify3. + takes a boolean. If false systemd-vmpawn + notifies the calling service manager with a READY=1 message when the init process is + created. If true it waits for a READY=1 message from the init process in the VM + before sending its own to the service manager. For more details about notifications see + sd_notify3. + + Defaults to false. (Note that this is unlike the option of the same name to + systemd-vmspawn1 + that defaults to true.) diff --git a/man/systemd-vmspawn.xml b/man/systemd-vmspawn.xml index 304bbb44a38..03a2da649b6 100644 --- a/man/systemd-vmspawn.xml +++ b/man/systemd-vmspawn.xml @@ -303,6 +303,25 @@ + + + + + Configures support for notifications from the VM's init process to + systemd-vmspawn. If true, systemd-vmspawn will consider the + machine as ready only when it has received a READY=1 message from the init + process in the VM. If false, systemd-vmspawn will consider the machine as ready + immediately after creation. In either case, systemd-vmspawn sends its own + readiness notification to its manager after the spawned VM is ready. For more details about + notifications see + sd_notify3. + + Defaults to true. (Note that this is unlike the option of the same name to + systemd-vmspawn1 + that defaults to false.) + + + diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index ce623cfd99b..6889734e9c7 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -139,6 +139,7 @@ static uint64_t arg_grow_image = 0; static char *arg_tpm_state_path = NULL; static TpmStateMode arg_tpm_state_mode = TPM_STATE_AUTO; static bool arg_ask_password = true; +static bool arg_notify_ready = true; STATIC_DESTRUCTOR_REGISTER(arg_directory, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -196,7 +197,9 @@ static int help(void) { " --firmware=PATH|list Select firmware definition file (or list available)\n" " --discard-disk=BOOL Control processing of discard requests\n" " -G --grow-image=BYTES Grow image file to specified size in bytes\n" + "\n%3$sExecution:%4$s\n" " -s --smbios11=STRING Pass an arbitrary SMBIOS Type #11 string to the VM\n" + " --notify-ready=BOOL Wait for ready notification from the VM\n" "\n%3$sSystem Identity:%4$s\n" " -M --machine=NAME Set the machine name for the VM\n" " --uuid=UUID Set a specific machine UUID for the VM\n" @@ -289,6 +292,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_TPM_STATE, ARG_NO_ASK_PASSWORD, ARG_PROPERTY, + ARG_NOTIFY_READY, }; static const struct option options[] = { @@ -337,6 +341,7 @@ static int parse_argv(int argc, char *argv[]) { { "tpm-state", required_argument, NULL, ARG_TPM_STATE }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "property", required_argument, NULL, ARG_PROPERTY }, + { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY }, {} }; @@ -673,6 +678,13 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_NOTIFY_READY: + r = parse_boolean_argument("--notify-ready=", optarg, &arg_notify_ready); + if (r < 0) + return r; + + break; + case '?': return -EINVAL; @@ -755,17 +767,20 @@ static int read_vsock_notify(NotifyConnectionData *d, int fd) { log_debug("Received notification message with tags: %s", strnull(j)); } + const char *status = strv_find_startswith(tags, "STATUS="); + if (status) + (void) sd_notifyf(/* unset_environment= */ false, "STATUS=VM running: %s", status); + if (strv_contains(tags, "READY=1")) { - r = sd_notify(false, "READY=1"); + r = sd_notify(/* unset_environment= */ false, "READY=1"); if (r < 0) log_warning_errno(r, "Failed to send readiness notification, ignoring: %m"); - } - const char *p = strv_find_startswith(tags, "STATUS="); - if (p) - (void) sd_notifyf(false, "STATUS=VM running: %s", p); + if (!status) + (void) sd_notifyf(/* unset_environment= */ false, "STATUS=VM running."); + } - p = strv_find_startswith(tags, "EXIT_STATUS="); + const char *p = strv_find_startswith(tags, "EXIT_STATUS="); if (p) { uint8_t k = 0; r = safe_atou8(p, &k); @@ -2669,6 +2684,16 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { child_vsock_fd = safe_close(child_vsock_fd); tap_fd = safe_close(tap_fd); + /* Report that the VM is now set up */ + (void) sd_notifyf(/* unset_environment= */ false, + "STATUS=VM started.\n" + "X_VMSPAWN_LEADER_PID=" PID_FMT, child_pidref.pid); + if (!arg_notify_ready) { + r = sd_notify(/* unset_environment= */ false, "READY=1\n"); + if (r < 0) + log_warning_errno(r, "Failed to send readiness notification, ignoring: %m"); + } + /* All operations that might need Polkit authorizations (i.e. machine registration, netif * acquisition, …) are complete now, get rid of the agent again, so that we retain exclusive control * of the TTY from now on. */