[libvirt] [libvirt-glib PATCHv3 1/7] gobject: Simplify gvir_connection_list*() implementations

Make use of virConnectListAll* functions to avoid making 4 calls and hence avoid race conditions and complicated code. --- libvirt-gobject/libvirt-gobject-connection.c | 203 ++++----------------------- 1 file changed, 28 insertions(+), 175 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index cf073a5..1576906 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -680,48 +680,6 @@ void gvir_connection_close(GVirConnection *conn) g_signal_emit(conn, signals[VIR_CONNECTION_CLOSED], 0); } -typedef gint (* CountFunction) (virConnectPtr vconn); -typedef gint (* ListFunction) (virConnectPtr vconn, gchar **lst, gint max); - -static gchar ** fetch_list(virConnectPtr vconn, - const char *name, - CountFunction count_func, - ListFunction list_func, - GCancellable *cancellable, - gint *length, - GError **err) -{ - gchar **lst = NULL; - gint n = 0; - - if ((n = count_func(vconn)) < 0) { - gvir_set_error(err, GVIR_CONNECTION_ERROR, - 0, - _("Unable to count %s"), name); - goto error; - } - - if (n) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto error; - - lst = g_new0(gchar *, n); - if ((n = list_func(vconn, lst, n)) < 0) { - gvir_set_error(err, GVIR_CONNECTION_ERROR, - 0, - _("Unable to list %s %d"), name, n); - goto error; - } - } - - *length = n; - return lst; - -error: - g_free(lst); - return NULL; -} - /** * gvir_connection_fetch_domains: * @conn: a #GVirConnection @@ -733,14 +691,11 @@ gboolean gvir_connection_fetch_domains(GVirConnection *conn, { GVirConnectionPrivate *priv; GHashTable *doms; - gchar **inactive = NULL; - gint ninactive = 0; - gint *active = NULL; - gint nactive = 0; + virDomainPtr *domains = NULL; + gint ndomains = 0; gboolean ret = FALSE; gint i; virConnectPtr vconn = NULL; - GError *lerr = NULL; g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), @@ -761,81 +716,28 @@ gboolean gvir_connection_fetch_domains(GVirConnection *conn, virConnectRef(vconn); g_mutex_unlock(priv->lock); - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - if ((nactive = virConnectNumOfDomains(vconn)) < 0) { - gvir_set_error_literal(err, GVIR_CONNECTION_ERROR, - 0, - _("Unable to count domains")); + ndomains = virConnectListAllDomains(vconn, &domains, 0); + if (ndomains < 0) { + gvir_set_error(err, GVIR_CONNECTION_ERROR, + 0, + _("Failed to fetch list of domains")); goto cleanup; } - if (nactive) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - active = g_new(gint, nactive); - if ((nactive = virConnectListDomains(vconn, active, nactive)) < 0) { - gvir_set_error_literal(err, GVIR_CONNECTION_ERROR, - 0, - _("Unable to list domains")); - goto cleanup; - } - } if (g_cancellable_set_error_if_cancelled(cancellable, err)) goto cleanup; - inactive = fetch_list(vconn, - "Domains", - virConnectNumOfDefinedDomains, - virConnectListDefinedDomains, - cancellable, - &ninactive, - &lerr); - if (lerr) { - g_propagate_error(err, lerr); - lerr = NULL; - goto cleanup; - } - doms = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref); - for (i = 0 ; i < nactive ; i++) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - virDomainPtr vdom = virDomainLookupByID(vconn, active[i]); + for (i = 0 ; i < ndomains; i++) { GVirDomain *dom; - if (!vdom) - continue; dom = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN, - "handle", vdom, + "handle", domains[i], NULL)); - virDomainFree(vdom); - - g_hash_table_insert(doms, - (gpointer)gvir_domain_get_uuid(dom), - dom); - } - - for (i = 0 ; i < ninactive ; i++) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - virDomainPtr vdom = virDomainLookupByName(vconn, inactive[i]); - GVirDomain *dom; - if (!vdom) - continue; - - dom = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN, - "handle", vdom, - NULL)); - virDomainFree(vdom); g_hash_table_insert(doms, (gpointer)gvir_domain_get_uuid(dom), @@ -852,10 +754,11 @@ gboolean gvir_connection_fetch_domains(GVirConnection *conn, ret = TRUE; cleanup: - g_free(active); - for (i = 0 ; i < ninactive ; i++) - g_free(inactive[i]); - g_free(inactive); + if (ndomains > 0) { + for (i = 0 ; i < ndomains; i++) + virDomainFree(domains[i]); + free(domains); + } return ret; } @@ -870,14 +773,11 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn, { GVirConnectionPrivate *priv; GHashTable *pools; - gchar **inactive = NULL; - gint ninactive = 0; - gchar **active = NULL; - gint nactive = 0; + virStoragePoolPtr *vpools = NULL; + gint npools = 0; gboolean ret = FALSE; gint i; virConnectPtr vconn = NULL; - GError *lerr = NULL; g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), @@ -901,77 +801,31 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn, if (g_cancellable_set_error_if_cancelled(cancellable, err)) goto cleanup; - active = fetch_list(vconn, - "Storage Pools", - virConnectNumOfStoragePools, - virConnectListStoragePools, - cancellable, - &nactive, - &lerr); - if (lerr) { - g_propagate_error(err, lerr); - lerr = NULL; + npools = virConnectListAllStoragePools(vconn, &vpools, 0); + if (npools < 0) { + gvir_set_error(err, GVIR_CONNECTION_ERROR, + 0, + _("Failed to fetch list of pools")); goto cleanup; } if (g_cancellable_set_error_if_cancelled(cancellable, err)) goto cleanup; - inactive = fetch_list(vconn, - "Storage Pools", - virConnectNumOfDefinedStoragePools, - virConnectListDefinedStoragePools, - cancellable, - &ninactive, - &lerr); - if (lerr) { - g_propagate_error(err, lerr); - lerr = NULL; - goto cleanup; - } - pools = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref); - for (i = 0 ; i < nactive ; i++) { + for (i = 0 ; i < npools; 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)); - virStoragePoolFree(vpool); - - g_hash_table_insert(pools, - (gpointer)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, + "handle", vpools[i], NULL)); - virStoragePoolFree(vpool); - g_hash_table_insert(pools, (gpointer)gvir_storage_pool_get_uuid(pool), pool); @@ -987,12 +841,11 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn, ret = TRUE; cleanup: - for (i = 0 ; i < nactive ; i++) - g_free(active[i]); - g_free(active); - for (i = 0 ; i < ninactive ; i++) - g_free(inactive[i]); - g_free(inactive); + if (npools > 0) { + for (i = 0 ; i < npools; i++) + virStoragePoolFree(vpools[i]); + free(vpools); + } return ret; } -- 2.4.3

--- libvirt-gobject/libvirt-gobject-connection.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 1576906..dddbd3a 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -748,7 +748,6 @@ gboolean gvir_connection_fetch_domains(GVirConnection *conn, if (priv->domains) g_hash_table_unref(priv->domains); priv->domains = doms; - virConnectClose(vconn); g_mutex_unlock(priv->lock); ret = TRUE; @@ -759,6 +758,8 @@ cleanup: virDomainFree(domains[i]); free(domains); } + if (vconn != NULL) + virConnectClose(vconn); return ret; } @@ -835,7 +836,6 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn, if (priv->pools) g_hash_table_unref(priv->pools); priv->pools = pools; - virConnectClose(vconn); g_mutex_unlock(priv->lock); ret = TRUE; @@ -846,6 +846,8 @@ cleanup: virStoragePoolFree(vpools[i]); free(vpools); } + if (vconn != NULL) + virConnectClose(vconn); return ret; } -- 2.4.3

GSimpleAsyncResult has been deprecated in favour of GTask and with latest glib headers, we get tons of warnings about use of deprecated API. This patch ports the GVirConnection class to GTask. --- libvirt-gobject/libvirt-gobject-connection.c | 236 ++++++++++++--------------- 1 file changed, 100 insertions(+), 136 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index dddbd3a..0e776c0 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -497,17 +497,16 @@ gboolean gvir_connection_open_read_only(GVirConnection *conn, } static void -gvir_connection_open_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_open_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, GCancellable *cancellable) { GVirConnection *conn = GVIR_CONNECTION(object); GError *err = NULL; - if (!gvir_connection_open(conn, cancellable, &err)) { - g_simple_async_result_set_from_error(res, err); - g_error_free(err); - } + if (!gvir_connection_open(conn, cancellable, &err)) + g_task_return_error(res, err); } @@ -523,19 +522,19 @@ void gvir_connection_open_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; g_return_if_fail(GVIR_IS_CONNECTION(conn)); g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); - res = g_simple_async_result_new(G_OBJECT(conn), - callback, - user_data, - gvir_connection_open_async); - g_simple_async_result_run_in_thread(res, - gvir_connection_open_helper, - G_PRIORITY_DEFAULT, - cancellable); + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_open_async); + g_task_run_in_thread(res, + gvir_connection_open_helper); g_object_unref(res); } @@ -550,28 +549,23 @@ gboolean gvir_connection_open_finish(GVirConnection *conn, GError **err) { g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); - g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(conn), - gvir_connection_open_async), + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), FALSE); - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err)) - return FALSE; - - return TRUE; + return g_task_propagate_boolean(G_TASK(result), err); } static void -gvir_connection_open_read_only_helper(GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) +gvir_connection_open_read_only_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, + GCancellable *cancellable) { GVirConnection *conn = GVIR_CONNECTION(object); GError *err = NULL; - if (!gvir_connection_open_read_only(conn, cancellable, &err)) { - g_simple_async_result_set_from_error(res, err); - g_error_free(err); - } + if (!gvir_connection_open_read_only(conn, cancellable, &err)) + g_task_return_error(res, err); } @@ -587,19 +581,19 @@ void gvir_connection_open_read_only_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; g_return_if_fail(GVIR_IS_CONNECTION(conn)); g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); - res = g_simple_async_result_new(G_OBJECT(conn), - callback, - user_data, - gvir_connection_open_read_only_async); - g_simple_async_result_run_in_thread(res, - gvir_connection_open_read_only_helper, - G_PRIORITY_DEFAULT, - cancellable); + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_open_read_only_async); + g_task_run_in_thread(res, + gvir_connection_open_read_only_helper); g_object_unref(res); } @@ -614,14 +608,10 @@ gboolean gvir_connection_open_read_only_finish(GVirConnection *conn, GError **err) { g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); - g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(conn), - gvir_connection_open_read_only_async), + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), FALSE); - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err)) - return FALSE; - - return TRUE; + return g_task_propagate_boolean(G_TASK(result), err); } gboolean gvir_connection_is_open(GVirConnection *conn) @@ -852,17 +842,16 @@ cleanup: } static void -gvir_connection_fetch_domains_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_fetch_domains_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, GCancellable *cancellable) { GVirConnection *conn = GVIR_CONNECTION(object); GError *err = NULL; - if (!gvir_connection_fetch_domains(conn, cancellable, &err)) { - g_simple_async_result_set_from_error(res, err); - g_error_free(err); - } + if (!gvir_connection_fetch_domains(conn, cancellable, &err)) + g_task_return_error(res, err); } @@ -878,19 +867,19 @@ void gvir_connection_fetch_domains_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; g_return_if_fail(GVIR_IS_CONNECTION(conn)); g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); - res = g_simple_async_result_new(G_OBJECT(conn), - callback, - user_data, - gvir_connection_fetch_domains_async); - g_simple_async_result_run_in_thread(res, - gvir_connection_fetch_domains_helper, - G_PRIORITY_DEFAULT, - cancellable); + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_fetch_domains_async); + g_task_run_in_thread(res, + gvir_connection_fetch_domains_helper); g_object_unref(res); } @@ -904,28 +893,23 @@ gboolean gvir_connection_fetch_domains_finish(GVirConnection *conn, GError **err) { g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); - g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(conn), - gvir_connection_fetch_domains_async), + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), FALSE); - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err)) - return FALSE; - - return TRUE; + return g_task_propagate_boolean(G_TASK(result), err); } static void -gvir_connection_fetch_pools_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_fetch_pools_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, 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); - } + if (!gvir_connection_fetch_storage_pools(conn, cancellable, &err)) + g_task_return_error(res, err); } /** @@ -940,19 +924,19 @@ void gvir_connection_fetch_storage_pools_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; g_return_if_fail(GVIR_IS_CONNECTION(conn)); g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); - res = g_simple_async_result_new(G_OBJECT(conn), - callback, - user_data, - gvir_connection_fetch_storage_pools_async); - g_simple_async_result_run_in_thread(res, - gvir_connection_fetch_pools_helper, - G_PRIORITY_DEFAULT, - cancellable); + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_fetch_storage_pools_async); + g_task_run_in_thread(res, + gvir_connection_fetch_pools_helper); g_object_unref(res); } @@ -966,14 +950,10 @@ gboolean gvir_connection_fetch_storage_pools_finish(GVirConnection *conn, GError **err) { g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); - g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(conn), - gvir_connection_fetch_storage_pools_async), + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), FALSE); - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err)) - return FALSE; - - return TRUE; + return g_task_propagate_boolean(G_TASK(result), err); } const gchar *gvir_connection_get_uri(GVirConnection *conn) @@ -1568,8 +1548,9 @@ GVirConfigCapabilities *gvir_connection_get_capabilities(GVirConnection *conn, } static void -gvir_connection_get_capabilities_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_get_capabilities_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, GCancellable *cancellable G_GNUC_UNUSED) { GVirConnection *conn = GVIR_CONNECTION(object); @@ -1578,12 +1559,12 @@ gvir_connection_get_capabilities_helper(GSimpleAsyncResult *res, caps = gvir_connection_get_capabilities(conn, &err); if (caps == NULL) { - g_simple_async_result_take_error(res, err); + g_task_return_error(res, err); return; } - g_simple_async_result_set_op_res_gpointer(res, caps, g_object_unref); + g_task_set_task_data(res, caps, g_object_unref); } /** @@ -1598,19 +1579,19 @@ void gvir_connection_get_capabilities_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; g_return_if_fail(GVIR_IS_CONNECTION(conn)); g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); - res = g_simple_async_result_new(G_OBJECT(conn), - callback, - user_data, - gvir_connection_get_capabilities_async); - g_simple_async_result_run_in_thread(res, - gvir_connection_get_capabilities_helper, - G_PRIORITY_DEFAULT, - cancellable); + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_get_capabilities_async); + g_task_run_in_thread(res, + gvir_connection_get_capabilities_helper); g_object_unref(res); } @@ -1628,19 +1609,11 @@ gvir_connection_get_capabilities_finish(GVirConnection *conn, GAsyncResult *result, GError **err) { - GVirConfigCapabilities *caps; - g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); - g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(conn), - gvir_connection_get_capabilities_async), + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), NULL); - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err)) - return NULL; - - caps = g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(result)); - - return g_object_ref(caps); + return g_task_propagate_pointer(G_TASK(result), err); } /** @@ -1708,22 +1681,23 @@ static void restore_domain_from_file_data_free(RestoreDomainFromFileData *data) static void gvir_connection_restore_domain_from_file_helper - (GSimpleAsyncResult *res, - GObject *object, + (GTask *res, + gpointer object, + gpointer task_data, GCancellable *cancellable G_GNUC_UNUSED) { GVirConnection *conn = GVIR_CONNECTION(object); RestoreDomainFromFileData *data; GError *err = NULL; - data = g_simple_async_result_get_op_res_gpointer(res); + data = (RestoreDomainFromFileData *)task_data; if (!gvir_connection_restore_domain_from_file(conn, data->filename, data->custom_conf, data->flags, &err)) - g_simple_async_result_take_error(res, err); + g_task_return_error(res, err); } /** @@ -1747,7 +1721,7 @@ gvir_connection_restore_domain_from_file_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *res; RestoreDomainFromFileData *data; g_return_if_fail(GVIR_IS_CONNECTION(conn)); @@ -1760,21 +1734,18 @@ gvir_connection_restore_domain_from_file_async(GVirConnection *conn, data->custom_conf = g_object_ref(custom_conf); data->flags = flags; - res = g_simple_async_result_new - (G_OBJECT(conn), - callback, - user_data, + res = g_task_new (G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, gvir_connection_restore_domain_from_file_async); - g_simple_async_result_set_op_res_gpointer - (res, - data, - (GDestroyNotify)restore_domain_from_file_data_free); + g_task_set_task_data(res, + data, + (GDestroyNotify)restore_domain_from_file_data_free); - g_simple_async_result_run_in_thread - (res, - gvir_connection_restore_domain_from_file_helper, - G_PRIORITY_DEFAULT, - cancellable); + g_task_run_in_thread(res, + gvir_connection_restore_domain_from_file_helper); g_object_unref(res); } @@ -1795,15 +1766,8 @@ gvir_connection_restore_domain_from_file_finish(GVirConnection *conn, GError **err) { g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); - g_return_val_if_fail(g_simple_async_result_is_valid - (result, - G_OBJECT(conn), - gvir_connection_restore_domain_from_file_async), - FALSE); - - if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), - err)) - return FALSE; + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), + FALSE); - return TRUE; + return g_task_propagate_boolean(G_TASK(result), err); } -- 2.4.3

Add API to query network interfaces from a connection. --- libvirt-gobject/libvirt-gobject-connection.c | 263 +++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-connection.h | 13 +- libvirt-gobject/libvirt-gobject.sym | 7 + 3 files changed, 281 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 0e776c0..00e6f8f 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -44,6 +44,7 @@ struct _GVirConnectionPrivate GHashTable *domains; GHashTable *pools; + GHashTable *interfaces; }; G_DEFINE_TYPE(GVirConnection, gvir_connection, G_TYPE_OBJECT); @@ -252,6 +253,10 @@ static void gvir_connection_init(GVirConnection *conn) g_str_equal, NULL, g_object_unref); + priv->interfaces = g_hash_table_new_full(g_str_hash, + g_str_equal, + NULL, + g_object_unref); } @@ -658,6 +663,11 @@ void gvir_connection_close(GVirConnection *conn) priv->pools = NULL; } + if (priv->interfaces) { + g_hash_table_unref(priv->interfaces); + priv->interfaces = NULL; + } + if (priv->conn) { virConnectDomainEventDeregister(priv->conn, domain_event_cb); virConnectClose(priv->conn); @@ -1423,6 +1433,259 @@ GVirDomain *gvir_connection_start_domain(GVirConnection *conn, } /** + * gvir_connection_fetch_interfaces: + * @conn: a #GVirConnection + * @cancellable: (allow-none)(transfer none): cancellation object + * @err: return location for any errors + * + * Use this method to fetch information on all network interfaces + * managed by connection @conn on host machine. Use + * #gvir_connection_get_interfaces or #gvir_connection_get_interface after + * wards to query the fetched interfaces. + * + * Return value: %TRUE on success, %FALSE otherwise and @err is set. + */ +gboolean gvir_connection_fetch_interfaces(GVirConnection *conn, + GCancellable *cancellable, + GError **err) +{ + GVirConnectionPrivate *priv; + GHashTable *interfaces; + virInterfacePtr *ifaces = NULL; + gint ninterfaces = 0; + gboolean ret = FALSE; + gint i; + virConnectPtr vconn = NULL; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); + g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), + FALSE); + g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE); + + priv = conn->priv; + g_mutex_lock(priv->lock); + if (!priv->conn) { + g_set_error_literal(err, 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; + + ninterfaces = virConnectListAllInterfaces(vconn, &ifaces, 0); + if (ninterfaces < 0) { + gvir_set_error(err, GVIR_CONNECTION_ERROR, + 0, + _("Failed to fetch list of interfaces")); + goto cleanup; + } + + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + interfaces = g_hash_table_new_full(g_str_hash, + g_str_equal, + NULL, + g_object_unref); + + for (i = 0 ; i < ninterfaces; i++) { + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + GVirInterface *iface; + + iface = GVIR_INTERFACE(g_object_new(GVIR_TYPE_INTERFACE, + "handle", ifaces[i], + NULL)); + + g_hash_table_insert(interfaces, + (gpointer)gvir_interface_get_name(iface), + iface); + } + + g_mutex_lock(priv->lock); + if (priv->interfaces) + g_hash_table_unref(priv->interfaces); + priv->interfaces = interfaces; + g_mutex_unlock(priv->lock); + + ret = TRUE; + +cleanup: + if (ninterfaces > 0) { + for (i = 0 ; i < ninterfaces; i++) + virInterfaceFree(ifaces[i]); + free(ifaces); + } + if (vconn != NULL) + virConnectClose(vconn); + return ret; +} + +static void +gvir_connection_fetch_interfaces_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, + GCancellable *cancellable) +{ + GVirConnection *conn = GVIR_CONNECTION(object); + GError *err = NULL; + + if (!gvir_connection_fetch_interfaces(conn, cancellable, &err)) + g_task_return_error(res, err); +} + + +/** + * gvir_connection_fetch_interfaces_async: + * @conn: a #GVirConnection + * @cancellable: (allow-none)(transfer none): cancellation object + * @callback: (scope async): completion callback + * @user_data: (closure): opaque data for callback + */ +void gvir_connection_fetch_interfaces_async(GVirConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *res; + + g_return_if_fail(GVIR_IS_CONNECTION(conn)); + g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); + + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_fetch_interfaces_async); + g_task_run_in_thread(res, + gvir_connection_fetch_interfaces_helper); + g_object_unref(res); +} + +/** + * gvir_connection_fetch_interfaces_finish: + * @conn: a #GVirConnection + * @result: (transfer none): async method result + * @err: return location for any errors + */ +gboolean gvir_connection_fetch_interfaces_finish(GVirConnection *conn, + GAsyncResult *result, + GError **err) +{ + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), + FALSE); + + return g_task_propagate_boolean(G_TASK(result), err); +} + +/** + * gvir_connection_get_interfaces: + * @conn: a #GVirConnection + * + * Gets a list of all the network interfaces managed by connection @conn on + * host machine. + * + * Return value: (element-type LibvirtGObject.Interface) (transfer full): List + * of #GVirInterface. The returned list should be freed with g_list_free(), + * after its elements have been unreffed with g_object_unref(). + */ +GList *gvir_connection_get_interfaces(GVirConnection *conn) +{ + GVirConnectionPrivate *priv; + GList *interfaces = NULL; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + if (priv->interfaces != NULL) { + interfaces = g_hash_table_get_values(priv->interfaces); + g_list_foreach(interfaces, gvir_domain_ref, NULL); + } + g_mutex_unlock(priv->lock); + + return interfaces; +} + +/** + * gvir_connection_get_interface: + * @conn: a #GVirConnection + * + * Get a particular interface which has name @name. + * + * Return value: (transfer full): A new reference to a #GVirInterface, or NULL + * if no interface exists with name @name. The returned object must be unreffed + * using g_object_unref() once used. + */ +GVirInterface *gvir_connection_get_interface(GVirConnection *conn, + const gchar *name) +{ + GVirConnectionPrivate *priv; + GVirInterface *iface; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + g_return_val_if_fail(name != NULL, NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + iface = g_hash_table_lookup(priv->interfaces, name); + if (iface) + g_object_ref(iface); + g_mutex_unlock(priv->lock); + + return iface; +} + +/** + * gvir_connection_find_interface_by_mac: + * @conn: a #GVirConnection + * + * Get a particular interface which has MAC address @mac. + * + * Return value: (transfer full): A new reference to a #GVirInterface, or NULL + * if no interface exists with MAC address @mac. The returned object must be + * unreffed using g_object_unref() once used. + */ +GVirInterface *gvir_connection_find_interface_by_mac(GVirConnection *conn, + const gchar *mac) +{ + GVirConnectionPrivate *priv; + GHashTableIter iter; + gpointer key, value; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + g_return_val_if_fail(mac != NULL, NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + g_hash_table_iter_init(&iter, priv->interfaces); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + GVirInterface *iface = value; + const gchar *thismac = gvir_interface_get_mac(iface); + + if (g_strcmp0(thismac, mac) == 0) { + g_object_ref(iface); + g_mutex_unlock(priv->lock); + return iface; + } + } + g_mutex_unlock(priv->lock); + + return NULL; +} + +/** * gvir_connection_create_storage_pool: * @conn: a #GVirConnection on which to create the pool * @conf: the configuration for the new storage pool diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h index 8bca8d4..0c22a58 100644 --- a/libvirt-gobject/libvirt-gobject-connection.h +++ b/libvirt-gobject/libvirt-gobject-connection.h @@ -144,14 +144,23 @@ GVirDomain *gvir_connection_start_domain(GVirConnection *conn, guint flags, GError **err); -#if 0 +gboolean gvir_connection_fetch_interfaces(GVirConnection *conn, + GCancellable *cancellable, + GError **err); +void gvir_connection_fetch_interfaces_async(GVirConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean gvir_connection_fetch_interfaces_finish(GVirConnection *conn, + GAsyncResult *result, + GError **err); GList *gvir_connection_get_interfaces(GVirConnection *conn); GVirInterface *gvir_connection_get_interface(GVirConnection *conn, const gchar *name); GVirInterface *gvir_connection_find_interface_by_mac(GVirConnection *conn, const gchar *macaddr); - +#if 0 GList *gvir_connection_get_networks(GVirConnection *conn); GVirNetwork *gvir_connection_get_network(GVirConnection *conn, const gchar *uuid); diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 29c4349..1effcda 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -273,6 +273,13 @@ LIBVIRT_GOBJECT_0.2.1 { LIBVIRT_GOBJECT_0.2.2 { global: + gvir_connection_fetch_interfaces; + gvir_connection_fetch_interfaces_async; + gvir_connection_fetch_interfaces_finish; + gvir_connection_find_interface_by_mac; + gvir_connection_get_interface; + gvir_connection_get_interfaces; + gvir_interface_get_mac; } LIBVIRT_GOBJECT_0.2.1; -- 2.4.3

Add API to query networks from a connection. --- libvirt-gobject/libvirt-gobject-connection.c | 255 +++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-connection.h | 13 +- libvirt-gobject/libvirt-gobject.sym | 6 + 3 files changed, 272 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 00e6f8f..462b6ec 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -45,6 +45,7 @@ struct _GVirConnectionPrivate GHashTable *domains; GHashTable *pools; GHashTable *interfaces; + GHashTable *networks; }; G_DEFINE_TYPE(GVirConnection, gvir_connection, G_TYPE_OBJECT); @@ -257,6 +258,10 @@ static void gvir_connection_init(GVirConnection *conn) g_str_equal, NULL, g_object_unref); + priv->networks = g_hash_table_new_full(g_str_hash, + g_str_equal, + NULL, + g_object_unref); } @@ -668,6 +673,11 @@ void gvir_connection_close(GVirConnection *conn) priv->interfaces = NULL; } + if (priv->networks) { + g_hash_table_unref(priv->networks); + priv->networks = NULL; + } + if (priv->conn) { virConnectDomainEventDeregister(priv->conn, domain_event_cb); virConnectClose(priv->conn); @@ -1686,6 +1696,251 @@ GVirInterface *gvir_connection_find_interface_by_mac(GVirConnection *conn, } /** + * gvir_connection_fetch_networks: + * @conn: a #GVirConnection + * @cancellable: (allow-none)(transfer none): cancellation object + */ +gboolean gvir_connection_fetch_networks(GVirConnection *conn, + GCancellable *cancellable, + GError **err) +{ + GVirConnectionPrivate *priv; + GHashTable *networks; + virNetworkPtr *vnetworks = NULL; + gint nnetworks = 0; + gboolean ret = FALSE; + gint i; + virConnectPtr vconn = NULL; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); + g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable), + FALSE); + g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE); + + priv = conn->priv; + g_mutex_lock(priv->lock); + if (!priv->conn) { + g_set_error_literal(err, 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; + + nnetworks = virConnectListAllNetworks(vconn, &vnetworks, 0); + if (nnetworks < 0) { + gvir_set_error(err, GVIR_CONNECTION_ERROR, + 0, + _("Failed to fetch list of networks")); + goto cleanup; + } + + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + networks = g_hash_table_new_full(g_str_hash, + g_str_equal, + NULL, + g_object_unref); + + for (i = 0 ; i < nnetworks; i++) { + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + GVirNetwork *network; + + network = GVIR_NETWORK(g_object_new(GVIR_TYPE_NETWORK, + "handle", vnetworks[i], + NULL)); + g_hash_table_insert(networks, + (gpointer)gvir_network_get_uuid(network), + network); + } + + g_mutex_lock(priv->lock); + if (priv->networks) + g_hash_table_unref(priv->networks); + priv->networks = networks; + g_mutex_unlock(priv->lock); + + ret = TRUE; + +cleanup: + if (nnetworks > 0) { + for (i = 0 ; i < nnetworks; i++) + virNetworkFree(vnetworks[i]); + free(vnetworks); + } + if (vconn != NULL) + virConnectClose(vconn); + return ret; +} + +static void +gvir_connection_fetch_networks_helper(GTask *res, + gpointer object, + gpointer task_data G_GNUC_UNUSED, + GCancellable *cancellable) +{ + GVirConnection *conn = GVIR_CONNECTION(object); + GError *err = NULL; + + if (!gvir_connection_fetch_networks(conn, cancellable, &err)) + g_task_return_error(res, err); +} + +/** + * gvir_connection_fetch_networks_async: + * @conn: a #GVirConnection + * @cancellable: (allow-none)(transfer none): cancellation object + * @callback: (scope async): completion callback + * @user_data: (closure): opaque data for callback + */ +void gvir_connection_fetch_networks_async(GVirConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *res; + + g_return_if_fail(GVIR_IS_CONNECTION(conn)); + g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); + + res = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(res, + gvir_connection_fetch_networks_async); + g_task_run_in_thread(res, + gvir_connection_fetch_networks_helper); + g_object_unref(res); +} + +/** + * gvir_connection_fetch_networks_finish: + * @conn: a #GVirConnection + * @result: (transfer none): async method result + * @err: return location for any errors + */ +gboolean gvir_connection_fetch_networks_finish(GVirConnection *conn, + GAsyncResult *result, + GError **err) +{ + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE); + g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)), + FALSE); + + return g_task_propagate_boolean(G_TASK(result), err); +} + +/** + * gvir_connection_get_networks: + * @conn: a #GVirConnection + * + * Gets a list of all the network networks available through @conn. + * + * Return value: (element-type LibvirtGObject.Network) (transfer full): List + * of #GVirNetwork. The returned list should be freed with g_list_free(), + * after its elements have been unreffed with g_object_unref(). + */ +GList *gvir_connection_get_networks(GVirConnection *conn) +{ + GVirConnectionPrivate *priv; + GList *networks = NULL; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + if (priv->networks != NULL) { + networks = g_hash_table_get_values(priv->networks); + g_list_foreach(networks, gvir_domain_ref, NULL); + } + g_mutex_unlock(priv->lock); + + return networks; +} + +/** + * gvir_connection_get_network: + * @conn: a #GVirConnection + * + * Get a particular network which has UUID @uuid. + * + * Return value: (transfer full): A new reference to a #GVirNetwork, or NULL if + * no network exists with UUID @uuid. The returned object must be unreffed using + * g_object_unref() once used. + */ +GVirNetwork *gvir_connection_get_network(GVirConnection *conn, + const gchar *uuid) +{ + GVirConnectionPrivate *priv; + GVirNetwork *network; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + g_return_val_if_fail(uuid != NULL, NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + network = g_hash_table_lookup(priv->networks, uuid); + if (network) + g_object_ref(network); + g_mutex_unlock(priv->lock); + + return network; +} + +/** + * gvir_connection_find_network_by_name: + * @conn: a #GVirConnection + * + * Get a particular network which has name @name. + * + * Return value: (transfer full): A new reference to a #GVirNetwork, or NULL if + * no network exists with name @name. The returned object must be unreffed using + * g_object_unref() once used. + */ +GVirNetwork *gvir_connection_find_network_by_name(GVirConnection *conn, + const gchar *name) +{ + GVirConnectionPrivate *priv; + GHashTableIter iter; + gpointer key, value; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + g_return_val_if_fail(name != NULL, NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + g_hash_table_iter_init(&iter, priv->networks); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + GVirNetwork *network = value; + const gchar *thisname = gvir_network_get_name(network); + + if (thisname == NULL) + continue; + + if (strcmp(thisname, name) == 0) { + g_object_ref(network); + g_mutex_unlock(priv->lock); + return network; + } + } + g_mutex_unlock(priv->lock); + + return NULL; +} + +/** * gvir_connection_create_storage_pool: * @conn: a #GVirConnection on which to create the pool * @conf: the configuration for the new storage pool diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h index 0c22a58..f3d2cb8 100644 --- a/libvirt-gobject/libvirt-gobject-connection.h +++ b/libvirt-gobject/libvirt-gobject-connection.h @@ -160,14 +160,23 @@ GVirInterface *gvir_connection_get_interface(GVirConnection *conn, GVirInterface *gvir_connection_find_interface_by_mac(GVirConnection *conn, const gchar *macaddr); -#if 0 +gboolean gvir_connection_fetch_networks(GVirConnection *conn, + GCancellable *cancellable, + GError **err); +void gvir_connection_fetch_networks_async(GVirConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean gvir_connection_fetch_networks_finish(GVirConnection *conn, + GAsyncResult *result, + GError **err); GList *gvir_connection_get_networks(GVirConnection *conn); GVirNetwork *gvir_connection_get_network(GVirConnection *conn, const gchar *uuid); GVirNetwork *gvir_connection_find_network_by_name(GVirConnection *conn, const gchar *name); - +#if 0 GList *gvir_connection_get_network_filters(GVirConnection *conn); GVirNetworkFilter *gvir_connection_get_network_filter(GVirConnection *conn, const gchar *uuid); diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 1effcda..88ca271 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -276,9 +276,15 @@ LIBVIRT_GOBJECT_0.2.2 { gvir_connection_fetch_interfaces; gvir_connection_fetch_interfaces_async; gvir_connection_fetch_interfaces_finish; + gvir_connection_fetch_networks; + gvir_connection_fetch_networks_async; + gvir_connection_fetch_networks_finish; gvir_connection_find_interface_by_mac; + gvir_connection_find_network_by_name; gvir_connection_get_interface; gvir_connection_get_interfaces; + gvir_connection_get_network; + gvir_connection_get_networks; gvir_interface_get_mac; } LIBVIRT_GOBJECT_0.2.1; -- 2.4.3

--- libvirt-gobject/Makefile.am | 5 +- .../libvirt-gobject-network-dhcp-lease-private.h | 34 +++ .../libvirt-gobject-network-dhcp-lease.c | 252 +++++++++++++++++++++ .../libvirt-gobject-network-dhcp-lease.h | 85 +++++++ libvirt-gobject/libvirt-gobject.h | 1 + libvirt-gobject/libvirt-gobject.sym | 13 ++ 6 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h create mode 100644 libvirt-gobject/libvirt-gobject-network-dhcp-lease.c create mode 100644 libvirt-gobject/libvirt-gobject-network-dhcp-lease.h diff --git a/libvirt-gobject/Makefile.am b/libvirt-gobject/Makefile.am index 7163c7d..8464f04 100644 --- a/libvirt-gobject/Makefile.am +++ b/libvirt-gobject/Makefile.am @@ -13,6 +13,7 @@ GOBJECT_HEADER_FILES = \ libvirt-gobject-domain.h \ libvirt-gobject-interface.h \ libvirt-gobject-network.h \ + libvirt-gobject-network-dhcp-lease.h \ libvirt-gobject-network-filter.h \ libvirt-gobject-node-device.h \ libvirt-gobject-secret.h \ @@ -22,7 +23,8 @@ GOBJECT_HEADER_FILES = \ libvirt-gobject-connection.h \ libvirt-gobject-manager.h noinst_HEADERS = \ - libvirt-gobject-storage-pool-private.h + libvirt-gobject-storage-pool-private.h \ + libvirt-gobject-network-dhcp-lease-private.h GOBJECT_SOURCE_FILES = \ libvirt-gobject-main.c \ libvirt-gobject-domain-snapshot.c \ @@ -32,6 +34,7 @@ GOBJECT_SOURCE_FILES = \ libvirt-gobject-domain.c \ libvirt-gobject-interface.c \ libvirt-gobject-network.c \ + libvirt-gobject-network-dhcp-lease.c \ libvirt-gobject-network-filter.c \ libvirt-gobject-node-device.c \ libvirt-gobject-secret.c \ diff --git a/libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h b/libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h new file mode 100644 index 0000000..eaf6c2f --- /dev/null +++ b/libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h @@ -0,0 +1,34 @@ +/* + * libvirt-gobject-network-dhcp-lease-private.h: libvirt gobject integration + * + * Copyright (C) 2010-2011 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * + * 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, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_PRIVATE_H__ +#define __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_PRIVATE_H__ + +G_BEGIN_DECLS + +GVirNetworkDHCPLease *gvir_network_dhcp_lease_new(virNetworkDHCPLeasePtr handle); + +G_END_DECLS + +#endif /* __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_PRIVATE_H__ */ diff --git a/libvirt-gobject/libvirt-gobject-network-dhcp-lease.c b/libvirt-gobject/libvirt-gobject-network-dhcp-lease.c new file mode 100644 index 0000000..b284453 --- /dev/null +++ b/libvirt-gobject/libvirt-gobject-network-dhcp-lease.c @@ -0,0 +1,252 @@ +/* + * libvirt-gobject-network-dhcp-lease.c: libvirt glib integration + * + * Copyright (C) 2008 Daniel P. Berrange + * Copyright (C) 2015 Red Hat, Inc. + * + * 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, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#include <libvirt/virterror.h> +#include <string.h> + +#include "libvirt-glib/libvirt-glib.h" +#include "libvirt-gobject/libvirt-gobject.h" +#include "libvirt-gobject-compat.h" +#include "libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h" + +#define GVIR_NETWORK_DHCP_LEASE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_NETWORK_DHCP_LEASE, GVirNetworkDHCPLeasePrivate)) + +struct _GVirNetworkDHCPLeasePrivate +{ + virNetworkDHCPLeasePtr handle; +}; + +G_DEFINE_TYPE(GVirNetworkDHCPLease, gvir_network_dhcp_lease, G_TYPE_OBJECT); + +enum { + PROP_0, + PROP_HANDLE, +}; + +static void gvir_network_dhcp_lease_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GVirNetworkDHCPLease *lease = GVIR_NETWORK_DHCP_LEASE(object); + GVirNetworkDHCPLeasePrivate *priv = lease->priv; + + switch (prop_id) { + case PROP_HANDLE: + g_value_set_pointer(value, priv->handle); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + +static void gvir_network_dhcp_lease_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GVirNetworkDHCPLease *lease = GVIR_NETWORK_DHCP_LEASE(object); + GVirNetworkDHCPLeasePrivate *priv = lease->priv; + + switch (prop_id) { + case PROP_HANDLE: + if (priv->handle) + virNetworkDHCPLeaseFree(priv->handle); + priv->handle = g_value_get_pointer(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + + +static void gvir_network_dhcp_lease_finalize(GObject *object) +{ + GVirNetworkDHCPLease *lease = GVIR_NETWORK_DHCP_LEASE(object); + GVirNetworkDHCPLeasePrivate *priv = lease->priv; + + g_debug("Finalize GVirNetworkDHCPLease=%p", lease); + + virNetworkDHCPLeaseFree(priv->handle); + + G_OBJECT_CLASS(gvir_network_dhcp_lease_parent_class)->finalize(object); +} + +static void gvir_network_dhcp_lease_class_init(GVirNetworkDHCPLeaseClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gvir_network_dhcp_lease_finalize; + object_class->get_property = gvir_network_dhcp_lease_get_property; + object_class->set_property = gvir_network_dhcp_lease_set_property; + + g_object_class_install_property(object_class, + PROP_HANDLE, + g_param_spec_pointer("handle", + "Handle", + "The lease handle", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_PRIVATE | + G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private(klass, sizeof(GVirNetworkDHCPLeasePrivate)); +} + + +static void gvir_network_dhcp_lease_init(GVirNetworkDHCPLease *lease) +{ + g_debug("Init GVirNetworkDHCPLease=%p", lease); + + lease->priv = GVIR_NETWORK_DHCP_LEASE_GET_PRIVATE(lease); +} + +GVirNetworkDHCPLease *gvir_network_dhcp_lease_new(virNetworkDHCPLeasePtr handle) +{ + return g_object_new(GVIR_TYPE_NETWORK_DHCP_LEASE, + "handle", handle, + NULL); +} + +/** + * gvir_network_dhcp_lease_get_iface: + * @lease: the lease + * + * Returns: (transfer none): The network interface name. + */ +const gchar *gvir_network_dhcp_lease_get_iface(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->iface; +} + +/** + * gvir_network_dhcp_lease_get_expirytime: + * @lease: the lease + * + * Returns: The expiry time of this lease, as seconds since epoch. + */ +gint64 gvir_network_dhcp_lease_get_expirytime(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), -1); + + return lease->priv->handle->expirytime; +} + +/** + * gvir_network_dhcp_lease_get_ip_type: + * @lease: the lease + * + * Returns: The type of IP, see %GVirIPAddrType for possible values. + */ +gint gvir_network_dhcp_lease_get_ip_type(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), -1); + + return lease->priv->handle->type; +} + +/** + * gvir_network_dhcp_lease_get_mac: + * @lease: the lease + * + * Returns: (transfer none): The MAC address. + */ +const gchar *gvir_network_dhcp_lease_get_mac(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->mac; +} + +/** + * gvir_network_dhcp_lease_get_iaid: + * @lease: the lease + * + * Returns: (transfer none): The IAID. + */ +const gchar *gvir_network_dhcp_lease_get_iaid(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->iaid; +} + +/** + * gvir_network_dhcp_lease_get_ip: + * @lease: the lease + * + * Returns: (transfer none): The IP address. + */ +const gchar *gvir_network_dhcp_lease_get_ip(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->ipaddr; +} + +/** + * gvir_network_dhcp_lease_get_prefix: + * @lease: the lease + * + * Returns: The number of network address bits in the IP address. + */ +guint gvir_network_dhcp_lease_get_prefix(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), 0); + + return lease->priv->handle->prefix; +} + +/** + * gvir_network_dhcp_lease_get_hostname: + * @lease: the lease + * + * Returns: (transfer none): The hostname. + */ +const gchar *gvir_network_dhcp_lease_get_hostname(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->hostname; +} + +/** + * gvir_network_dhcp_lease_get_clientid: + * @lease: the lease + * + * Returns: (transfer none): The client ID or DUID. + */ +const gchar *gvir_network_dhcp_lease_get_clientid(GVirNetworkDHCPLease *lease) +{ + g_return_val_if_fail(GVIR_IS_NETWORK_DHCP_LEASE(lease), NULL); + + return lease->priv->handle->clientid; +} diff --git a/libvirt-gobject/libvirt-gobject-network-dhcp-lease.h b/libvirt-gobject/libvirt-gobject-network-dhcp-lease.h new file mode 100644 index 0000000..83f7da9 --- /dev/null +++ b/libvirt-gobject/libvirt-gobject-network-dhcp-lease.h @@ -0,0 +1,85 @@ +/* + * libvirt-gobject-network-dhcp-lease.h: libvirt gobject integration + * + * Copyright (C) 2010-2011 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * + * 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, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Daniel P. Berrange <berrange@redhat.com> + */ + +#if !defined(__LIBVIRT_GOBJECT_H__) && !defined(LIBVIRT_GOBJECT_BUILD) +#error "Only <libvirt-gobject/libvirt-gobject.h> can be included directly." +#endif + +#ifndef __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_H__ +#define __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_H__ + +G_BEGIN_DECLS + +/** + * GVirIPAddrType: + * @GVIR_IP_ADDR_TYPE_IPV4: IPv4 Address. + * @GVIR_IP_ADDR_TYPE_IPV6: IPv6 Address. + */ +typedef enum { + GVIR_IP_ADDR_TYPE_IPV4 = 0, + GVIR_IP_ADDR_TYPE_IPV6 = 1 +} GVirIPAddrType; + +#define GVIR_TYPE_NETWORK_DHCP_LEASE (gvir_network_dhcp_lease_get_type ()) +#define GVIR_NETWORK_DHCP_LEASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_TYPE_NETWORK_DHCP_LEASE, GVirNetworkDHCPLease)) +#define GVIR_NETWORK_DHCP_LEASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_TYPE_NETWORK_DHCP_LEASE, GVirNetworkDHCPLeaseClass)) +#define GVIR_IS_NETWORK_DHCP_LEASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_TYPE_NETWORK_DHCP_LEASE)) +#define GVIR_IS_NETWORK_DHCP_LEASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_TYPE_NETWORK_DHCP_LEASE)) +#define GVIR_NETWORK_DHCP_LEASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_TYPE_NETWORK_DHCP_LEASE, GVirNetworkDHCPLeaseClass)) + +typedef struct _GVirNetworkDHCPLease GVirNetworkDHCPLease; +typedef struct _GVirNetworkDHCPLeasePrivate GVirNetworkDHCPLeasePrivate; +typedef struct _GVirNetworkDHCPLeaseClass GVirNetworkDHCPLeaseClass; + +struct _GVirNetworkDHCPLease +{ + GObject parent; + + GVirNetworkDHCPLeasePrivate *priv; + + /* Do not add fields to this struct */ +}; + +struct _GVirNetworkDHCPLeaseClass +{ + GObjectClass parent_class; + + gpointer padding[7]; +}; + +GType gvir_network_dhcp_lease_get_type(void); + +const gchar *gvir_network_dhcp_lease_get_iface(GVirNetworkDHCPLease *lease); +gint64 gvir_network_dhcp_lease_get_expirytime(GVirNetworkDHCPLease *lease); +gint gvir_network_dhcp_lease_get_ip_type(GVirNetworkDHCPLease *lease); +const gchar *gvir_network_dhcp_lease_get_mac(GVirNetworkDHCPLease *lease); +const gchar *gvir_network_dhcp_lease_get_iaid(GVirNetworkDHCPLease *lease); +const gchar *gvir_network_dhcp_lease_get_ip(GVirNetworkDHCPLease *lease); +guint gvir_network_dhcp_lease_get_prefix(GVirNetworkDHCPLease *lease); +const gchar *gvir_network_dhcp_lease_get_hostname(GVirNetworkDHCPLease *lease); +const gchar *gvir_network_dhcp_lease_get_clientid(GVirNetworkDHCPLease *lease); + +G_END_DECLS + +#endif /* __LIBVIRT_GOBJECT_NETWORK_DHCP_LEASE_H__ */ diff --git a/libvirt-gobject/libvirt-gobject.h b/libvirt-gobject/libvirt-gobject.h index 2b95070..d542482 100644 --- a/libvirt-gobject/libvirt-gobject.h +++ b/libvirt-gobject/libvirt-gobject.h @@ -37,6 +37,7 @@ #include <libvirt-gobject/libvirt-gobject-domain.h> #include <libvirt-gobject/libvirt-gobject-interface.h> #include <libvirt-gobject/libvirt-gobject-network.h> +#include <libvirt-gobject/libvirt-gobject-network-dhcp-lease.h> #include <libvirt-gobject/libvirt-gobject-network-filter.h> #include <libvirt-gobject/libvirt-gobject-node-device.h> #include <libvirt-gobject/libvirt-gobject-secret.h> diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index 88ca271..d345813 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -287,6 +287,19 @@ LIBVIRT_GOBJECT_0.2.2 { gvir_connection_get_networks; gvir_interface_get_mac; + + gvir_ip_addr_type_get_type; + + gvir_network_dhcp_lease_get_clientid; + gvir_network_dhcp_lease_get_expirytime; + gvir_network_dhcp_lease_get_hostname; + gvir_network_dhcp_lease_get_iaid; + gvir_network_dhcp_lease_get_iface; + gvir_network_dhcp_lease_get_ip; + gvir_network_dhcp_lease_get_ip_type; + gvir_network_dhcp_lease_get_mac; + gvir_network_dhcp_lease_get_prefix; + gvir_network_dhcp_lease_get_type; } LIBVIRT_GOBJECT_0.2.1; # .... define new API here using predicted next version number .... -- 2.4.3

--- libvirt-gobject/libvirt-gobject-network.c | 54 +++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-network.h | 4 +++ libvirt-gobject/libvirt-gobject.sym | 2 ++ 3 files changed, 60 insertions(+) diff --git a/libvirt-gobject/libvirt-gobject-network.c b/libvirt-gobject/libvirt-gobject-network.c index b1b38a0..b29be36 100644 --- a/libvirt-gobject/libvirt-gobject-network.c +++ b/libvirt-gobject/libvirt-gobject-network.c @@ -29,6 +29,7 @@ #include "libvirt-glib/libvirt-glib.h" #include "libvirt-gobject/libvirt-gobject.h" #include "libvirt-gobject-compat.h" +#include "libvirt-gobject/libvirt-gobject-network-dhcp-lease-private.h" #define GVIR_NETWORK_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_NETWORK, GVirNetworkPrivate)) @@ -224,3 +225,56 @@ GVirConfigNetwork *gvir_network_get_config(GVirNetwork *network, free(xml); return conf; } + +/** + * gvir_network_get_dhcp_leases: + * @network: the network + * @mac: (allow-none): The optional ASCII formatted MAC address of an interface + * @flags: placeholder for flags, pass 0 + * + * @err: Place-holder for possible errors + * + * This function fetches leases info of guests in the specified network. If the + * optional parameter @mac is specified, the returned list will contain only + * lease info about a specific guest interface with @mac. There can be multiple + * leases for a single @mac because this API supports DHCPv6 too. + * + * Returns: (element-type LibvirtGObject.NetworkDHCPLease) (transfer full): the + * list of network leases. Each object in the returned list should be unreffed + * with g_object_unref() and the list itself using g_list_free, when no longer + * needed. + */ +GList *gvir_network_get_dhcp_leases(GVirNetwork *network, + const char* mac, + guint flags, + GError **err) +{ + virNetworkDHCPLeasePtr *leases; + GList *ret = NULL; + int num_leases, i; + + g_return_val_if_fail(GVIR_IS_NETWORK(network), NULL); + g_return_val_if_fail(err == NULL || *err == NULL, NULL); + + num_leases = virNetworkGetDHCPLeases(network->priv->handle, mac, &leases, flags); + if (num_leases < 0) { + gvir_set_error_literal(err, GVIR_NETWORK_ERROR, + 0, + "Unable to get network DHCP leases"); + return NULL; + } + + if (num_leases == 0) + return NULL; + + for (i = 0; i < num_leases; i++) { + GVirNetworkDHCPLease *lease; + + lease = gvir_network_dhcp_lease_new(leases[i]); + ret = g_list_prepend(ret, lease); + } + ret = g_list_reverse(ret); + free(leases); + + return ret; +} diff --git a/libvirt-gobject/libvirt-gobject-network.h b/libvirt-gobject/libvirt-gobject-network.h index 9f746c0..5617ed6 100644 --- a/libvirt-gobject/libvirt-gobject-network.h +++ b/libvirt-gobject/libvirt-gobject-network.h @@ -71,6 +71,10 @@ const gchar *gvir_network_get_uuid(GVirNetwork *network); GVirConfigNetwork *gvir_network_get_config(GVirNetwork *network, guint flags, GError **err); +GList *gvir_network_get_dhcp_leases(GVirNetwork *network, + const char* mac, + guint flags, + GError **err); G_END_DECLS diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym index d345813..13f35e5 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -300,6 +300,8 @@ LIBVIRT_GOBJECT_0.2.2 { gvir_network_dhcp_lease_get_mac; gvir_network_dhcp_lease_get_prefix; gvir_network_dhcp_lease_get_type; + + gvir_network_get_dhcp_leases; } LIBVIRT_GOBJECT_0.2.1; # .... define new API here using predicted next version number .... -- 2.4.3
participants (1)
-
Zeeshan Ali (Khattak)