[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [libvirt-designer][PATCH v2 2/4] domain: Introduce disk support



Let users add either files or devices as disks to domains.
---
 libvirt-designer/libvirt-designer-domain.c |  259 ++++++++++++++++++++++++++++
 libvirt-designer/libvirt-designer-domain.h |    7 +
 libvirt-designer/libvirt-designer.sym      |    3 +
 3 files changed, 269 insertions(+), 0 deletions(-)

diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c
index a8cabde..8e649d7 100644
--- a/libvirt-designer/libvirt-designer-domain.c
+++ b/libvirt-designer/libvirt-designer-domain.c
@@ -37,6 +37,12 @@ struct _GVirDesignerDomainPrivate
     GVirConfigCapabilities *caps;
     OsinfoOs *os;
     OsinfoPlatform *platform;
+
+    OsinfoDeployment *deployment;
+    /* next disk targets */
+    unsigned int ide;
+    unsigned int virtio;
+    unsigned int sata;
 };
 
 G_DEFINE_TYPE(GVirDesignerDomain, gvir_designer_domain, G_TYPE_OBJECT);
@@ -134,6 +140,8 @@ static void gvir_designer_domain_finalize(GObject *object)
     g_object_unref(priv->os);
     g_object_unref(priv->platform);
     g_object_unref(priv->caps);
+    if (priv->deployment)
+        g_object_unref(priv->deployment);
 
     G_OBJECT_CLASS(gvir_designer_domain_parent_class)->finalize(object);
 }
@@ -663,3 +671,254 @@ cleanup:
         g_object_unref(guest);
     return ret;
 }
+
+static GList *
+gvir_designer_domain_get_supported_disk_bus_types(GVirDesignerDomain *design)
+{
+    GVirDesignerDomainPrivate *priv = design->priv;
+    OsinfoDeviceList *dev_list;
+    GHashTable *bus_hash = g_hash_table_new(g_str_hash, g_str_equal);
+    GList *ret = NULL;
+    int i;
+
+    dev_list = osinfo_os_get_devices_by_property(priv->os, "class", "block", TRUE);
+    if (!dev_list)
+        goto cleanup;
+
+    for (i = 0; i < osinfo_list_get_length(OSINFO_LIST(dev_list)); i++) {
+        OsinfoDevice *dev = OSINFO_DEVICE(osinfo_list_get_nth(OSINFO_LIST(dev_list), i));
+        const gchar *bus = osinfo_device_get_bus_type(dev);
+
+        if (bus)
+            g_hash_table_add(bus_hash, g_strdup(bus));
+    }
+
+    ret = g_hash_table_get_keys(bus_hash);
+    if (ret)
+        ret = g_list_copy(ret);
+
+cleanup:
+    g_hash_table_destroy(bus_hash);
+    return ret;
+}
+
+static OsinfoDeviceLink *
+gvir_designer_domain_get_preferred_device(GVirDesignerDomain *design,
+                                          const char *class,
+                                          GError **error)
+{
+    GVirDesignerDomainPrivate *priv = design->priv;
+    OsinfoFilter *filter = osinfo_filter_new();
+    OsinfoDeviceLinkFilter *filter_link = NULL;
+    OsinfoDeployment *deployment = priv->deployment;
+    OsinfoDeviceLink *dev_link = NULL;
+
+    if (!deployment) {
+        priv->deployment = deployment = osinfo_db_find_deployment(osinfo_db,
+                                                                  priv->os,
+                                                                  priv->platform);
+        if (!deployment) {
+            g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+                        "Unable to find any deployment in libosinfo database");
+            goto cleanup;
+        }
+    }
+
+    osinfo_filter_add_constraint(filter, "class", class);
+    filter_link = osinfo_devicelinkfilter_new(filter);
+    dev_link = osinfo_deployment_get_preferred_device_link(deployment, OSINFO_FILTER(filter_link));
+
+cleanup:
+    if (filter_link)
+        g_object_unref(filter_link);
+    if (filter)
+        g_object_unref(filter);
+    return dev_link;
+}
+
+static const gchar *
+gvir_designer_domain_get_preferred_disk_bus_type(GVirDesignerDomain *design,
+                                                 GError **error)
+{
+    OsinfoDevice *dev;
+    OsinfoDeviceLink *dev_link = gvir_designer_domain_get_preferred_device(design,
+                                                                           "block",
+                                                                           error);
+    const gchar *ret = NULL;
+
+    if (!dev_link)
+        return NULL;
+
+    dev = osinfo_devicelink_get_target(dev_link);
+    if (dev)
+        ret = osinfo_device_get_bus_type(dev);
+
+    return ret;
+}
+
+static gchar *
+gvir_designer_domain_next_disk_target(GVirDesignerDomain *design,
+                                      GVirConfigDomainDiskBus bus)
+{
+    gchar *ret = NULL;
+    GVirDesignerDomainPrivate *priv = design->priv;
+
+    switch (bus) {
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_IDE:
+        ret = g_strdup_printf("hd%c", 'a' + priv->ide++);
+        break;
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_VIRTIO:
+        ret = g_strdup_printf("vd%c", 'a' + priv->virtio++);
+        break;
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_SATA:
+        ret = g_strdup_printf("sd%c", 'a' + priv->sata++);
+        break;
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_FDC:
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_SCSI:
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_XEN:
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_USB:
+    case GVIR_CONFIG_DOMAIN_DISK_BUS_UML:
+    default:
+        /* not supported yet */
+        /* XXX should we fallback to ide/virtio? */
+        break;
+    }
+
+    return ret;
+}
+
+static GVirConfigDomainDisk *
+gvir_designer_domain_add_disk_full(GVirDesignerDomain *design,
+                                   GVirConfigDomainDiskType type,
+                                   const char *path,
+                                   const char *format,
+                                   gchar *target,
+                                   GError **error)
+{
+    GVirDesignerDomainPrivate *priv = design->priv;
+    GVirConfigDomainDisk *disk = NULL;
+    GVirConfigDomainDiskBus bus;
+    gchar *target_gen = NULL;
+    const gchar *bus_str = NULL;
+    GList *bus_str_list = NULL, *item = NULL;
+
+    /* Guess preferred disk bus */
+    bus_str = gvir_designer_domain_get_preferred_disk_bus_type(design, error);
+    if (!bus_str) {
+        /* And fallback if fails */
+        bus_str_list = gvir_designer_domain_get_supported_disk_bus_types(design);
+        if (!bus_str_list) {
+            if (!*error)
+                g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+                            "Unable to find any disk bus type");
+            goto error;
+        }
+
+        item = g_list_first(bus_str_list);
+        bus_str = item->data;
+        if (!bus_str)
+            goto error;
+    }
+
+    g_clear_error(error);
+
+    disk = gvir_config_domain_disk_new();
+    gvir_config_domain_disk_set_type(disk, type);
+    gvir_config_domain_disk_set_source(disk, path);
+    gvir_config_domain_disk_set_driver_name(disk, "qemu");
+    if (format)
+        gvir_config_domain_disk_set_driver_type(disk, format);
+    if (g_str_equal(bus_str, "ide")) {
+        bus = GVIR_CONFIG_DOMAIN_DISK_BUS_IDE;
+    } else if (g_str_equal(bus_str, "virtio") ||
+               g_str_equal(bus_str, "pci")) {
+        bus = GVIR_CONFIG_DOMAIN_DISK_BUS_VIRTIO;
+    } else if (g_str_equal(bus_str, "sata")) {
+        bus = GVIR_CONFIG_DOMAIN_DISK_BUS_SATA;
+    } else {
+        g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+                    "unsupported disk bus type '%s'", bus_str);
+        goto error;
+    }
+
+    gvir_config_domain_disk_set_target_bus(disk, bus);
+
+    if (!target) {
+        target = target_gen = gvir_designer_domain_next_disk_target(design, bus);
+        if (!target_gen) {
+            g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+                        "unable to generate target name for bus '%s'", bus_str);
+            goto error;
+        }
+    }
+    gvir_config_domain_disk_set_target_dev(disk, target);
+
+    g_list_free(bus_str_list);
+    g_free(target_gen);
+
+    gvir_config_domain_add_device(priv->config, GVIR_CONFIG_DOMAIN_DEVICE(disk));
+
+    return disk;
+
+error:
+    g_free(target_gen);
+    g_list_free(bus_str_list);
+    if (disk)
+        g_object_unref(disk);
+    return NULL;
+}
+/**
+ * gvir_designer_domain_add_disk_file:
+ * @design: (transfer none): the domain designer instance
+ * @filepath: (transfer none): the path to a file
+ * @format: (transfer none): disk format
+ *
+ * Add a new disk to the domain.
+ *
+ * Returns: (transfer none): the pointer to new disk.
+ * If something fails NULL is returned and @error is set.
+ */
+GVirConfigDomainDisk *gvir_designer_domain_add_disk_file(GVirDesignerDomain *design,
+                                                         const char *filepath,
+                                                         const char *format,
+                                                         GError **error)
+{
+    g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+    GVirConfigDomainDisk *ret = NULL;
+
+    ret = gvir_designer_domain_add_disk_full(design,
+                                             GVIR_CONFIG_DOMAIN_DISK_FILE,
+                                             filepath,
+                                             format,
+                                             NULL,
+                                             error);
+    return ret;
+}
+
+/**
+ * gvir_designer_domain_add_disk_device:
+ * @design: (transfer none): the domain designer instance
+ * @devpath: (transfer none): path to the device
+ *
+ * Add given device as a new disk to the domain designer instance.
+ *
+ * Returns: (transfer none): the pointer to the new disk.
+ * If something fails NULL is returned and @error is set.
+ */
+GVirConfigDomainDisk *gvir_designer_domain_add_disk_device(GVirDesignerDomain *design,
+                                                           const char *devpath,
+                                                           GError **error)
+{
+    g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+    GVirConfigDomainDisk *ret = NULL;
+
+    ret = gvir_designer_domain_add_disk_full(design,
+                                             GVIR_CONFIG_DOMAIN_DISK_BLOCK,
+                                             devpath,
+                                             "raw",
+                                             NULL,
+                                             error);
+    return ret;
+}
diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h
index 23b5750..06a5749 100644
--- a/libvirt-designer/libvirt-designer-domain.h
+++ b/libvirt-designer/libvirt-designer-domain.h
@@ -93,6 +93,13 @@ gboolean gvir_designer_domain_setup_container_full(GVirDesignerDomain *design,
                                                    const char *arch,
                                                    GError **error);
 
+GVirConfigDomainDisk *gvir_designer_domain_add_disk_file(GVirDesignerDomain *design,
+                                                         const char *filepath,
+                                                         const char *format,
+                                                         GError **error);
+GVirConfigDomainDisk *gvir_designer_domain_add_disk_device(GVirDesignerDomain *design,
+                                                           const char *devpath,
+                                                           GError **error);
 
 G_END_DECLS
 
diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym
index 2a56a92..e67323a 100644
--- a/libvirt-designer/libvirt-designer.sym
+++ b/libvirt-designer/libvirt-designer.sym
@@ -10,6 +10,9 @@ LIBVIRT_DESIGNER_0.0.1 {
 	gvir_designer_domain_get_platform;
 	gvir_designer_domain_get_capabilities;
 
+	gvir_designer_domain_add_disk_file;
+	gvir_designer_domain_add_disk_device;
+
 	gvir_designer_domain_setup_machine;
 	gvir_designer_domain_setup_machine_full;
 	gvir_designer_domain_setup_container;
-- 
1.7.8.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]