From: "Zeeshan Ali (Khattak)" <zeeshanak@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list