shared: extract disk-spec parsing into machine-util
Move the ImageFormat / DiskType enums and their string tables out of vmspawn's private settings header into a new src/shared/machine-util, and add parse_disk_spec() — the colon-prefix loop that turns "[FORMAT:][DISKTYPE:]PATH" into the two enums plus a normalized path. No behavior change for vmspawn. A follow-up machinectl attach-disk change accepts the same syntax and consumes the shared helper. Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "machine-util.h"
|
||||
#include "parse-argument.h"
|
||||
#include "string-table.h"
|
||||
|
||||
static const char *const image_format_table[_IMAGE_FORMAT_MAX] = {
|
||||
[IMAGE_FORMAT_RAW] = "raw",
|
||||
[IMAGE_FORMAT_QCOW2] = "qcow2",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
|
||||
|
||||
static const char *const disk_type_table[_DISK_TYPE_MAX] = {
|
||||
[DISK_TYPE_VIRTIO_BLK] = "virtio-blk",
|
||||
[DISK_TYPE_VIRTIO_SCSI] = "virtio-scsi",
|
||||
[DISK_TYPE_NVME] = "nvme",
|
||||
[DISK_TYPE_VIRTIO_SCSI_CDROM] = "scsi-cd",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(disk_type, DiskType);
|
||||
|
||||
/* Wire value for the io.systemd.VirtualMachineInstance.BlockDriver IDL enum. */
|
||||
static const char *const block_driver_table[_DISK_TYPE_MAX] = {
|
||||
[DISK_TYPE_VIRTIO_BLK] = "virtio_blk",
|
||||
[DISK_TYPE_VIRTIO_SCSI] = "scsi_hd",
|
||||
[DISK_TYPE_NVME] = "nvme",
|
||||
[DISK_TYPE_VIRTIO_SCSI_CDROM] = "scsi_cd",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(block_driver, DiskType);
|
||||
|
||||
/* QEMU -device driver name (e.g. "virtio-blk-pci"). */
|
||||
static const char *const qemu_device_driver_table[_DISK_TYPE_MAX] = {
|
||||
[DISK_TYPE_VIRTIO_BLK] = "virtio-blk-pci",
|
||||
[DISK_TYPE_VIRTIO_SCSI] = "scsi-hd",
|
||||
[DISK_TYPE_NVME] = "nvme",
|
||||
[DISK_TYPE_VIRTIO_SCSI_CDROM] = "scsi-cd",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(qemu_device_driver, DiskType);
|
||||
|
||||
int parse_disk_spec(
|
||||
const char *arg,
|
||||
ImageFormat *format,
|
||||
DiskType *disk_type,
|
||||
char **ret_path) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(arg);
|
||||
assert(format);
|
||||
assert(disk_type);
|
||||
assert(ret_path);
|
||||
|
||||
ImageFormat parsed_format = *format;
|
||||
DiskType parsed_disk_type = *disk_type;
|
||||
const char *dp = arg;
|
||||
|
||||
/* Format and disk-type vocabularies don't overlap, so prefixes may appear in any order. */
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
const char *save = dp;
|
||||
|
||||
r = extract_first_word(&dp, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0 || !dp) {
|
||||
/* No ':' remained after this word — rest is the path. */
|
||||
dp = save;
|
||||
break;
|
||||
}
|
||||
|
||||
ImageFormat f = image_format_from_string(word);
|
||||
if (f >= 0) {
|
||||
parsed_format = f;
|
||||
continue;
|
||||
}
|
||||
|
||||
DiskType dt = disk_type_from_string(word);
|
||||
if (dt >= 0) {
|
||||
parsed_disk_type = dt;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Unknown prefix — rewind, remainder is the path. */
|
||||
dp = save;
|
||||
break;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *path = NULL;
|
||||
r = parse_path_argument(dp, /* suppress_root= */ false, &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*format = parsed_format;
|
||||
*disk_type = parsed_disk_type;
|
||||
*ret_path = TAKE_PTR(path);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "shared-forward.h"
|
||||
|
||||
typedef enum ImageFormat {
|
||||
IMAGE_FORMAT_RAW,
|
||||
IMAGE_FORMAT_QCOW2,
|
||||
_IMAGE_FORMAT_MAX,
|
||||
_IMAGE_FORMAT_INVALID = -EINVAL,
|
||||
} ImageFormat;
|
||||
|
||||
typedef enum DiskType {
|
||||
DISK_TYPE_VIRTIO_BLK,
|
||||
DISK_TYPE_VIRTIO_SCSI,
|
||||
DISK_TYPE_NVME,
|
||||
DISK_TYPE_VIRTIO_SCSI_CDROM,
|
||||
_DISK_TYPE_MAX,
|
||||
_DISK_TYPE_INVALID = -EINVAL,
|
||||
} DiskType;
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
|
||||
DECLARE_STRING_TABLE_LOOKUP(disk_type, DiskType);
|
||||
DECLARE_STRING_TABLE_LOOKUP(block_driver, DiskType);
|
||||
DECLARE_STRING_TABLE_LOOKUP(qemu_device_driver, DiskType);
|
||||
|
||||
/* Parse "[FORMAT:][DISKTYPE:]PATH"; *format and *disk_type are in-out. */
|
||||
int parse_disk_spec(
|
||||
const char *arg,
|
||||
ImageFormat *format,
|
||||
DiskType *disk_type,
|
||||
char **ret_path);
|
||||
@@ -133,6 +133,7 @@ shared_sources = files(
|
||||
'machine-credential.c',
|
||||
'machine-id-setup.c',
|
||||
'machine-register.c',
|
||||
'machine-util.c',
|
||||
'macvlan-util.c',
|
||||
'main-func.c',
|
||||
'metrics.c',
|
||||
|
||||
@@ -3,22 +3,6 @@
|
||||
#include "string-table.h"
|
||||
#include "vmspawn-settings.h"
|
||||
|
||||
static const char *const image_format_table[_IMAGE_FORMAT_MAX] = {
|
||||
[IMAGE_FORMAT_RAW] = "raw",
|
||||
[IMAGE_FORMAT_QCOW2] = "qcow2",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
|
||||
|
||||
static const char *const disk_type_table[_DISK_TYPE_MAX] = {
|
||||
[DISK_TYPE_VIRTIO_BLK] = "virtio-blk",
|
||||
[DISK_TYPE_VIRTIO_SCSI] = "virtio-scsi",
|
||||
[DISK_TYPE_NVME] = "nvme",
|
||||
[DISK_TYPE_VIRTIO_SCSI_CDROM] = "scsi-cd",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(disk_type, DiskType);
|
||||
|
||||
void extra_drive_context_done(ExtraDriveContext *ctx) {
|
||||
assert(ctx);
|
||||
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "machine-util.h"
|
||||
#include "shared-forward.h"
|
||||
|
||||
typedef enum ImageFormat {
|
||||
IMAGE_FORMAT_RAW,
|
||||
IMAGE_FORMAT_QCOW2,
|
||||
_IMAGE_FORMAT_MAX,
|
||||
_IMAGE_FORMAT_INVALID = -EINVAL,
|
||||
} ImageFormat;
|
||||
|
||||
typedef enum DiskType {
|
||||
DISK_TYPE_VIRTIO_BLK,
|
||||
DISK_TYPE_VIRTIO_SCSI,
|
||||
DISK_TYPE_NVME,
|
||||
DISK_TYPE_VIRTIO_SCSI_CDROM,
|
||||
_DISK_TYPE_MAX,
|
||||
_DISK_TYPE_INVALID = -EINVAL,
|
||||
} DiskType;
|
||||
|
||||
typedef struct ExtraDrive {
|
||||
char *path;
|
||||
ImageFormat format;
|
||||
@@ -69,6 +54,4 @@ typedef enum SettingsMask {
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
|
||||
DECLARE_STRING_TABLE_LOOKUP(console_transport, ConsoleTransport);
|
||||
DECLARE_STRING_TABLE_LOOKUP(disk_type, DiskType);
|
||||
DECLARE_STRING_TABLE_LOOKUP(firmware, Firmware);
|
||||
DECLARE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
|
||||
|
||||
+2
-32
@@ -752,39 +752,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
OPTION_LONG("extra-drive", "[FORMAT:][DISKTYPE:]PATH", "Adds an additional disk to the VM"): {
|
||||
ImageFormat format = IMAGE_FORMAT_RAW;
|
||||
DiskType extra_disk_type = _DISK_TYPE_INVALID;
|
||||
const char *dp = arg;
|
||||
|
||||
/* Parse optional colon-separated prefixes. The format and disk type
|
||||
* value sets don't overlap, so they can appear in any order. */
|
||||
for (;;) {
|
||||
const char *colon = strchr(dp, ':');
|
||||
if (!colon)
|
||||
break;
|
||||
|
||||
_cleanup_free_ char *prefix = strndup(dp, colon - dp);
|
||||
if (!prefix)
|
||||
return log_oom();
|
||||
|
||||
ImageFormat f = image_format_from_string(prefix);
|
||||
if (f >= 0) {
|
||||
format = f;
|
||||
dp = colon + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
DiskType dt = disk_type_from_string(prefix);
|
||||
if (dt >= 0) {
|
||||
extra_disk_type = dt;
|
||||
dp = colon + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not a recognized prefix, treat the rest as the path */
|
||||
break;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *drive_path = NULL;
|
||||
r = parse_path_argument(dp, /* suppress_root= */ false, &drive_path);
|
||||
|
||||
r = parse_disk_spec(arg, &format, &extra_disk_type, &drive_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user