[libvirt] [libvirt-glib] API to deal with storage pool(s)
Lei Li
lilei at linux.vnet.ibm.com
Tue Sep 27 03:40:45 UTC 2011
On 09/27/2011 06:19 AM, Zeeshan Ali (Khattak) wrote:
> From: "Zeeshan Ali (Khattak)"<zeeshanak at gnome.org>
>
> Add API to fetch, list, retrieve& find storage pool(s) on a connection.
> ---
> libvirt-gobject/libvirt-gobject-connection.c | 279 ++++++++++++++++++++++++++
> libvirt-gobject/libvirt-gobject-connection.h | 12 +-
> libvirt-gobject/libvirt-gobject.sym | 6 +
> 3 files changed, 296 insertions(+), 1 deletions(-)
>
> diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
> index 69c6956..c512e79 100644
> --- a/libvirt-gobject/libvirt-gobject-connection.c
> +++ b/libvirt-gobject/libvirt-gobject-connection.c
> @@ -43,6 +43,7 @@ struct _GVirConnectionPrivate
> virConnectPtr conn;
>
> GHashTable *domains;
> + GHashTable *pools;
> };
>
> G_DEFINE_TYPE(GVirConnection, gvir_connection, G_TYPE_OBJECT);
> @@ -357,6 +358,11 @@ void gvir_connection_close(GVirConnection *conn)
> priv->domains = NULL;
> }
>
> + if (priv->pools) {
> + g_hash_table_unref(priv->pools);
> + priv->pools = NULL;
> + }
> +
> if (priv->conn) {
> virConnectClose(priv->conn);
> priv->conn = NULL;
> @@ -503,6 +509,148 @@ cleanup:
> return ret;
> }
>
> +/**
> + * gvir_connection_fetch_storage_pools:
> + * @conn: the connection
> + * @cancellable: (allow-none)(transfer none): cancellation object
> + */
> +gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn,
> + GCancellable *cancellable,
> + GError **err)
> +{
> + GVirConnectionPrivate *priv = conn->priv;
> + GHashTable *pools;
> + gchar **inactive = NULL;
> + gint ninactive = 0;
> + gchar **active = NULL;
> + gint nactive = 0;
> + gboolean ret = FALSE;
> + gint i;
> + virConnectPtr vconn = NULL;
> +
> + g_mutex_lock(priv->lock);
> + if (!priv->conn) {
> + *err = gvir_error_new(GVIR_CONNECTION_ERROR,
> + 0,
> + "Connection is not open");
> + g_mutex_unlock(priv->lock);
> + goto cleanup;
> + }
> + vconn = priv->conn;
> + /* Stop another thread closing the connection just at the minute */
> + virConnectRef(vconn);
> + g_mutex_unlock(priv->lock);
> +
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + if ((nactive = virConnectNumOfStoragePools(vconn))< 0) {
> + *err = gvir_error_new(GVIR_CONNECTION_ERROR,
> + 0,
> + "Unable to count pools");
> + goto cleanup;
> + }
> + if (nactive) {
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + active = g_new(gchar *, nactive);
> + if ((nactive = virConnectListStoragePools(vconn,
> + active,
> + nactive))< 0) {
> + *err = gvir_error_new(GVIR_CONNECTION_ERROR,
> + 0,
> + "Unable to list pools");
> + goto cleanup;
> + }
> + }
> +
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + if ((ninactive = virConnectNumOfDefinedStoragePools(vconn))< 0) {
> + *err = gvir_error_new(GVIR_CONNECTION_ERROR,
> + 0,
> + "Unable to count pools");
> + goto cleanup;
> + }
> +
> + if (ninactive) {
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + inactive = g_new(gchar *, ninactive);
> + if ((ninactive = virConnectListDefinedStoragePools(vconn,
> + inactive,
> + ninactive))< 0) {
> + *err = gvir_error_new(GVIR_CONNECTION_ERROR,
> + 0,
> + "Unable to list pools %d", ninactive);
> + goto cleanup;
> + }
> + }
> +
> + pools = g_hash_table_new_full(g_str_hash,
> + g_str_equal,
> + g_free,
> + g_object_unref);
> +
> + for (i = 0 ; i< nactive ; i++) {
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + virStoragePoolPtr vpool;
> + GVirStoragePool *pool;
> +
> + vpool = virStoragePoolLookupByName(vconn, active[i]);
> + if (!vpool)
> + continue;
> +
> + pool = GVIR_STORAGE_POOL(g_object_new(GVIR_TYPE_STORAGE_POOL,
> + "handle", vpool,
> + NULL));
> +
> + g_hash_table_insert(pools,
> + g_strdup(gvir_storage_pool_get_uuid(pool)),
> + pool);
> + }
> +
> + for (i = 0 ; i< ninactive ; i++) {
> + if (g_cancellable_set_error_if_cancelled(cancellable, err))
> + goto cleanup;
> +
> + virStoragePoolPtr vpool;
> + GVirStoragePool *pool;
> +
> + vpool = virStoragePoolLookupByName(vconn, inactive[i]);
> + if (!vpool)
> + continue;
> +
> + pool = GVIR_STORAGE_POOL(g_object_new(GVIR_TYPE_STORAGE_POOL,
> + "handle", vpool,
> + NULL));
> +
> + g_hash_table_insert(pools,
> + g_strdup(gvir_storage_pool_get_uuid(pool)),
> + pool);
> + }
> +
> + g_mutex_lock(priv->lock);
> + if (priv->pools)
> + g_hash_table_unref(priv->pools);
> + priv->pools = pools;
> + virConnectClose(vconn);
> + g_mutex_unlock(priv->lock);
> +
> + ret = TRUE;
> +
> +cleanup:
> + g_free(active);
> + for (i = 0 ; i< ninactive ; i++)
> + g_free(inactive[i]);
> + g_free(inactive);
> + return ret;
> +}
>
> static void
> gvir_connection_fetch_domains_helper(GSimpleAsyncResult *res,
> @@ -566,6 +714,67 @@ gboolean gvir_connection_fetch_domains_finish(GVirConnection *conn,
> return TRUE;
> }
>
> +static void
> +gvir_connection_fetch_pools_helper(GSimpleAsyncResult *res,
> + GObject *object,
> + GCancellable *cancellable)
> +{
> + GVirConnection *conn = GVIR_CONNECTION(object);
> + GError *err = NULL;
> +
> + if (!gvir_connection_fetch_storage_pools(conn, cancellable,&err)) {
> + g_simple_async_result_set_from_error(res, err);
> + g_error_free(err);
> + }
> +}
> +
> +/**
> + * gvir_connection_fetch_storage_pools_async:
> + * @conn: the connection
> + * @cancellable: (allow-none)(transfer none): cancellation object
> + * @callback: (transfer none): completion callback
> + * @opaque: (transfer none)(allow-none): opaque data for callback
> + */
> +void gvir_connection_fetch_storage_pools_async(GVirConnection *conn,
> + GCancellable *cancellable,
> + GAsyncReadyCallback callback,
> + gpointer opaque)
> +{
> + GSimpleAsyncResult *res;
> +
> + res = g_simple_async_result_new(G_OBJECT(conn),
> + callback,
> + opaque,
> + gvir_connection_fetch_storage_pools);
> + g_simple_async_result_run_in_thread(res,
> + gvir_connection_fetch_pools_helper,
> + G_PRIORITY_DEFAULT,
> + cancellable);
> + g_object_unref(res);
> +}
> +
> +/**
> + * gvir_connection_fetch_storage_pools_finish:
> + * @conn: the connection
> + * @result: (transfer none): async method result
> + */
> +gboolean gvir_connection_fetch_storage_pools_finish(GVirConnection *conn,
> + GAsyncResult *result,
> + GError **err)
> +{
> + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), 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_connection_fetch_storage_pools);
> + if (g_simple_async_result_propagate_error(simple, err))
> + return FALSE;
> + }
> +
> + return TRUE;
> +}
>
> const gchar *gvir_connection_get_uri(GVirConnection *conn)
> {
> @@ -595,6 +804,25 @@ GList *gvir_connection_get_domains(GVirConnection *conn)
> }
>
> /**
> + * gvir_connection_get_storage_pools:
> + *
> + * Return value: (element-type LibvirtGObject.StoragePool) (transfer full): List
> + * of #GVirStoragePool
> + */
> +GList *gvir_connection_get_storage_pools(GVirConnection *conn)
> +{
> + GVirConnectionPrivate *priv = conn->priv;
> + GList *pools;
> +
> + g_mutex_lock(priv->lock);
> + pools = g_hash_table_get_values(priv->pools);
> + g_list_foreach(pools, gvir_domain_ref, NULL);
> + g_mutex_unlock(priv->lock);
> +
> + return pools;
> +}
> +
> +/**
> * gvir_connection_get_domain:
> * @uuid: uuid string of the requested domain
> *
> @@ -613,6 +841,26 @@ GVirDomain *gvir_connection_get_domain(GVirConnection *conn,
> return dom;
> }
>
> +/**
> + * gvir_connection_get_storage_pool:
> + * @uuid: uuid string of the requested storage pool
> + *
> + * Return value: (transfer full): the #GVirStoragePool, or NULL
> + */
> +GVirStoragePool *gvir_connection_get_storage_pool(GVirConnection *conn,
> + const gchar *uuid)
> +{
> + GVirConnectionPrivate *priv = conn->priv;
> + GVirStoragePool *pool;
> +
> + g_mutex_lock(priv->lock);
> + pool = g_hash_table_lookup(priv->pools, uuid);
> + if (pool)
> + g_object_ref(pool);
> + g_mutex_unlock(priv->lock);
> +
> + return pool;
> +}
>
> /**
> * gvir_connection_find_domain_by_id:
> @@ -677,6 +925,37 @@ GVirDomain *gvir_connection_find_domain_by_name(GVirConnection *conn,
> return NULL;
> }
>
> +/**
> + * gvir_connection_find_storage_pool_by_name:
> + * @name: name of the requested storage pool
> + *
> + * Return value: (transfer full): the #GVirStoragePool, or NULL
> + */
> +GVirStoragePool *gvir_connection_find_storage_pool_by_name(GVirConnection *conn,
> + const gchar *name)
> +{
> + GVirConnectionPrivate *priv = conn->priv;
> + GHashTableIter iter;
> + gpointer key, value;
> +
> + g_mutex_lock(priv->lock);
> + g_hash_table_iter_init(&iter, priv->pools);
> +
> + while (g_hash_table_iter_next(&iter,&key,&value)) {
> + GVirStoragePool *pool = value;
> + const gchar *thisname = gvir_storage_pool_get_name(pool);
> +
> + if (strcmp(thisname, name) == 0) {
> + g_object_ref(pool);
> + g_mutex_unlock(priv->lock);
> + return pool;
> + }
> + }
> + g_mutex_unlock(priv->lock);
> +
> + return NULL;
> +}
> +
> static gpointer
> gvir_connection_handle_copy(gpointer src)
> {
> diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h
> index c453bed..d05f792 100644
> --- a/libvirt-gobject/libvirt-gobject-connection.h
> +++ b/libvirt-gobject/libvirt-gobject-connection.h
> @@ -141,14 +141,24 @@ GVirNodeDevice *gvir_connection_get_node_device(GVirConnection *conn,
> GList *gvir_connection_get_secrets(GVirConnection *conn);
> GVirSecret *gvir_connection_get_secret(GVirConnection *conn,
> const gchar *uuid);
> +#endif
>
> +gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn,
> + GCancellable *cancellable,
> + GError **err);
> +void gvir_connection_fetch_storage_pools_async(GVirConnection *conn,
> + GCancellable *cancellable,
> + GAsyncReadyCallback callback,
> + gpointer opaque);
> +gboolean gvir_connection_fetch_storage_pools_finish(GVirConnection *conn,
> + GAsyncResult *result,
> + GError **err);
>
> GList *gvir_connection_get_storage_pools(GVirConnection *conn);
> GVirStoragePool *gvir_connection_get_storage_pool(GVirConnection *conn,
> const gchar *uuid);
> GVirStoragePool *gvir_connection_find_storage_pool_by_name(GVirConnection *conn,
> const gchar *name);
> -#endif
>
> GVirStream *gvir_connection_get_stream(GVirConnection *conn,
> gint flags);
> diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
> index eae40a2..ff2f4cf 100644
> --- a/libvirt-gobject/libvirt-gobject.sym
> +++ b/libvirt-gobject/libvirt-gobject.sym
> @@ -14,10 +14,16 @@ LIBVIRT_GOBJECT_0.0.1 {
> gvir_connection_get_stream;
>
> gvir_connection_fetch_domains;
> + gvir_connection_fetch_storage_pools;
> + gvir_connection_fetch_storage_pools_async;
> + gvir_connection_fetch_storage_pools_finish;
> gvir_connection_get_domains;
> + gvir_connection_get_storage_pools;
> gvir_connection_get_domain;
> + gvir_connection_get_storage_pool;
> gvir_connection_find_domain_by_id;
> gvir_connection_find_domain_by_name;
> + gvir_connection_find_storage_pool_by_name;
I think It would be better to add API
gvir_connection_find_storage_pool_by_id also to keep consistence
with domain.
> gvir_connection_create_domain;
>
> gvir_domain_get_type;
--
Lei
More information about the libvir-list
mailing list