[libvirt] [sandbox PATCH 0/4] Getting qemu sandboxes run as root + host-image format

Hi all, Here are a few patches to make sandboxes run with qemu:///system connection. The last one is just a new feature to allow using somethings else than RAW images in host-image mounts. This feature will later be needed to run docker container using Eren's work. Cédric Bosdonnat (4): Make sure the sandbox state dir and config can be accessed Write /dev/vd* instead of vd* in mounts.cfg qemu: mount all host-images as ext4 Add host-image format parameter .../libvirt-sandbox-builder-container.c | 4 + libvirt-sandbox/libvirt-sandbox-builder-machine.c | 13 +++- .../libvirt-sandbox-config-mount-host-image.c | 91 +++++++++++++++++++++- .../libvirt-sandbox-config-mount-host-image.h | 5 +- libvirt-sandbox/libvirt-sandbox-config.c | 70 +++++++++++++++-- .../libvirt-sandbox-context-interactive.c | 4 +- libvirt-sandbox/libvirt-sandbox.sym | 5 ++ libvirt-sandbox/tests/test-config.c | 1 + 8 files changed, 180 insertions(+), 13 deletions(-) -- 2.1.4

When running a KVM sandbox as root, the qemu process will run as another user (likely qemu). We need to make sure this user can access the vmlinux and initrd.img, sandbox.cfg and mounts.cfg files. --- libvirt-sandbox/libvirt-sandbox-config.c | 2 +- libvirt-sandbox/libvirt-sandbox-context-interactive.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libvirt-sandbox/libvirt-sandbox-config.c b/libvirt-sandbox/libvirt-sandbox-config.c index 087b5ce..8991043 100644 --- a/libvirt-sandbox/libvirt-sandbox-config.c +++ b/libvirt-sandbox/libvirt-sandbox-config.c @@ -2258,7 +2258,7 @@ gboolean gvir_sandbox_config_save_to_path(GVirSandboxConfig *config, if (!(data = g_key_file_to_data(file, &len, error))) goto cleanup; - if (!(os = G_OUTPUT_STREAM(g_file_create(f, G_FILE_CREATE_PRIVATE, NULL, error)))) + if (!(os = G_OUTPUT_STREAM(g_file_create(f, G_FILE_CREATE_NONE, NULL, error)))) goto cleanup; if (!g_output_stream_write_all(os, data, len, NULL, NULL, error)) diff --git a/libvirt-sandbox/libvirt-sandbox-context-interactive.c b/libvirt-sandbox/libvirt-sandbox-context-interactive.c index cec7965..78b2fbd 100644 --- a/libvirt-sandbox/libvirt-sandbox-context-interactive.c +++ b/libvirt-sandbox/libvirt-sandbox-context-interactive.c @@ -217,8 +217,8 @@ static gboolean gvir_sandbox_context_interactive_start(GVirSandboxContext *ctxt, error))) goto cleanup; - g_mkdir_with_parents(statedir, 0700); - g_mkdir_with_parents(configdir, 0700); + g_mkdir_with_parents(statedir, 0755); + g_mkdir_with_parents(configdir, 0755); unlink(configfile); if (!gvir_sandbox_config_save_to_path(config, configfile, error)) -- 2.1.4

Fixes a regression introduced by d74b4350: the init-qemu tool expects /dev/vd* sources to create the block device, while we were just having vd*. Write again /dev/vd* to mounts.cfg. --- libvirt-sandbox/libvirt-sandbox-builder-machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c b/libvirt-sandbox/libvirt-sandbox-builder-machine.c index 35a5816..c446447 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c +++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c @@ -303,7 +303,7 @@ static gboolean gvir_sandbox_builder_machine_write_mount_cfg(GVirSandboxConfig * fstype = "9p"; options = g_strdup("trans=virtio,version=9p2000.u"); } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_HOST_IMAGE(mconfig)) { - source = g_strdup_printf("vd%c", (char)('a' + nHostImage++)); + source = g_strdup_printf("/dev/vd%c", (char)('a' + nHostImage++)); fstype = "ext3"; options = g_strdup(""); } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_GUEST_BIND(mconfig)) { -- 2.1.4

To avoid troubles when mounting ext4 images, hard-code ext4 as mount format instead of ext3. --- libvirt-sandbox/libvirt-sandbox-builder-machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c b/libvirt-sandbox/libvirt-sandbox-builder-machine.c index c446447..e342ba1 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c +++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c @@ -304,7 +304,7 @@ static gboolean gvir_sandbox_builder_machine_write_mount_cfg(GVirSandboxConfig * options = g_strdup("trans=virtio,version=9p2000.u"); } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_HOST_IMAGE(mconfig)) { source = g_strdup_printf("/dev/vd%c", (char)('a' + nHostImage++)); - fstype = "ext3"; + fstype = "ext4"; options = g_strdup(""); } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_GUEST_BIND(mconfig)) { GVirSandboxConfigMountFile *mfile = GVIR_SANDBOX_CONFIG_MOUNT_FILE(mconfig); -- 2.1.4

Let the user specify the format of the source disk image in host-image mounts. This will allow us to mount other image types than raw ones. --- .../libvirt-sandbox-builder-container.c | 4 + libvirt-sandbox/libvirt-sandbox-builder-machine.c | 9 +++ .../libvirt-sandbox-config-mount-host-image.c | 91 +++++++++++++++++++++- .../libvirt-sandbox-config-mount-host-image.h | 5 +- libvirt-sandbox/libvirt-sandbox-config.c | 68 +++++++++++++++- libvirt-sandbox/libvirt-sandbox.sym | 5 ++ libvirt-sandbox/tests/test-config.c | 1 + 7 files changed, 175 insertions(+), 8 deletions(-) diff --git a/libvirt-sandbox/libvirt-sandbox-builder-container.c b/libvirt-sandbox/libvirt-sandbox-builder-container.c index c3a58b2..383c956 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder-container.c +++ b/libvirt-sandbox/libvirt-sandbox-builder-container.c @@ -273,6 +273,8 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil g_object_unref(fs); } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_HOST_IMAGE(mconfig)) { GVirSandboxConfigMountFile *mfile = GVIR_SANDBOX_CONFIG_MOUNT_FILE(mconfig); + GVirSandboxConfigMountHostImage *mimage = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(mconfig); + GVirConfigDomainDiskFormat format; fs = gvir_config_domain_filesys_new(); gvir_config_domain_filesys_set_type(fs, GVIR_CONFIG_DOMAIN_FILESYS_FILE); @@ -281,6 +283,8 @@ static gboolean gvir_sandbox_builder_container_construct_devices(GVirSandboxBuil gvir_sandbox_config_mount_file_get_source(mfile)); gvir_config_domain_filesys_set_target(fs, gvir_sandbox_config_mount_get_target(mconfig)); + format = gvir_sandbox_config_mount_host_image_get_format(mimage); + gvir_config_domain_filesys_set_driver_format(fs, format); gvir_config_domain_add_device(domain, GVIR_CONFIG_DOMAIN_DEVICE(fs)); diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c b/libvirt-sandbox/libvirt-sandbox-builder-machine.c index e342ba1..5e6bf72 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c +++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c @@ -497,6 +497,7 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde { GVirConfigDomainFilesys *fs; GVirConfigDomainDisk *disk; + GVirConfigDomainDiskDriver *diskDriver; GVirConfigDomainInterface *iface; GVirConfigDomainMemballoon *ball; GVirConfigDomainConsole *con; @@ -560,6 +561,8 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde } else if (GVIR_SANDBOX_IS_CONFIG_MOUNT_HOST_IMAGE(mconfig)) { GVirSandboxConfigMountFile *mfile = GVIR_SANDBOX_CONFIG_MOUNT_FILE(mconfig); + GVirSandboxConfigMountHostImage *mimage = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(mconfig); + GVirConfigDomainDiskFormat format; gchar *target = g_strdup_printf("vd%c", (char)('a' + nHostImage++)); disk = gvir_config_domain_disk_new(); @@ -568,8 +571,14 @@ static gboolean gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde gvir_sandbox_config_mount_file_get_source(mfile)); gvir_config_domain_disk_set_target_dev(disk, target); + diskDriver = gvir_config_domain_disk_driver_new(); + format = gvir_sandbox_config_mount_host_image_get_format(mimage); + gvir_config_domain_disk_driver_set_format(diskDriver, format); + gvir_config_domain_disk_set_driver(disk, diskDriver); + gvir_config_domain_add_device(domain, GVIR_CONFIG_DOMAIN_DEVICE(disk)); + g_object_unref(diskDriver); g_object_unref(disk); g_free(target); } diff --git a/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.c b/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.c index 61e8f42..37573ef 100644 --- a/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.c +++ b/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.c @@ -45,21 +45,90 @@ struct _GVirSandboxConfigMountHostImagePrivate { - gboolean unused; + GVirConfigDomainDiskFormat format; }; G_DEFINE_TYPE(GVirSandboxConfigMountHostImage, gvir_sandbox_config_mount_host_image, GVIR_SANDBOX_TYPE_CONFIG_MOUNT_FILE); +enum { + PROP_0, + PROP_FORMAT, +}; + +enum { + LAST_SIGNAL +}; + +//static gint signals[LAST_SIGNAL]; + + +static void gvir_sandbox_config_mount_host_image_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GVirSandboxConfigMountHostImage *config = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(object); + GVirSandboxConfigMountHostImagePrivate *priv = config->priv; + + switch (prop_id) { + case PROP_FORMAT: + g_value_set_enum(value, priv->format); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + + +static void gvir_sandbox_config_mount_host_image_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GVirSandboxConfigMountHostImage *config = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(object); + GVirSandboxConfigMountHostImagePrivate *priv = config->priv; + + switch (prop_id) { + case PROP_FORMAT: + priv->format = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + static void gvir_sandbox_config_mount_host_image_class_init(GVirSandboxConfigMountHostImageClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = gvir_sandbox_config_mount_host_image_get_property; + object_class->set_property = gvir_sandbox_config_mount_host_image_set_property; + + g_object_class_install_property(object_class, + PROP_FORMAT, + g_param_spec_enum("format", + "Disk format", + "The disk format", + GVIR_CONFIG_TYPE_DOMAIN_DISK_FORMAT, + GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + g_type_class_add_private(klass, sizeof(GVirSandboxConfigMountHostImagePrivate)); } static void gvir_sandbox_config_mount_host_image_init(GVirSandboxConfigMountHostImage *config) { - config->priv = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE_GET_PRIVATE(config); + GVirSandboxConfigMountHostImagePrivate *priv = config->priv; + priv = config->priv = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE_GET_PRIVATE(config); + + priv->format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW; } @@ -72,14 +141,30 @@ static void gvir_sandbox_config_mount_host_image_init(GVirSandboxConfigMountHost * Returns: (transfer full): a new sandbox mount object */ GVirSandboxConfigMountHostImage *gvir_sandbox_config_mount_host_image_new(const gchar *source, - const gchar *targetdir) + const gchar *targetdir, + GVirConfigDomainDiskFormat format) { return GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(g_object_new(GVIR_SANDBOX_TYPE_CONFIG_MOUNT_HOST_IMAGE, "source", source, "target", targetdir, + "format", format, NULL)); } +/** + * gvir_sandbox_config_mount_host_image_get_format: + * @config: (transfer none): the sandbox mount config + * + * Retrieves the image format of the host-image filesystem. + * + * Returns: (transfer none): the imave format + */ +GVirConfigDomainDiskFormat gvir_sandbox_config_mount_host_image_get_format(GVirSandboxConfigMountHostImage *config) +{ + GVirSandboxConfigMountHostImagePrivate *priv = config->priv; + return priv->format; +} + /* * Local variables: * c-indent-level: 4 diff --git a/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.h b/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.h index 228c459..95ec05e 100644 --- a/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.h +++ b/libvirt-sandbox/libvirt-sandbox-config-mount-host-image.h @@ -59,7 +59,10 @@ struct _GVirSandboxConfigMountHostImageClass GType gvir_sandbox_config_mount_host_image_get_type(void); GVirSandboxConfigMountHostImage *gvir_sandbox_config_mount_host_image_new(const gchar *source, - const gchar *targetdir); + const gchar *targetdir, + GVirConfigDomainDiskFormat format); + +GVirConfigDomainDiskFormat gvir_sandbox_config_mount_host_image_get_format(GVirSandboxConfigMountHostImage *config); G_END_DECLS diff --git a/libvirt-sandbox/libvirt-sandbox-config.c b/libvirt-sandbox/libvirt-sandbox-config.c index 8991043..fbc65a6 100644 --- a/libvirt-sandbox/libvirt-sandbox-config.c +++ b/libvirt-sandbox/libvirt-sandbox-config.c @@ -1266,6 +1266,7 @@ gboolean gvir_sandbox_config_add_mount_strv(GVirSandboxConfig *config, * * - host-bind:/tmp=/var/lib/sandbox/demo/tmp * - host-image:/=/var/lib/sandbox/demo.img + * - host-image:/=/var/lib/sandbox/demo.qcow2,format=qcow2 * - guest-bind:/home=/tmp/home * - ram:/tmp=500M */ @@ -1327,6 +1328,33 @@ gboolean gvir_sandbox_config_add_mount_opts(GVirSandboxConfig *config, } mnt = GVIR_SANDBOX_CONFIG_MOUNT(gvir_sandbox_config_mount_ram_new(target, size)); + } else if (type == GVIR_SANDBOX_TYPE_CONFIG_MOUNT_HOST_IMAGE) { + const gchar *formatStr = NULL; + gint format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW; + + if ((tmp = strchr(source, ',')) != NULL) { + GEnumClass *enum_class = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_FORMAT); + GEnumValue *enum_value = NULL; + + *tmp = '\0'; + formatStr = tmp + 1; + + if ((strncmp(formatStr, "format=", 7) == 0) && + !(enum_value = g_enum_get_value_by_nick(enum_class, formatStr + 7))) { + g_type_class_unref(enum_class); + g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0, + _("Unknown disk image format: '%s'"), formatStr + 7); + return FALSE; + } + g_type_class_unref(enum_class); + format = enum_value->value; + } + + mnt = GVIR_SANDBOX_CONFIG_MOUNT(g_object_new(type, + "target", target, + "source", source, + "format", format, + NULL)); } else { mnt = GVIR_SANDBOX_CONFIG_MOUNT(g_object_new(type, "target", target, @@ -1615,6 +1643,7 @@ static GVirSandboxConfigMount *gvir_sandbox_config_load_config_mount(GKeyFile *f gchar *target = NULL; gchar *source = NULL; gchar *type = NULL; + gchar *formatStr = NULL; guint j; GError *e = NULL; GType mountType; @@ -1664,10 +1693,33 @@ static GVirSandboxConfigMount *gvir_sandbox_config_load_config_mount(GKeyFile *f goto error; } - config = GVIR_SANDBOX_CONFIG_MOUNT(g_object_new(mountType, - "target", target, - "source", source, - NULL)); + if (mountType == GVIR_SANDBOX_TYPE_CONFIG_MOUNT_HOST_IMAGE) { + GEnumClass *enum_class = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_FORMAT); + GEnumValue *enum_value; + + if ((formatStr = g_key_file_get_string(file, key, "format", NULL)) == NULL) { + g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0, + "%s", _("Missing image format in config file")); + goto error; + } + + if (!(enum_value = g_enum_get_value_by_nick(enum_class, formatStr))) { + g_type_class_unref(enum_class); + g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0, + _("Unknown image format %s in config file"), formatStr); + goto error; + } + g_type_class_unref(enum_class); + + config = GVIR_SANDBOX_CONFIG_MOUNT(gvir_sandbox_config_mount_host_image_new(source, + target, + enum_value->value)); + } else { + config = GVIR_SANDBOX_CONFIG_MOUNT(g_object_new(mountType, + "target", target, + "source", source, + NULL)); + } } for (j = 0 ; j < 1024 ; j++) { @@ -1964,6 +2016,14 @@ static void gvir_sandbox_config_save_config_mount(GVirSandboxConfigMount *config g_key_file_set_string(file, key, "usage", tmp); g_free(tmp); } else { + if (GVIR_SANDBOX_IS_CONFIG_MOUNT_HOST_IMAGE(config)) { + GVirSandboxConfigMountHostImage *mimage = GVIR_SANDBOX_CONFIG_MOUNT_HOST_IMAGE(config); + GVirConfigDomainDiskFormat format = gvir_sandbox_config_mount_host_image_get_format(mimage); + GEnumClass *klass = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_FORMAT); + GEnumValue *value = g_enum_get_value(klass, format); + g_type_class_unref(klass); + g_key_file_set_string(file, key, "format", value->value_nick); + } g_key_file_set_string(file, key, "source", gvir_sandbox_config_mount_file_get_source( GVIR_SANDBOX_CONFIG_MOUNT_FILE(config))); diff --git a/libvirt-sandbox/libvirt-sandbox.sym b/libvirt-sandbox/libvirt-sandbox.sym index 7afef53..532fb63 100644 --- a/libvirt-sandbox/libvirt-sandbox.sym +++ b/libvirt-sandbox/libvirt-sandbox.sym @@ -209,3 +209,8 @@ LIBVIRT_SANDBOX_0.2.1 { local: *; }; + +LIBVIRT_SANDBOX_0.5.1 { + global: + gvir_sandbox_config_mount_guest_bind_get_format; +} LIBVIRT_SANDBOX_0.2.1; diff --git a/libvirt-sandbox/tests/test-config.c b/libvirt-sandbox/tests/test-config.c index 1afec83..dcbe5c1 100644 --- a/libvirt-sandbox/tests/test-config.c +++ b/libvirt-sandbox/tests/test-config.c @@ -54,6 +54,7 @@ int main(int argc, char **argv) const gchar *mounts[] = { "host-bind:/var/run/hell=/tmp/home", "host-image:/etc=/tmp/home", + "host-image:/etc=/tmp/home,format=qcow2", "host-bind:/tmp=", NULL }; -- 2.1.4
participants (1)
-
Cédric Bosdonnat