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.
This commit is contained in:
Sam Leonard
2024-05-08 23:24:54 +01:00
committed by Luca Boccassi
parent 506aa3713b
commit 1e83cfff8d
3 changed files with 81 additions and 26 deletions
+55 -19
View 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));
if (r < 0)
return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
/* 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;
return 0;
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 connect to machined on /run/systemd/machine/io.systemd.Machine: %m");
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) {
+9 -1
View 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);
+17 -6
View 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;