]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn: register with io.systemd.Machine.Register
authorSam Leonard <sam.leonard@codethink.co.uk>
Tue, 9 Apr 2024 16:27:21 +0000 (17:27 +0100)
committerLuca Boccassi <bluca@debian.org>
Wed, 8 May 2024 22:24:54 +0000 (23:24 +0100)
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
src/vmspawn/vmspawn-register.h
src/vmspawn/vmspawn.c

index d04c3dafad90bb358104ce80562f570b91360672..35c14559452a5671ba7fa1fa04a0d43146740ed5 100644 (file)
@@ -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) {
index 7aa82ce849a0a4fdc46b8bd47aafafd30a6db1c1..69f56714b2b656470c539f3fff6ddc327fb51b0c 100644 (file)
@@ -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);
index 116c043709feae264232584512b1cfc8f3437510..51f622d0a8e30d9cea9279332c334c09571d850b 100644 (file)
@@ -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;