vmspawn: add --bind-volume= command line option
systemd-vmspawn --bind-volume=PROVIDER:VOLUME[:CONFIG][:K=V,...] For each --bind-volume passed at startup, vmspawn calls Acquire() on the named StorageProvider and attaches the resulting fd to the VM as an additional drive. The drive is identified by the user-visible name '<provider>:<volume>' on the bridge — that is also the handle used later when machinectl unbind-volume detaches drives at runtime (though boot-time drives like these are NOT removable; that is the StorageImmutable behaviour added earlier). The colon grammar is parsed by the shared bind_volume_parse() helper. The 3rd 'config' field selects the guest device type from the disk_type_table[] vocabulary (virtio-blk, virtio-scsi, nvme, scsi-cd); empty defaults to virtio-blk per the TASK grammar. Wiring lives next to the existing --extra-drive setup: parse_argv() appends a parsed BindVolume to arg_bind_volumes, and prepare_device_info() hands the array to vmspawn_bind_volume_prepare_boot() which Acquires each volume and pushes a DriveInfo onto the existing drives array. PCIe port assignment (assign_pcie_ports()) and the QMP setup loop pick them up automatically. Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
@@ -38,7 +38,7 @@ _systemd_vmspawn() {
|
||||
[BIND]='--bind --bind-ro'
|
||||
[SSH_KEY]='--ssh-key'
|
||||
[CONSOLE]='--console'
|
||||
[ARG]='--cpus --ram --vsock-cid -M --machine --uuid --private-users --background --set-credential --load-credential --forward-journal-max-use --forward-journal-keep-free --forward-journal-max-file-size --forward-journal-max-files'
|
||||
[ARG]='--cpus --ram --vsock-cid -M --machine --uuid --private-users --background --set-credential --load-credential --forward-journal-max-use --forward-journal-keep-free --forward-journal-max-file-size --forward-journal-max-files --bind-volume'
|
||||
[IMAGE_FORMAT]='--image-format'
|
||||
[IMAGE_DISK_TYPE]='--image-disk-type'
|
||||
)
|
||||
|
||||
+32
-1
@@ -88,6 +88,7 @@
|
||||
#include "user-record.h"
|
||||
#include "user-util.h"
|
||||
#include "utf8.h"
|
||||
#include "vmspawn-bind-volume.h"
|
||||
#include "vmspawn-mount.h"
|
||||
#include "vmspawn-qemu-config.h"
|
||||
#include "vmspawn-qmp.h"
|
||||
@@ -163,6 +164,7 @@ static bool arg_keep_unit = false;
|
||||
static sd_id128_t arg_uuid = {};
|
||||
static char **arg_kernel_cmdline_extra = NULL;
|
||||
static ExtraDriveContext arg_extra_drives = {};
|
||||
static BindVolumes arg_bind_volumes = {};
|
||||
static char *arg_background = NULL;
|
||||
static bool arg_pass_ssh_key = true;
|
||||
static char *arg_ssh_key_type = NULL;
|
||||
@@ -200,6 +202,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_runtime_mounts, runtime_mount_context_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline_extra, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_extra_drives, extra_drive_context_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_bind_volumes, bind_volumes_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_ssh_key_type, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_smbios11, strv_freep);
|
||||
@@ -766,6 +769,30 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
OPTION_LONG("bind-volume", "PROVIDER:VOLUME[:CONFIG][:KEY=VALUE,...]",
|
||||
"Acquire a storage volume from a StorageProvider and attach it to the VM"): {
|
||||
_cleanup_(bind_volume_freep) BindVolume *bv = NULL;
|
||||
|
||||
r = bind_volume_parse(opts.arg, &bv);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --bind-volume= argument '%s': %m", opts.arg);
|
||||
|
||||
if (disk_type_from_bind_volume_config(bv->config) < 0) {
|
||||
_cleanup_free_ char *valid = NULL;
|
||||
for (DiskType t = 0; t < _DISK_TYPE_MAX; t++)
|
||||
if (!strextend_with_separator(&valid, ", ", disk_type_to_string(t)))
|
||||
return log_oom();
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unknown device type '%s' for --bind-volume=. Valid values: %s.",
|
||||
bv->config, valid);
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(arg_bind_volumes.items, arg_bind_volumes.n_items + 1))
|
||||
return log_oom();
|
||||
arg_bind_volumes.items[arg_bind_volumes.n_items++] = TAKE_PTR(bv);
|
||||
break;
|
||||
}
|
||||
|
||||
OPTION_LONG("bind-user", "NAME", "Bind user from host to virtual machine"):
|
||||
if (!valid_user_group_name(opts.arg, /* flags= */ 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid user name to bind: %s", opts.arg);
|
||||
@@ -2475,7 +2502,7 @@ static int prepare_device_info(const char *runtime_dir, MachineConfig *c) {
|
||||
|
||||
/* Build drive info for QMP-based setup. vmspawn opens all image files and
|
||||
* passes fds to QEMU via add-fd — QEMU never needs filesystem access. */
|
||||
drives->drives = new0(DriveInfo*, 1 + arg_extra_drives.n_drives);
|
||||
drives->drives = new0(DriveInfo*, 1 + arg_extra_drives.n_drives + arg_bind_volumes.n_items);
|
||||
if (!drives->drives)
|
||||
return log_oom();
|
||||
|
||||
@@ -2487,6 +2514,10 @@ static int prepare_device_info(const char *runtime_dir, MachineConfig *c) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = vmspawn_bind_volume_prepare_boot(arg_runtime_scope, &arg_bind_volumes, drives);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return assign_pcie_ports(c);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user