[libvirt] [sandbox PATCH 02/10] Add configuration object for disk support

Eren Yagdiran erenyagdiran at gmail.com
Thu Jun 25 11:27:22 UTC 2015


Add the config gobject, functions to store and load the new configuration
fragments and test. This will allow creating sandboxes with attached
disk with a parameter formatted like file:hda=/source/file.qcow2,format=qcow2
---
 libvirt-sandbox/Makefile.am                   |   2 +
 libvirt-sandbox/libvirt-sandbox-config-disk.c | 274 ++++++++++++++++++++++++
 libvirt-sandbox/libvirt-sandbox-config-disk.h |  82 +++++++
 libvirt-sandbox/libvirt-sandbox-config.c      | 293 ++++++++++++++++++++++++++
 libvirt-sandbox/libvirt-sandbox-config.h      |  10 +
 libvirt-sandbox/libvirt-sandbox.h             |   1 +
 libvirt-sandbox/libvirt-sandbox.sym           |   4 +
 libvirt-sandbox/tests/test-config.c           |  11 +
 8 files changed, 677 insertions(+)
 create mode 100644 libvirt-sandbox/libvirt-sandbox-config-disk.c
 create mode 100644 libvirt-sandbox/libvirt-sandbox-config-disk.h

diff --git a/libvirt-sandbox/Makefile.am b/libvirt-sandbox/Makefile.am
index 6917f04..8237c50 100644
--- a/libvirt-sandbox/Makefile.am
+++ b/libvirt-sandbox/Makefile.am
@@ -55,6 +55,7 @@ SANDBOX_HEADER_FILES = \
 			libvirt-sandbox-main.h \
 			libvirt-sandbox-util.h \
 			libvirt-sandbox-config.h \
+			libvirt-sandbox-config-disk.h \
 			libvirt-sandbox-config-network.h \
 			libvirt-sandbox-config-network-address.h \
 			libvirt-sandbox-config-network-filterref-parameter.h \
@@ -86,6 +87,7 @@ SANDBOX_SOURCE_FILES = \
 			libvirt-sandbox-main.c \
 			libvirt-sandbox-util.c \
 			libvirt-sandbox-config.c \
+			libvirt-sandbox-config-disk.c \
 			libvirt-sandbox-config-network.c \
 			libvirt-sandbox-config-network-address.c \
 			libvirt-sandbox-config-network-filterref.c \
diff --git a/libvirt-sandbox/libvirt-sandbox-config-disk.c b/libvirt-sandbox/libvirt-sandbox-config-disk.c
new file mode 100644
index 0000000..04f1cf0
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-disk.c
@@ -0,0 +1,274 @@
+/*
+ * libvirt-sandbox-config-disk.c: libvirt sandbox configuration
+ *
+ * Copyright (C) 2015 Universitat Politècnica de Catalunya.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Eren Yagdiran <erenyagdiran at gmail.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "libvirt-sandbox/libvirt-sandbox.h"
+
+/**
+ * SECTION: libvirt-sandbox-config-disk
+ * @short_description: Disk attachment configuration details
+ * @include: libvirt-sandbox/libvirt-sandbox.h
+ * @see_aloso: #GVirSandboxConfig
+ *
+ * Provides an object to store information about a disk attachment in the sandbox
+ *
+ */
+
+#define GVIR_SANDBOX_CONFIG_DISK_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_SANDBOX_TYPE_CONFIG_DISK, GVirSandboxConfigDiskPrivate))
+
+
+struct _GVirSandboxConfigDiskPrivate
+{
+    GVirConfigDomainDiskType type;
+    gchar *target;
+    gchar *source;
+    GVirConfigDomainDiskFormat format;
+};
+
+G_DEFINE_TYPE(GVirSandboxConfigDisk, gvir_sandbox_config_disk, G_TYPE_OBJECT);
+
+
+enum {
+    PROP_0,
+    PROP_TYPE,
+    PROP_TARGET,
+    PROP_SOURCE,
+    PROP_FORMAT
+};
+
+enum {
+    LAST_SIGNAL
+};
+
+
+
+static void gvir_sandbox_config_disk_get_property(GObject *object,
+                                                  guint prop_id,
+                                                  GValue *value,
+                                                  GParamSpec *pspec)
+{
+    GVirSandboxConfigDisk *config = GVIR_SANDBOX_CONFIG_DISK(object);
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        g_value_set_string(value, priv->target);
+        break;
+    case PROP_SOURCE:
+        g_value_set_string(value, priv->source);
+        break;
+    case PROP_TYPE:
+        g_value_set_enum(value, priv->type);
+        break;
+    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_disk_set_property(GObject *object,
+                                                  guint prop_id,
+                                                  const GValue *value,
+                                                  GParamSpec *pspec)
+{
+    GVirSandboxConfigDisk *config = GVIR_SANDBOX_CONFIG_DISK(object);
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        g_free(priv->target);
+        priv->target = g_value_dup_string(value);
+        break;
+    case PROP_SOURCE:
+        g_free(priv->source);
+        priv->source = g_value_dup_string(value);
+        break;
+    case PROP_TYPE:
+        priv->type = g_value_get_enum(value);
+        break;
+    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_disk_finalize(GObject *object)
+{
+    GVirSandboxConfigDisk *config = GVIR_SANDBOX_CONFIG_DISK(object);
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+
+    g_free(priv->target);
+    g_free(priv->source);
+
+    G_OBJECT_CLASS(gvir_sandbox_config_disk_parent_class)->finalize(object);
+}
+
+
+static void gvir_sandbox_config_disk_class_init(GVirSandboxConfigDiskClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->finalize = gvir_sandbox_config_disk_finalize;
+    object_class->get_property = gvir_sandbox_config_disk_get_property;
+    object_class->set_property = gvir_sandbox_config_disk_set_property;
+
+    g_object_class_install_property(object_class,
+                                    PROP_TARGET,
+                                    g_param_spec_string("target",
+                                                        "Target",
+                                                        "The sandbox target directory",
+                                                        NULL,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_NICK |
+                                                        G_PARAM_STATIC_BLURB));
+
+    g_object_class_install_property(object_class,
+                                    PROP_SOURCE,
+                                    g_param_spec_string("source",
+                                                        "Source",
+                                                        "The sandbox source directory",
+                                                        NULL,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_NICK |
+                                                        G_PARAM_STATIC_BLURB));
+
+
+    g_object_class_install_property(object_class,
+                                    PROP_TYPE,
+                                    g_param_spec_enum("type",
+                                                      "Disk type",
+                                                      "The sandbox disk type",
+                                                      GVIR_CONFIG_TYPE_DOMAIN_DISK_TYPE,
+                                                      GVIR_CONFIG_DOMAIN_DISK_FILE,
+                                                      G_PARAM_READABLE |
+                                                      G_PARAM_WRITABLE |
+                                                      G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_STATIC_NAME |
+                                                      G_PARAM_STATIC_NICK |
+                                                      G_PARAM_STATIC_BLURB));
+
+    g_object_class_install_property(object_class,
+                                    PROP_FORMAT,
+                                    g_param_spec_enum("format",
+                                                      "Disk format",
+                                                      "The sandbox 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(GVirSandboxConfigDiskPrivate));
+}
+
+
+static void gvir_sandbox_config_disk_init(GVirSandboxConfigDisk *config)
+{
+    config->priv = GVIR_SANDBOX_CONFIG_DISK_GET_PRIVATE(config);
+}
+
+/**
+ * gvir_sandbox_config_disk_get_disk_type:
+ * @config: (transfer none): the sandbox disk config
+ *
+ * Retrieves the type property for the custom disk
+ *
+ * Returns: (transfer none): the type property of disk
+ */
+GVirConfigDomainDiskType gvir_sandbox_config_disk_get_disk_type(GVirSandboxConfigDisk *config)
+{
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+    return priv->type;
+}
+
+
+/**
+ * gvir_sandbox_config_disk_get_format:
+ * @config: (transfer none): the sandbox disk config
+ *
+ * Retrieves the format property for the custom disk
+ *
+ * Returns: (transfer none): the format property of disk
+ */
+GVirConfigDomainDiskFormat gvir_sandbox_config_disk_get_format(GVirSandboxConfigDisk *config)
+{
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+    return priv->format;
+}
+
+
+/**
+ * gvir_sandbox_config_disk_get_target:
+ * @config: (transfer none): the sandbox disk config
+ *
+ * Retrieves the target property for the custom disk
+ *
+ * Returns: (transfer none): the target property path
+ */
+const gchar *gvir_sandbox_config_disk_get_target(GVirSandboxConfigDisk *config)
+{
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+    return priv->target;
+}
+
+
+/**
+ * gvir_sandbox_config_disk_get_source:
+ * @config: (transfer none): the sandbox disk config
+ *
+ * Retrieves the source property for the custom disk
+ *
+ * Returns: (transfer none): the source property
+ */
+const gchar *gvir_sandbox_config_disk_get_source(GVirSandboxConfigDisk *config)
+{
+    GVirSandboxConfigDiskPrivate *priv = config->priv;
+    return priv->source;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  indent-tabs-mode: nil
+ *  tab-width: 8
+ * End:
+ */
+
diff --git a/libvirt-sandbox/libvirt-sandbox-config-disk.h b/libvirt-sandbox/libvirt-sandbox-config-disk.h
new file mode 100644
index 0000000..f3667b5
--- /dev/null
+++ b/libvirt-sandbox/libvirt-sandbox-config-disk.h
@@ -0,0 +1,82 @@
+/*
+ * libvirt-sandbox-config-diskaccess.h: libvirt sandbox configuration
+ *
+ * Copyright (C) 2015 Universitat Politècnica de Catalunya.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Eren Yagdiran <erenyagdiran at gmail.com>
+ */
+
+#if !defined(__LIBVIRT_SANDBOX_H__) && !defined(LIBVIRT_SANDBOX_BUILD)
+#error "Only <libvirt-sandbox/libvirt-sandbox.h> can be included directly."
+#endif
+
+#ifndef __LIBVIRT_SANDBOX_CONFIG_DISK_H__
+#define __LIBVIRT_SANDBOX_CONFIG_DISK_H__
+
+G_BEGIN_DECLS
+
+#define GVIR_SANDBOX_TYPE_CONFIG_DISK            (gvir_sandbox_config_disk_get_type ())
+#define GVIR_SANDBOX_CONFIG_DISK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_SANDBOX_TYPE_CONFIG_DISK, GVirSandboxConfigDisk))
+#define GVIR_SANDBOX_CONFIG_DISK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_SANDBOX_TYPE_CONFIG_DISK, GVirSandboxConfigDiskClass))
+#define GVIR_SANDBOX_IS_CONFIG_DISK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_SANDBOX_TYPE_CONFIG_DISK))
+#define GVIR_SANDBOX_IS_CONFIG_DISK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_SANDBOX_TYPE_CONFIG_DISK))
+#define GVIR_SANDBOX_CONFIG_DISK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_SANDBOX_TYPE_CONFIG_DISK, GVirSandboxConfigDiskClass))
+
+#define GVIR_SANDBOX_TYPE_CONFIG_DISK_HANDLE      (gvir_sandbox_config_disk_handle_get_type ())
+
+typedef struct _GVirSandboxConfigDisk GVirSandboxConfigDisk;
+typedef struct _GVirSandboxConfigDiskPrivate GVirSandboxConfigDiskPrivate;
+typedef struct _GVirSandboxConfigDiskClass GVirSandboxConfigDiskClass;
+
+struct _GVirSandboxConfigDisk
+{
+    GObject parent;
+
+    GVirSandboxConfigDiskPrivate *priv;
+
+    /* Do not add fields to this struct */
+};
+
+struct _GVirSandboxConfigDiskClass
+{
+    GObjectClass parent_class;
+
+    gpointer padding[LIBVIRT_SANDBOX_CLASS_PADDING];
+};
+
+GType gvir_sandbox_config_disk_get_type(void);
+
+const gchar *gvir_sandbox_config_disk_get_target(GVirSandboxConfigDisk *config);
+
+const gchar *gvir_sandbox_config_disk_get_source(GVirSandboxConfigDisk *config);
+
+GVirConfigDomainDiskType gvir_sandbox_config_disk_get_disk_type(GVirSandboxConfigDisk *config);
+
+GVirConfigDomainDiskFormat gvir_sandbox_config_disk_get_format(GVirSandboxConfigDisk *config);
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_SANDBOX_CONFIG_DISK_H__ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  indent-tabs-mode: nil
+ *  tab-width: 8
+ * End:
+ */
diff --git a/libvirt-sandbox/libvirt-sandbox-config.c b/libvirt-sandbox/libvirt-sandbox-config.c
index fbc65a6..3342706 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -27,6 +27,7 @@
 #include <glib/gi18n.h>
 
 #include "libvirt-sandbox/libvirt-sandbox.h"
+#include "libvirt-sandbox/libvirt-sandbox-util.h"
 #include <errno.h>
 #include <selinux/selinux.h>
 
@@ -62,6 +63,7 @@ struct _GVirSandboxConfigPrivate
 
     GList *networks;
     GList *mounts;
+    GList *disks;
 
     gchar *secLabel;
     gboolean secDynamic;
@@ -274,6 +276,9 @@ static void gvir_sandbox_config_finalize(GObject *object)
     g_list_foreach(priv->networks, (GFunc)g_object_unref, NULL);
     g_list_free(priv->networks);
 
+    g_list_foreach(priv->disks, (GFunc)g_object_unref, NULL);
+    g_list_free(priv->disks);
+
 
     g_free(priv->name);
     g_free(priv->uuid);
@@ -1141,6 +1146,166 @@ gboolean gvir_sandbox_config_has_networks(GVirSandboxConfig *config)
 
 
 /**
+ * gvir_sandbox_config_add_disk:
+ * @config: (transfer none): the sandbox config
+ * @dsk: (transfer none): the disk configuration
+ *
+ * Adds a new custom disk to the sandbox
+ *
+ */
+void gvir_sandbox_config_add_disk(GVirSandboxConfig *config,
+                                   GVirSandboxConfigDisk *dsk)
+{
+    GVirSandboxConfigPrivate *priv = config->priv;
+
+    g_object_ref(dsk);
+
+    priv->disks = g_list_append(priv->disks, dsk);
+}
+
+
+/**
+ * gvir_sandbox_config_get_disks:
+ * @config: (transfer none): the sandbox config
+ *
+ * Retrieves the list of custom disks in the sandbox
+ *
+ * Returns: (transfer full) (element-type GVirSandboxConfigMount): the list of disks
+ */
+GList *gvir_sandbox_config_get_disks(GVirSandboxConfig *config)
+{
+    GVirSandboxConfigPrivate *priv = config->priv;
+    g_list_foreach(priv->disks, (GFunc)g_object_ref, NULL);
+    return g_list_copy(priv->disks);
+}
+
+
+/**
+ * gvir_sandbox_config_add_disk_strv:
+ * @config: (transfer none): the sandbox config
+ * @disks: (transfer none)(array zero-terminated=1): the list of disks
+ *
+ * Parses @disks whose elements are in the format TYPE:TARGET=SOURCE,FORMAT=FORMAT
+ * creating #GVirSandboxConfigMount instances for each element. For
+ * example
+ *
+ * - file:hda=/var/lib/sandbox/demo/tmp.qcow2,format=qcow2
+ */
+gboolean gvir_sandbox_config_add_disk_strv(GVirSandboxConfig *config,
+                                           gchar **disks,
+                                           GError **error)
+{
+    gsize i = 0;
+    while (disks && disks[i]) {
+        if (!gvir_sandbox_config_add_disk_opts(config,
+                                               disks[i],
+                                               error))
+            return FALSE;
+        i++;
+    }
+    return TRUE;
+}
+
+
+/**
+ * gvir_sandbox_config_add_disk_opts:
+ * @config: (transfer none): the sandbox config
+ * @disk: (transfer none): the disk config
+ *
+ * Parses @disk in the format TYPE:TARGET=SOURCE,FORMAT=FORMAT
+ * creating #GVirSandboxConfigDisk instances for each element. For
+ * example
+ *
+ * - file:hda=/var/lib/sandbox/demo/tmp.qcow2,format=qcow2
+ */
+
+gboolean gvir_sandbox_config_add_disk_opts(GVirSandboxConfig *config,
+                                           const char *opt,
+                                           GError **error)
+{
+    gchar *typeStr = NULL;
+    gchar *formatStr = NULL;
+    gchar *target = NULL;
+    gchar *source = NULL;
+    GVirSandboxConfigDisk *diskConfig;
+    gchar *tmp;
+    gint type;
+    gint format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW;
+    GEnumClass *enum_class = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_TYPE);
+    GEnumValue *enum_value;
+
+    if (!(typeStr = g_strdup(opt)))
+        return FALSE;
+
+    tmp = strchr(typeStr, ':');
+
+    if (!tmp) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("No disk type prefix on %s"), opt);
+       	return FALSE;
+    }
+
+    *tmp = '\0';
+    target = tmp + 1;
+    if (!(enum_value = g_enum_get_value_by_nick(enum_class, typeStr))) {
+        g_type_class_unref(enum_class);
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("Unknown disk type prefix on %s"), opt);
+        return FALSE;
+    }
+    g_type_class_unref(enum_class);
+    type = enum_value->value;
+
+    if (type != GVIR_CONFIG_DOMAIN_DISK_FILE) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("Unimplemented disk type prefix on %s"), opt);
+        return FALSE;
+    }
+
+    if (!(tmp = strchr(target, '='))) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("Missing disk source string on %s"), opt);
+        return FALSE;
+    }
+
+    *tmp = '\0';
+    source = tmp + 1;
+
+    if ((tmp = strchr(source, ',')) != NULL) {
+        *tmp = '\0';
+        formatStr = tmp + 1;
+
+        if ((strncmp(formatStr, "format=", 7) != 0) ||
+                (format = gvir_sandbox_util_disk_format_from_str(formatStr + 7, error)) < 0){
+                g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                            _("Unknown disk image format: '%s'"), formatStr + 7);
+                return FALSE;
+        }
+    }
+    else {
+        if ((format = gvir_sandbox_util_guess_image_format(source, error)) < 0) {
+           format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW;
+        }
+    }
+
+
+    diskConfig = GVIR_SANDBOX_CONFIG_DISK(g_object_new(GVIR_SANDBOX_TYPE_CONFIG_DISK,
+                                                "type", type,
+                                                "target", target,
+                                                "source", source,
+                                                "format", format,
+                                                NULL));
+
+    gvir_sandbox_config_add_disk(config, diskConfig);
+
+    g_object_unref(diskConfig);
+    g_free(typeStr);
+
+    return TRUE;
+}
+
+
+/**
  * gvir_sandbox_config_add_mount:
  * @config: (transfer none): the sandbox config
  * @mnt: (transfer none): the mount configuration
@@ -1757,6 +1922,85 @@ static GVirSandboxConfigMount *gvir_sandbox_config_load_config_mount(GKeyFile *f
 }
 
 
+static GVirSandboxConfigDisk *gvir_sandbox_config_load_config_disk(GKeyFile *file,
+                                                                   guint i,
+                                                                   GError **error)
+{
+    GVirSandboxConfigDisk *config = NULL;
+    gchar *key = NULL;
+    gchar *target = NULL;
+    gchar *source = NULL;
+    gchar *typeStr = NULL;
+    gchar *formatStr = NULL;
+    gint type, format;
+    GError *e = NULL;
+    GEnumClass *enum_class = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_TYPE);
+    GEnumValue *enum_value;
+
+    key = g_strdup_printf("disk.%u", i);
+    if ((target = g_key_file_get_string(file, key, "target", &e)) == NULL) {
+        if (e->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND) {
+            g_error_free(e);
+            return NULL;
+        }
+        g_error_free(e);
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    "%s", _("Missing disk target in config file"));
+        goto cleanup;
+    }
+    if ((source = g_key_file_get_string(file, key, "source", NULL)) == NULL) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    "%s", _("Missing disk source in config file"));
+        goto cleanup;
+    }
+    if ((typeStr = g_key_file_get_string(file, key, "type", NULL)) == NULL) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    "%s", _("Missing disk type in config file"));
+        goto cleanup;
+    }
+
+    if (!(enum_value = g_enum_get_value_by_nick(enum_class, typeStr))) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("Unknown disk type %s in config file"), typeStr);
+        goto error;
+    }
+    type = enum_value->value;
+
+    if ((formatStr = g_key_file_get_string(file, key, "format", NULL)) == NULL) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    "%s", _("Missing disk format in config file"));
+        goto cleanup;
+    }
+
+    if ((format = gvir_sandbox_util_disk_format_from_str(formatStr, error)) < 0) {
+        g_set_error(error, GVIR_SANDBOX_CONFIG_ERROR, 0,
+                    _("Unknown disk format %s in config file"), formatStr);
+        goto error;
+    }
+
+    config = GVIR_SANDBOX_CONFIG_DISK(g_object_new(GVIR_SANDBOX_TYPE_CONFIG_DISK,
+                                                   "type", type,
+                                                   "target", target,
+                                                   "source", source,
+                                                   "format", format,
+                                                   NULL));
+
+ cleanup:
+    g_type_class_unref(enum_class);
+    g_free(target);
+    g_free(source);
+    g_free(typeStr);
+    g_free(formatStr);
+    g_free(key);
+    return config;
+
+ error:
+    g_object_unref(config);
+    config = NULL;
+    goto cleanup;
+}
+
+
 static GVirSandboxConfigNetwork *gvir_sandbox_config_load_config_network(GKeyFile *file,
                                                                          guint i,
                                                                          GError **error)
@@ -1973,6 +2217,16 @@ static gboolean gvir_sandbox_config_load_config(GVirSandboxConfig *config,
     }
 
 
+    for (i = 0 ; i < 1024 ; i++) {
+        GVirSandboxConfigDisk *disk;
+        if (!(disk = gvir_sandbox_config_load_config_disk(file, i, error)) &&
+            *error)
+            goto cleanup;
+        if (disk)
+            priv->disks = g_list_append(priv->disks, disk);
+    }
+
+
     g_free(priv->secLabel);
     if ((str = g_key_file_get_string(file, "security", "label", NULL)) != NULL)
         priv->secLabel = str;
@@ -1993,6 +2247,35 @@ static gboolean gvir_sandbox_config_load_config(GVirSandboxConfig *config,
 }
 
 
+static void gvir_sandbox_config_save_config_disk(GVirSandboxConfigDisk *config,
+                                                 GKeyFile *file,
+                                                 guint i)
+{
+    gchar *key;
+    GVirConfigDomainDiskType type = gvir_sandbox_config_disk_get_disk_type(config);
+    GVirConfigDomainDiskFormat format = gvir_sandbox_config_disk_get_format(config);
+    GEnumClass *klass = NULL;
+    GEnumValue *value = NULL;
+
+    key = g_strdup_printf("disk.%u", i);
+
+    klass = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_TYPE);
+    value = g_enum_get_value(klass, type);
+    g_type_class_unref(klass);
+    g_key_file_set_string(file, key, "type", value->value_nick);
+
+    g_key_file_set_string(file, key, "source",
+                          gvir_sandbox_config_disk_get_source(config));
+    g_key_file_set_string(file, key, "target",
+                          gvir_sandbox_config_disk_get_target(config));
+
+    klass = g_type_class_ref(GVIR_CONFIG_TYPE_DOMAIN_DISK_FORMAT);
+    value = g_enum_get_value(klass, format);
+    g_type_class_unref(klass);
+    g_key_file_set_string(file, key, "format", value->value_nick);
+    g_free(key);
+}
+
 static void gvir_sandbox_config_save_config_mount(GVirSandboxConfigMount *config,
                                                   GKeyFile *file,
                                                   guint i)
@@ -2174,6 +2457,16 @@ static void gvir_sandbox_config_save_config(GVirSandboxConfig *config,
     }
 
     i = 0;
+    tmp = priv->disks;
+    while (tmp) {
+        gvir_sandbox_config_save_config_disk(tmp->data,
+                                             file,
+                                             i);
+        tmp = tmp->next;
+        i++;
+    }
+
+    i = 0;
     tmp = priv->networks;
     while (tmp) {
         gvir_sandbox_config_save_config_network(GVIR_SANDBOX_CONFIG_NETWORK(tmp->data),
diff --git a/libvirt-sandbox/libvirt-sandbox-config.h b/libvirt-sandbox/libvirt-sandbox-config.h
index 1a65e3d..deaea68 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.h
+++ b/libvirt-sandbox/libvirt-sandbox-config.h
@@ -122,6 +122,16 @@ gboolean gvir_sandbox_config_add_network_strv(GVirSandboxConfig *config,
                                               GError **error);
 gboolean gvir_sandbox_config_has_networks(GVirSandboxConfig *config);
 
+void gvir_sandbox_config_add_disk(GVirSandboxConfig *config,
+                                  GVirSandboxConfigDisk *dsk);
+GList *gvir_sandbox_config_get_disks(GVirSandboxConfig *config);
+gboolean gvir_sandbox_config_add_disk_strv(GVirSandboxConfig *config,
+                                           gchar **disks,
+                                           GError **error);
+gboolean gvir_sandbox_config_add_disk_opts(GVirSandboxConfig *config,
+                                           const char *disk,
+                                           GError **error);
+
 void gvir_sandbox_config_add_mount(GVirSandboxConfig *config,
                                    GVirSandboxConfigMount *mnt);
 GList *gvir_sandbox_config_get_mounts(GVirSandboxConfig *config);
diff --git a/libvirt-sandbox/libvirt-sandbox.h b/libvirt-sandbox/libvirt-sandbox.h
index adb21a1..20dc871 100644
--- a/libvirt-sandbox/libvirt-sandbox.h
+++ b/libvirt-sandbox/libvirt-sandbox.h
@@ -31,6 +31,7 @@
 #include <libvirt-sandbox/libvirt-sandbox-main.h>
 #include <libvirt-sandbox/libvirt-sandbox-util.h>
 #include <libvirt-sandbox/libvirt-sandbox-enum-types.h>
+#include <libvirt-sandbox/libvirt-sandbox-config-disk.h>
 #include <libvirt-sandbox/libvirt-sandbox-config-mount.h>
 #include <libvirt-sandbox/libvirt-sandbox-config-mount-file.h>
 #include <libvirt-sandbox/libvirt-sandbox-config-mount-host-bind.h>
diff --git a/libvirt-sandbox/libvirt-sandbox.sym b/libvirt-sandbox/libvirt-sandbox.sym
index a17dfed..bb717ed 100644
--- a/libvirt-sandbox/libvirt-sandbox.sym
+++ b/libvirt-sandbox/libvirt-sandbox.sym
@@ -213,4 +213,8 @@ LIBVIRT_SANDBOX_0.2.1 {
 LIBVIRT_SANDBOX_0.5.2 {
    global:
 	gvir_sandbox_config_mount_guest_bind_get_format;
+	gvir_sandbox_config_add_disk;
+	gvir_sandbox_config_add_disk_strv;
+	gvir_sandbox_config_add_disk_opts;
+	gvir_sandbox_config_disk_get_type;
 } LIBVIRT_SANDBOX_0.2.1;
diff --git a/libvirt-sandbox/tests/test-config.c b/libvirt-sandbox/tests/test-config.c
index dcbe5c1..3ea2017 100644
--- a/libvirt-sandbox/tests/test-config.c
+++ b/libvirt-sandbox/tests/test-config.c
@@ -58,6 +58,14 @@ int main(int argc, char **argv)
         "host-bind:/tmp=",
         NULL
     };
+    const gchar *disks[] = {
+        "file:hda=/tmp/img.blah,format=qcow2",
+        "file:hda=/tmp/img.qcow2",
+        "file:hda=/tmp/img.qcow2,format=raw",
+        "file:hda=/tmp/img.img",
+        "file:hda=/tmp/imq",
+        NULL
+    };
     const gchar *includes[] = {
         "/etc/nswitch.conf",
         "/etc/resolve.conf",
@@ -96,6 +104,9 @@ int main(int argc, char **argv)
     if (!gvir_sandbox_config_add_mount_strv(cfg1, (gchar**)mounts, &err))
         goto cleanup;
 
+    if (!gvir_sandbox_config_add_disk_strv(cfg1, (gchar**)disks, &err))
+        goto cleanup;
+
     if (!gvir_sandbox_config_add_host_include_strv(cfg1, (gchar**)includes, &err))
         goto cleanup;
 
-- 
2.1.0




More information about the libvir-list mailing list