[libvirt] [libvirt-glib 2/2] API for storage pool volume management

Zeeshan Ali (Khattak) zeeshanak at gnome.org
Wed Sep 28 18:30:48 UTC 2011


From: "Zeeshan Ali (Khattak)" <zeeshanak at gnome.org>

---
 libvirt-gobject/libvirt-gobject-storage-pool.c |  304 +++++++++++++++++++++++-
 libvirt-gobject/libvirt-gobject-storage-pool.h |   19 ++
 libvirt-gobject/libvirt-gobject.sym            |    6 +
 3 files changed, 319 insertions(+), 10 deletions(-)

diff --git a/libvirt-gobject/libvirt-gobject-storage-pool.c b/libvirt-gobject/libvirt-gobject-storage-pool.c
index 0959642..5499e4d 100644
--- a/libvirt-gobject/libvirt-gobject-storage-pool.c
+++ b/libvirt-gobject/libvirt-gobject-storage-pool.c
@@ -38,7 +38,10 @@ extern gboolean debugFlag;
 
 struct _GVirStoragePoolPrivate
 {
+    GMutex *lock;
     virStoragePoolPtr handle;
+
+    GHashTable *volumes;
 };
 
 G_DEFINE_TYPE(GVirStoragePool, gvir_storage_pool, G_TYPE_OBJECT);
@@ -64,8 +67,8 @@ static void gvir_storage_pool_get_property(GObject *object,
                                            GValue *value,
                                            GParamSpec *pspec)
 {
-    GVirStoragePool *conn = GVIR_STORAGE_POOL(object);
-    GVirStoragePoolPrivate *priv = conn->priv;
+    GVirStoragePool *pool = GVIR_STORAGE_POOL(object);
+    GVirStoragePoolPrivate *priv = pool->priv;
 
     switch (prop_id) {
     case PROP_HANDLE:
@@ -83,8 +86,8 @@ static void gvir_storage_pool_set_property(GObject *object,
                                            const GValue *value,
                                            GParamSpec *pspec)
 {
-    GVirStoragePool *conn = GVIR_STORAGE_POOL(object);
-    GVirStoragePoolPrivate *priv = conn->priv;
+    GVirStoragePool *pool = GVIR_STORAGE_POOL(object);
+    GVirStoragePoolPrivate *priv = pool->priv;
 
     switch (prop_id) {
     case PROP_HANDLE:
@@ -101,13 +104,20 @@ static void gvir_storage_pool_set_property(GObject *object,
 
 static void gvir_storage_pool_finalize(GObject *object)
 {
-    GVirStoragePool *conn = GVIR_STORAGE_POOL(object);
-    GVirStoragePoolPrivate *priv = conn->priv;
+    GVirStoragePool *pool = GVIR_STORAGE_POOL(object);
+    GVirStoragePoolPrivate *priv = pool->priv;
+
+    DEBUG("Finalize GVirStoragePool=%p", pool);
 
-    DEBUG("Finalize GVirStoragePool=%p", conn);
+    if (priv->volumes) {
+        g_hash_table_unref(priv->volumes);
+        priv->volumes = NULL;
+    }
 
     virStoragePoolFree(priv->handle);
 
+    g_mutex_free(priv->lock);
+
     G_OBJECT_CLASS(gvir_storage_pool_parent_class)->finalize(object);
 }
 
@@ -137,15 +147,17 @@ static void gvir_storage_pool_class_init(GVirStoragePoolClass *klass)
 }
 
 
-static void gvir_storage_pool_init(GVirStoragePool *conn)
+static void gvir_storage_pool_init(GVirStoragePool *pool)
 {
     GVirStoragePoolPrivate *priv;
 
-    DEBUG("Init GVirStoragePool=%p", conn);
+    DEBUG("Init GVirStoragePool=%p", pool);
 
-    priv = conn->priv = GVIR_STORAGE_POOL_GET_PRIVATE(conn);
+    priv = pool->priv = GVIR_STORAGE_POOL_GET_PRIVATE(pool);
 
     memset(priv, 0, sizeof(*priv));
+
+    priv->lock = g_mutex_new();
 }
 
 static gpointer
@@ -220,3 +232,275 @@ GVirConfigStoragePool *gvir_storage_pool_get_config(GVirStoragePool *pool,
     g_free(xml);
     return conf;
 }
+
+typedef gint (* CountFunction) (virStoragePoolPtr vpool);
+typedef gint (* ListFunction) (virStoragePoolPtr vpool, gchar **lst, gint max);
+
+static gchar ** fetch_list(virStoragePoolPtr vpool,
+                           const char *name,
+                           CountFunction count_func,
+                           ListFunction list_func,
+                           GCancellable *cancellable,
+                           gint *length,
+                           GError **err)
+{
+    gchar **lst = NULL;
+    gint n = 0;
+    gint i;
+
+    if ((n = count_func(vpool)) < 0) {
+        *err = gvir_error_new(GVIR_STORAGE_POOL_ERROR,
+                              0,
+                              "Unable to count %s", name);
+        goto error;
+    }
+
+    if (n) {
+        if (g_cancellable_set_error_if_cancelled(cancellable, err))
+            goto error;
+
+        lst = g_new(gchar *, n);
+        if ((n = list_func(vpool, lst, n)) < 0) {
+            *err = gvir_error_new(GVIR_STORAGE_POOL_ERROR,
+                                  0,
+                                  "Unable to list %s %d", name, n);
+            goto error;
+        }
+    }
+
+    *length = n;
+    return lst;
+
+error:
+    for (i = 0 ; i < n; i++)
+        g_free(lst[i]);
+    g_free(lst);
+    return NULL;
+}
+
+/**
+ * gvir_storage_pool_refresh:
+ * @pool: the storage pool
+ * @cancellable: (allow-none)(transfer none): cancellation object
+ */
+gboolean gvir_storage_pool_refresh(GVirStoragePool *pool,
+                                   GCancellable *cancellable,
+                                   GError **err)
+{
+    GVirStoragePoolPrivate *priv = pool->priv;
+    GHashTable *vol_hash;
+    gchar **volumes = NULL;
+    gint nvolumes = 0;
+    gboolean ret = FALSE;
+    gint i;
+    virStoragePoolPtr vpool = NULL;
+
+    vpool = priv->handle;
+
+    if (virStoragePoolRefresh(vpool, 0) < 0) {
+        *err = gvir_error_new_literal(GVIR_STORAGE_POOL_ERROR,
+                                      0,
+                                      "Unable to refresh storage pool");
+        goto cleanup;
+    }
+
+    volumes = fetch_list(vpool,
+                        "Storage Volumes",
+                        virStoragePoolNumOfVolumes,
+                        virStoragePoolListVolumes,
+                        cancellable,
+                        &nvolumes,
+                        err);
+    if (*err != NULL)
+        goto cleanup;
+
+    if (g_cancellable_set_error_if_cancelled(cancellable, err))
+        goto cleanup;
+
+    vol_hash = g_hash_table_new_full(g_str_hash,
+                                     g_str_equal,
+                                     g_free,
+                                     g_object_unref);
+
+    for (i = 0 ; i < nvolumes ; i++) {
+        if (g_cancellable_set_error_if_cancelled(cancellable, err))
+            goto cleanup;
+
+        virStorageVolPtr vvolume;
+        GVirStorageVol *volume;
+
+        vvolume = virStorageVolLookupByName(vpool, volumes[i]);
+        if (!vvolume)
+            continue;
+
+        volume = GVIR_STORAGE_VOL(g_object_new(GVIR_TYPE_STORAGE_VOL,
+                                               "handle", vvolume,
+                                               NULL));
+
+        g_hash_table_insert(vol_hash, g_strdup(volumes[i]), volume);
+    }
+
+    g_mutex_lock(priv->lock);
+    if (priv->volumes)
+        g_hash_table_unref(priv->volumes);
+    priv->volumes = vol_hash;
+    g_mutex_unlock(priv->lock);
+
+    ret = TRUE;
+
+cleanup:
+    for (i = 0 ; i < nvolumes ; i++)
+        g_free(volumes[i]);
+    g_free(volumes);
+    return ret;
+}
+
+static void
+gvir_storage_pool_refresh_helper(GSimpleAsyncResult *res,
+                                 GObject *object,
+                                 GCancellable *cancellable)
+{
+    GVirStoragePool *pool = GVIR_STORAGE_POOL(object);
+    GError *err = NULL;
+
+    if (!gvir_storage_pool_refresh(pool, cancellable, &err)) {
+        g_simple_async_result_set_from_error(res, err);
+        g_error_free(err);
+    }
+}
+
+/**
+ * gvir_storage_pool_refresh_async:
+ * @pool: the storage pool
+ * @cancellable: (allow-none)(transfer none): cancellation object
+ * @callback: (transfer none): completion callback
+ * @opaque: (transfer none)(allow-none): opaque data for callback
+ */
+void gvir_storage_pool_refresh_async(GVirStoragePool *pool,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer opaque)
+{
+    GSimpleAsyncResult *res;
+
+    res = g_simple_async_result_new(G_OBJECT(pool),
+                                    callback,
+                                    opaque,
+                                    gvir_storage_pool_refresh);
+    g_simple_async_result_run_in_thread(res,
+                                        gvir_storage_pool_refresh_helper,
+                                        G_PRIORITY_DEFAULT,
+                                        cancellable);
+    g_object_unref(res);
+}
+
+/**
+ * gvir_storage_pool_refresh_finish:
+ * @pool: the storage pool
+ * @result: (transfer none): async method result
+ */
+gboolean gvir_storage_pool_refresh_finish(GVirStoragePool *pool,
+                                          GAsyncResult *result,
+                                          GError **err)
+{
+    g_return_val_if_fail(GVIR_IS_STORAGE_POOL(pool), FALSE);
+    g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
+
+    if (G_IS_SIMPLE_ASYNC_RESULT(result)) {
+        GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(result);
+        g_warn_if_fail (g_simple_async_result_get_source_tag(simple) ==
+                        gvir_storage_pool_refresh);
+        if (g_simple_async_result_propagate_error(simple, err))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void gvir_storage_vol_ref(gpointer obj, gpointer ignore G_GNUC_UNUSED)
+{
+    g_object_ref(obj);
+}
+
+/**
+ * gvir_storage_pool_get_volumes:
+ * @pool: the storage pool
+ *
+ * Return value: (element-type LibvirtGObject.StoragePool) (transfer full): List
+ * of #GVirStorageVol
+ */
+GList *gvir_storage_pool_get_volumes(GVirStoragePool *pool)
+{
+    GVirStoragePoolPrivate *priv = pool->priv;
+    GList *volumes;
+
+    g_mutex_lock(priv->lock);
+    volumes = g_hash_table_get_values(priv->volumes);
+    g_list_foreach(volumes, gvir_storage_vol_ref, NULL);
+    g_mutex_unlock(priv->lock);
+
+    return volumes;
+}
+
+/**
+ * gvir_storage_pool_get_volume:
+ * @pool: the storage pool
+ * @name: Name of the requested storage volume
+ *
+ * Return value: (transfer full): the #GVirStorageVol, or NULL
+ */
+GVirStoragePool *gvir_storage_pool_get_volume(GVirStoragePool *pool,
+                                              const gchar *name)
+{
+    GVirStoragePoolPrivate *priv = pool->priv;
+    GVirStoragePool *volume;
+
+    g_mutex_lock(priv->lock);
+    volume = g_hash_table_lookup(priv->volumes, name);
+    if (volume)
+        g_object_ref(volume);
+    g_mutex_unlock(priv->lock);
+
+    return volume;
+}
+
+/**
+ * gvir_storage_pool_create_volume:
+ * @pool: the storage pool in which to create the volume
+ * @conf: the configuration for the new volume
+ * Returns: (transfer full): the newly created volume
+ */
+GVirStorageVol *gvir_storage_pool_create_volume
+                                (GVirStoragePool *pool,
+                                 GVirConfigStorageVol *conf,
+                                 GError **err)
+{
+    const gchar *xml;
+    virStorageVolPtr handle;
+    GVirStoragePoolPrivate *priv = pool->priv;
+
+    xml = gvir_config_object_get_doc(GVIR_CONFIG_OBJECT(conf));
+
+    g_return_val_if_fail(xml != NULL, NULL);
+
+    if (!(handle = virStorageVolCreateXML(priv->handle, xml, 0))) {
+        *err = gvir_error_new_literal(GVIR_STORAGE_POOL_ERROR,
+                                      0,
+                                      "Failed to create volume");
+        return NULL;
+    }
+
+    GVirStorageVol *volume;
+
+    volume = GVIR_STORAGE_VOL(g_object_new(GVIR_TYPE_STORAGE_VOL,
+                                           "handle", handle,
+                                           NULL));
+
+    g_mutex_lock(priv->lock);
+    g_hash_table_insert(priv->volumes,
+                        g_strdup(gvir_storage_vol_get_name(volume)),
+                        volume);
+    g_mutex_unlock(priv->lock);
+
+    return g_object_ref(volume);
+}
diff --git a/libvirt-gobject/libvirt-gobject-storage-pool.h b/libvirt-gobject/libvirt-gobject-storage-pool.h
index ffd5db7..67b945e 100644
--- a/libvirt-gobject/libvirt-gobject-storage-pool.h
+++ b/libvirt-gobject/libvirt-gobject-storage-pool.h
@@ -69,6 +69,25 @@ GVirConfigStoragePool *gvir_storage_pool_get_config(GVirStoragePool *pool,
                                                     guint64 flags,
                                                     GError **err);
 
+gboolean gvir_storage_pool_refresh(GVirStoragePool *pool,
+                                   GCancellable *cancellable,
+                                   GError **err);
+void gvir_storage_pool_refresh_async(GVirStoragePool *pool,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer opaque);
+gboolean gvir_storage_pool_refresh_finish(GVirStoragePool *pool,
+                                          GAsyncResult *result,
+                                          GError **err);
+
+GList *gvir_storage_pool_get_volumes(GVirStoragePool *pool);
+GVirStoragePool *gvir_storage_pool_get_volume(GVirStoragePool *pool,
+                                              const gchar *name);
+GVirStorageVol *gvir_storage_pool_create_volume
+                                (GVirStoragePool *pool,
+                                 GVirConfigStorageVol *conf,
+                                 GError **err);
+
 G_END_DECLS
 
 #endif /* __LIBVIRT_GOBJECT_STORAGE_POOL_H__ */
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index ea4ec38..cd24d83 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -79,6 +79,12 @@ LIBVIRT_GOBJECT_0.0.1 {
 	gvir_storage_pool_get_name;
 	gvir_storage_pool_get_uuid;
 	gvir_storage_pool_get_config;
+	gvir_storage_pool_refresh;
+	gvir_storage_pool_refresh_async;
+	gvir_storage_pool_refresh_finish;
+	gvir_storage_pool_get_volumes;
+	gvir_storage_pool_get_volume;
+	gvir_storage_pool_create_volume;
 
 	gvir_storage_vol_get_type;
 	gvir_storage_vol_handle_get_type;
-- 
1.7.6.2




More information about the libvir-list mailing list