From 1e83cfff8dfb0fb641711cbfee606207418756e3 Mon Sep 17 00:00:00 2001 From: Sam Leonard Date: Tue, 9 Apr 2024 17:27:21 +0100 Subject: [PATCH] vmspawn: register with io.systemd.Machine.Register When available, use varlink to register the VM, so that we can talk over SSH to the guest. Enables 'machinectl shell' for vmspawn guests. --- src/vmspawn/vmspawn-register.c | 72 +++++++++++++++++++++++++--------- src/vmspawn/vmspawn-register.h | 10 ++++- src/vmspawn/vmspawn.c | 23 ++++++++--- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/src/vmspawn/vmspawn-register.c b/src/vmspawn/vmspawn-register.c index d04c3dafad9..35c14559452 100644 --- a/src/vmspawn/vmspawn-register.c +++ b/src/vmspawn/vmspawn-register.c @@ -5,36 +5,72 @@ #include "bus-error.h" #include "bus-locator.h" +#include "json.h" #include "macro.h" #include "process-util.h" +#include "socket-util.h" #include "string-util.h" +#include "varlink.h" #include "vmspawn-register.h" -int register_machine(sd_bus *bus, const char *machine_name, sd_id128_t uuid, const char *service, const char *directory) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +int register_machine( + sd_bus *bus, + const char *machine_name, + sd_id128_t uuid, + const char *service, + const char *directory, + unsigned cid, + const char *address, + const char *key_path) { + + _cleanup_(varlink_unrefp) Varlink *vl = NULL; int r; - assert(bus); assert(machine_name); assert(service); - r = bus_call_method( - bus, - bus_machine_mgr, - "RegisterMachine", - &error, - NULL, - "sayssus", - machine_name, - SD_BUS_MESSAGE_APPEND_ID128(uuid), - service, - "vm", - (uint32_t) getpid_cached(), - strempty(directory)); + /* First try to use varlink, as it provides more features (such as SSH support). */ + r = varlink_connect_address(&vl, "/run/systemd/machine/io.systemd.Machine"); + if (r == -ENOENT || ERRNO_IS_DISCONNECT(r)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + assert(bus); + + /* In case we are running with an older machined, fallback to the existing D-Bus method. */ + r = bus_call_method( + bus, + bus_machine_mgr, + "RegisterMachine", + &error, + NULL, + "sayssus", + machine_name, + SD_BUS_MESSAGE_APPEND_ID128(uuid), + service, + "vm", + (uint32_t) getpid_cached(), + strempty(directory)); + if (r < 0) + return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); + + return 0; + } if (r < 0) - return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to connect to machined on /run/systemd/machine/io.systemd.Machine: %m"); - return 0; + + return varlink_callb_and_log(vl, + "io.systemd.Machine.Register", + NULL, + JSON_BUILD_OBJECT( + JSON_BUILD_PAIR_STRING("name", machine_name), + JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(uuid), "id", JSON_BUILD_ID128(uuid)), + JSON_BUILD_PAIR_STRING("service", service), + JSON_BUILD_PAIR_STRING("class", "vm"), + JSON_BUILD_PAIR_CONDITION(VSOCK_CID_IS_REGULAR(cid), "vsockCid", JSON_BUILD_UNSIGNED(cid)), + JSON_BUILD_PAIR_CONDITION(directory, "rootDirectory", JSON_BUILD_STRING(directory)), + JSON_BUILD_PAIR_CONDITION(address, "sshAddress", JSON_BUILD_STRING(address)), + JSON_BUILD_PAIR_CONDITION(key_path, "sshPrivateKeyPath", JSON_BUILD_STRING(key_path)))); } int unregister_machine(sd_bus *bus, const char *machine_name) { diff --git a/src/vmspawn/vmspawn-register.h b/src/vmspawn/vmspawn-register.h index 7aa82ce849a..69f56714b2b 100644 --- a/src/vmspawn/vmspawn-register.h +++ b/src/vmspawn/vmspawn-register.h @@ -3,5 +3,13 @@ #include "sd-bus.h" #include "sd-id128.h" -int register_machine(sd_bus *bus, const char *machine_name, sd_id128_t uuid, const char *service, const char *directory); +int register_machine( + sd_bus *bus, + const char *machine_name, + sd_id128_t uuid, + const char *service, + const char *directory, + unsigned cid, + const char *address, + const char *key_path); int unregister_machine(sd_bus *bus, const char *machine_name); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 116c043709f..51f622d0a8e 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -1222,12 +1222,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { if (r < 0) return r; - if (arg_register) { - r = register_machine(bus, arg_machine, arg_uuid, trans_scope, arg_directory); - if (r < 0) - return r; - } - bool use_kvm = arg_kvm > 0; if (arg_kvm < 0) { r = qemu_check_kvm_support(); @@ -1931,6 +1925,23 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { log_debug("Executing: %s", joined); } + if (arg_register) { + char vm_address[STRLEN("vsock/") + DECIMAL_STR_MAX(unsigned)]; + + xsprintf(vm_address, "vsock/%u", child_cid); + r = register_machine( + bus, + arg_machine, + arg_uuid, + trans_scope, + arg_directory, + child_cid, + child_cid != VMADDR_CID_ANY ? vm_address : NULL, + ssh_private_key_path); + if (r < 0) + return r; + } + assert_se(sigprocmask_many(SIG_BLOCK, /* old_sigset=*/ NULL, SIGCHLD, SIGWINCH) >= 0); _cleanup_(sd_event_source_unrefp) sd_event_source *notify_event_source = NULL; -- 2.47.3