[libvirt] [libvirt-glib PATCHv5 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..e088427 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++) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - virStoragePoolPtr vpool; + for (i = 0 ; i < npools; i++) { 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

A virConnect reference is leaked in error cases. This patch moves the unref after the label we jump to on errors, to avoid this leak. --- 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 e088427..02eef7b 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 | 280 +++++++++++++-------------- 1 file changed, 136 insertions(+), 144 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 02eef7b..5b3a7bc 100644 --- a/libvirt-gobject/libvirt-gobject-connection.c +++ b/libvirt-gobject/libvirt-gobject-connection.c @@ -497,17 +497,18 @@ gboolean gvir_connection_open_read_only(GVirConnection *conn, } static void -gvir_connection_open_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_open_helper(GTask *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); } @@ -523,20 +524,20 @@ void gvir_connection_open_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; 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); - g_object_unref(res); + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_open_async); + g_task_run_in_thread(task, + gvir_connection_open_helper); + g_object_unref(task); } @@ -550,28 +551,28 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_open_async, 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 *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); } @@ -587,20 +588,20 @@ void gvir_connection_open_read_only_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; 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); - g_object_unref(res); + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_open_read_only_async); + g_task_run_in_thread(task, + gvir_connection_open_read_only_helper); + g_object_unref(task); } @@ -614,14 +615,13 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_open_read_only_async, 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 +852,18 @@ cleanup: } static void -gvir_connection_fetch_domains_helper(GSimpleAsyncResult *res, - GObject *object, +gvir_connection_fetch_domains_helper(GTask *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); } @@ -878,20 +879,20 @@ void gvir_connection_fetch_domains_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; 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); - g_object_unref(res); + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_fetch_domains_async); + g_task_run_in_thread(task, + gvir_connection_fetch_domains_helper); + g_object_unref(task); } /** @@ -904,28 +905,28 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_fetch_domains_async, 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 *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); } /** @@ -940,20 +941,20 @@ void gvir_connection_fetch_storage_pools_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; 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); - g_object_unref(res); + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_fetch_storage_pools_async); + g_task_run_in_thread(task, + gvir_connection_fetch_pools_helper); + g_object_unref(task); } /** @@ -966,14 +967,13 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_fetch_storage_pools_async, 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 +1568,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 *task, + gpointer object, + gpointer task_data G_GNUC_UNUSED, GCancellable *cancellable G_GNUC_UNUSED) { GVirConnection *conn = GVIR_CONNECTION(object); @@ -1578,12 +1579,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(task, err); return; } - g_simple_async_result_set_op_res_gpointer(res, caps, g_object_unref); + g_task_return_pointer(task, caps, g_object_unref); } /** @@ -1598,20 +1599,20 @@ void gvir_connection_get_capabilities_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; 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); - g_object_unref(res); + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_get_capabilities_async); + g_task_run_in_thread(task, + gvir_connection_get_capabilities_helper); + g_object_unref(task); } /** @@ -1628,19 +1629,14 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_get_capabilities_async, + FALSE); - 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 +1704,25 @@ static void restore_domain_from_file_data_free(RestoreDomainFromFileData *data) static void gvir_connection_restore_domain_from_file_helper - (GSimpleAsyncResult *res, - GObject *object, + (GTask *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); } /** @@ -1747,7 +1746,7 @@ gvir_connection_restore_domain_from_file_async(GVirConnection *conn, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; RestoreDomainFromFileData *data; g_return_if_fail(GVIR_IS_CONNECTION(conn)); @@ -1760,23 +1759,20 @@ 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, + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, 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_simple_async_result_run_in_thread - (res, - gvir_connection_restore_domain_from_file_helper, - G_PRIORITY_DEFAULT, - cancellable); - - g_object_unref(res); + g_task_set_task_data(task, + data, + (GDestroyNotify)restore_domain_from_file_data_free); + + g_task_run_in_thread(task, + gvir_connection_restore_domain_from_file_helper); + + g_object_unref(task); } /** @@ -1795,15 +1791,11 @@ 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_restore_domain_from_file_async, + 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 | 270 +++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-connection.h | 13 +- libvirt-gobject/libvirt-gobject.sym | 7 + 3 files changed, 288 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 5b3a7bc..7d28178 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); } @@ -668,6 +673,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); @@ -1443,6 +1453,266 @@ 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 afterwards + * 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++) { + GVirInterface *iface; + + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + 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 *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); +} + + +/** + * 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 *task; + + g_return_if_fail(GVIR_IS_CONNECTION(conn)); + g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); + + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_fetch_interfaces_async); + g_task_run_in_thread(task, + gvir_connection_fetch_interfaces_helper); + g_object_unref(task); +} + +/** + * 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_fetch_interfaces_async, + FALSE); + + return g_task_propagate_boolean(G_TASK(result), err); +} + +/** + * gvir_connection_get_interfaces: + * @conn: a #GVirConnection + * + * Get 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 + * @name: interface name to lookup + * + * 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 + * @mac: MAC address to lookup + * + * 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 | 262 +++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-connection.h | 13 +- libvirt-gobject/libvirt-gobject.sym | 6 + 3 files changed, 279 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 7d28178..9e7bb68 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); } @@ -678,6 +683,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); @@ -1713,6 +1723,258 @@ 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++) { + GVirNetwork *network; + + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + 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 *task, + 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(task, err); + else + g_task_return_boolean(task, TRUE); +} + +/** + * 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 *task; + + g_return_if_fail(GVIR_IS_CONNECTION(conn)); + g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable)); + + task = g_task_new(G_OBJECT(conn), + cancellable, + callback, + user_data); + g_task_set_source_tag(task, + gvir_connection_fetch_networks_async); + g_task_run_in_thread(task, + gvir_connection_fetch_networks_helper); + g_object_unref(task); +} + +/** + * 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); + g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) == + gvir_connection_fetch_networks_async, + FALSE); + + return g_task_propagate_boolean(G_TASK(result), err); +} + +/** + * gvir_connection_get_networks: + * @conn: a #GVirConnection + * + * Get 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 + * @uuid: UUID of the network to lookup + * + * 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 + * @name: name of the network to search for + * + * 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..6ac3c14 --- /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_expiry_time: + * @lease: the lease + * + * Returns: The expiry time of this lease, as seconds since epoch. + */ +gint64 gvir_network_dhcp_lease_get_expiry_time(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_client_id: + * @lease: the lease + * + * Returns: (transfer none): The client ID or DUID. + */ +const gchar *gvir_network_dhcp_lease_get_client_id(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..a011d65 --- /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_expiry_time(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_client_id(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..dfd858a 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_client_id; + gvir_network_dhcp_lease_get_expiry_time; + 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 | 55 +++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-network.h | 4 +++ libvirt-gobject/libvirt-gobject.sym | 2 ++ 3 files changed, 61 insertions(+) diff --git a/libvirt-gobject/libvirt-gobject-network.c b/libvirt-gobject/libvirt-gobject-network.c index b1b38a0..2a7bed6 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,57 @@ 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, must be 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); + g_return_val_if_fail(flags != 0, 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 dfd858a..ca89a45 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

On Tue, Jul 07, 2015 at 03:17:37PM +0100, Zeeshan Ali (Khattak) wrote:
--- libvirt-gobject/libvirt-gobject-network.c | 55 +++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-network.h | 4 +++ libvirt-gobject/libvirt-gobject.sym | 2 ++ 3 files changed, 61 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-network.c b/libvirt-gobject/libvirt-gobject-network.c index b1b38a0..2a7bed6 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,57 @@ 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, must be 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); + g_return_val_if_fail(flags != 0, 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;
Could be return g_list_reverse(ret); and drop the ret = g_list_reverse(ret); above, but both are good for me. Christophe

On Tue, Jul 7, 2015 at 3:17 PM, Zeeshan Ali (Khattak) <zeeshanak@gnome.org> wrote:
--- libvirt-gobject/libvirt-gobject-network.c | 55 +++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-network.h | 4 +++ libvirt-gobject/libvirt-gobject.sym | 2 ++ 3 files changed, 61 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-network.c b/libvirt-gobject/libvirt-gobject-network.c index b1b38a0..2a7bed6 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,57 @@ 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, must be 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); + g_return_val_if_fail(flags != 0, NULL);
Oh, this should be flags == 0. I'll fix before pushing. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

Hi all, Christophe pointed out that this and the previous patch binds API that was added an year ago: commit: 03e0e79e07622496522609741734c2fdcacb5bf2 Author: Nehal J Wani <nehaljw.kkd1@gmail.com> Date: Tue Jun 24 02:31:49 2014 +0530 net-dhcp-leases: Implement the public APIs Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. --------------- While I think 1 year old is pretty old enough to justify bumping the dep to that version, Christophe thinks its still too soon. I'd hate to go through the trouble of adding ugly #ifdef around these new API but if others (I guess mainly Dan?) agree with Christophe, I can do that. On Tue, Jul 7, 2015 at 4:26 PM, Zeeshan Ali (Khattak) <zeeshanak@gnome.org> wrote:
On Tue, Jul 7, 2015 at 3:17 PM, Zeeshan Ali (Khattak) <zeeshanak@gnome.org> wrote:
--- libvirt-gobject/libvirt-gobject-network.c | 55 +++++++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-network.h | 4 +++ libvirt-gobject/libvirt-gobject.sym | 2 ++ 3 files changed, 61 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-network.c b/libvirt-gobject/libvirt-gobject-network.c index b1b38a0..2a7bed6 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,57 @@ 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, must be 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); + g_return_val_if_fail(flags != 0, NULL);
Oh, this should be flags == 0. I'll fix before pushing.
-- Regards,
Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/
-- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Tue, Jul 07, 2015 at 05:27:39PM +0100, Zeeshan Ali (Khattak) wrote:
Hi all,
Christophe pointed out that this and the previous patch binds API that was added an year ago:
commit: 03e0e79e07622496522609741734c2fdcacb5bf2 Author: Nehal J Wani <nehaljw.kkd1@gmail.com> Date: Tue Jun 24 02:31:49 2014 +0530
net-dhcp-leases: Implement the public APIs
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. ---------------
While I think 1 year old is pretty old enough to justify bumping the dep to that version, Christophe thinks its still too soon. I'd hate to go through the trouble of adding ugly #ifdef around these new API but if others (I guess mainly Dan?) agree with Christophe, I can do that.
1 year being old/not old is not a very useful/convincing argument. What is more interesting is what (supported) distros are shipping (f21, el7, oldest ubuntu LTS shipping libvirt-glib, debian, ...). I'd tend to favour #ifdefs though unless this gets very invasive/ugly ;) Christophe

On Wed, Jul 8, 2015 at 11:11 AM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Tue, Jul 07, 2015 at 05:27:39PM +0100, Zeeshan Ali (Khattak) wrote:
Hi all,
Christophe pointed out that this and the previous patch binds API that was added an year ago:
commit: 03e0e79e07622496522609741734c2fdcacb5bf2 Author: Nehal J Wani <nehaljw.kkd1@gmail.com> Date: Tue Jun 24 02:31:49 2014 +0530
net-dhcp-leases: Implement the public APIs
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. ---------------
While I think 1 year old is pretty old enough to justify bumping the dep to that version, Christophe thinks its still too soon. I'd hate to go through the trouble of adding ugly #ifdef around these new API but if others (I guess mainly Dan?) agree with Christophe, I can do that.
1 year being old/not old is not a very useful/convincing argument. What is more interesting is what (supported) distros are shipping (f21, el7, oldest ubuntu LTS shipping libvirt-glib, debian, ...).
For the record, I don't think upstream development should depend on when distros decided to upgrade packages and their release cycles. The important thing is for us to give them enough time and IMO 1 year is plenty of time. Also keeping in mind that it makes very little sense to upgrade libvirt-glib and not libvirt since libvirt doesn't break any ABI/API.
I'd tend to favour #ifdefs though unless this gets very invasive/ugly ;)
Well we don't agree and that's why I brought it up here. :) -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Wed, Jul 08, 2015 at 01:13:09PM +0100, Zeeshan Ali (Khattak) wrote:
On Wed, Jul 8, 2015 at 11:11 AM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Tue, Jul 07, 2015 at 05:27:39PM +0100, Zeeshan Ali (Khattak) wrote:
Hi all,
Christophe pointed out that this and the previous patch binds API that was added an year ago:
commit: 03e0e79e07622496522609741734c2fdcacb5bf2 Author: Nehal J Wani <nehaljw.kkd1@gmail.com> Date: Tue Jun 24 02:31:49 2014 +0530
net-dhcp-leases: Implement the public APIs
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. ---------------
While I think 1 year old is pretty old enough to justify bumping the dep to that version, Christophe thinks its still too soon. I'd hate to go through the trouble of adding ugly #ifdef around these new API but if others (I guess mainly Dan?) agree with Christophe, I can do that.
1 year being old/not old is not a very useful/convincing argument. What is more interesting is what (supported) distros are shipping (f21, el7, oldest ubuntu LTS shipping libvirt-glib, debian, ...).
For the record, I don't think upstream development should depend on when distros decided to upgrade packages and their release cycles.
Ok, I'll call you next time I need to get something newish to work with the RHEL6 glib ;)
Also keeping in mind that it makes very little sense to upgrade libvirt-glib and not libvirt since libvirt doesn't break any ABI/API.
Generally speaking, there could be security issues, critical bugs in Boxes which require a libvirt-glib update to be fixed, ... where upgrading just libvirt-glib would be much more convenient than upgrading the whole stack. So all in all, this is just a tradeoff to make between making our life easier, and (potentially) making distributions life easier. Which can be a very uninteresting discussion to have if they all have a new enough libvirt, hence my question about what they have.. Christophe

On Wed, Jul 8, 2015 at 2:27 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Wed, Jul 08, 2015 at 01:13:09PM +0100, Zeeshan Ali (Khattak) wrote:
On Wed, Jul 8, 2015 at 11:11 AM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Tue, Jul 07, 2015 at 05:27:39PM +0100, Zeeshan Ali (Khattak) wrote:
Hi all,
Christophe pointed out that this and the previous patch binds API that was added an year ago:
commit: 03e0e79e07622496522609741734c2fdcacb5bf2 Author: Nehal J Wani <nehaljw.kkd1@gmail.com> Date: Tue Jun 24 02:31:49 2014 +0530
net-dhcp-leases: Implement the public APIs
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. ---------------
While I think 1 year old is pretty old enough to justify bumping the dep to that version, Christophe thinks its still too soon. I'd hate to go through the trouble of adding ugly #ifdef around these new API but if others (I guess mainly Dan?) agree with Christophe, I can do that.
1 year being old/not old is not a very useful/convincing argument. What is more interesting is what (supported) distros are shipping (f21, el7, oldest ubuntu LTS shipping libvirt-glib, debian, ...).
For the record, I don't think upstream development should depend on when distros decided to upgrade packages and their release cycles.
Ok, I'll call you next time I need to get something newish to work with the RHEL6 glib ;)
glib is much lower level and libvirt-glib isn't about binding it so its very different case.
Also keeping in mind that it makes very little sense to upgrade libvirt-glib and not libvirt since libvirt doesn't break any ABI/API.
Generally speaking, there could be security issues, critical bugs in Boxes which require a libvirt-glib update to be fixed,
That is why we roll out bug fix releases to stable releases and try our best not to bump any deps while doing so. If there is a bug fix in a newer release thats not made available for an older release, distros are extremely unlikely to simply upgrade to latest release but rather back port those fixes since new release would also bring along new features (and therefore bugs).
... where upgrading just libvirt-glib would be much more convenient than upgrading the whole stack. So all in all, this is just a tradeoff to make between making our life easier, and (potentially) making distributions life easier.
Surely we need to meet somewhere in between. If Ubuntu or Debian would for example not upgrade their libvirt for many years to come, would we keep wasting our time on adding ugly hacks upstream for them? -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Wed, Jul 08, 2015 at 03:37:43PM +0100, Zeeshan Ali (Khattak) wrote:
Also keeping in mind that it makes very little sense to upgrade libvirt-glib and not libvirt since libvirt doesn't break any ABI/API.
Generally speaking, there could be security issues, critical bugs in Boxes which require a libvirt-glib update to be fixed,
That is why we roll out bug fix releases to stable releases and try our best not to bump any deps while doing so.
So far, we haven't done that for libvirt-glib, just incremental releases with bugfixes and new features...
... where upgrading just libvirt-glib would be much more convenient than upgrading the whole stack. So all in all, this is just a tradeoff to make between making our life easier, and (potentially) making distributions life easier.
Surely we need to meet somewhere in between. If Ubuntu or Debian would for example not upgrade their libvirt for many years to come, would we keep wasting our time on adding ugly hacks upstream for them?
So far, you keep saying "let's bump the req!", but you haven't brought anything forward to support that "ugly hack" statement in this specific case, nor any hard data regarding which distros could be impacted by a req bump. I'll stop this discussion until you bring some concrete datapoints to the table. Christophe

On Wed, Jul 8, 2015 at 3:42 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Wed, Jul 08, 2015 at 03:37:43PM +0100, Zeeshan Ali (Khattak) wrote:
Also keeping in mind that it makes very little sense to upgrade libvirt-glib and not libvirt since libvirt doesn't break any ABI/API.
Generally speaking, there could be security issues, critical bugs in Boxes which require a libvirt-glib update to be fixed,
That is why we roll out bug fix releases to stable releases and try our best not to bump any deps while doing so.
So far, we haven't done that for libvirt-glib, just incremental releases with bugfixes and new features...
Only because we never really needed to.
... where upgrading just libvirt-glib would be much more convenient than upgrading the whole stack. So all in all, this is just a tradeoff to make between making our life easier, and (potentially) making distributions life easier.
Surely we need to meet somewhere in between. If Ubuntu or Debian would for example not upgrade their libvirt for many years to come, would we keep wasting our time on adding ugly hacks upstream for them?
So far, you keep saying "let's bump the req!",
I'm sorry if that is all you read in my emails, cause I've been trying my best to have a rational discussion here.
but you haven't brought anything forward to support that "ugly hack" statement in this specific case,
#ifdef based solution is going to be ugly, surely you know that. I never made any claims about the magnitude of ugliness, I always want to avoid ugly hacks whenever possible.
nor any hard data regarding which distros could be impacted by a req bump. I'll stop this discussion until you bring some concrete datapoints to the table.
Fair enough! The main point of this discussion was not to convince you but rather to get a third opinion. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Wed, Jul 08, 2015 at 07:00:36PM +0100, Zeeshan Ali (Khattak) wrote:
On Wed, Jul 8, 2015 at 3:42 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
but you haven't brought anything forward to support that "ugly hack" statement in this specific case,
#ifdef based solution is going to be ugly, surely you know that. I never made any claims about the magnitude of ugliness, I always want to avoid ugly hacks whenever possible.
If it just requires 2 or 3 #ifdef, adding them and forgetting they existed would have been faster than this thread ;)
nor any hard data regarding which distros could be impacted by a req bump. I'll stop this discussion until you bring some concrete datapoints to the table.
Fair enough! The main point of this discussion was not to convince you but rather to get a third opinion.
Honestly, this is a very weird attitude, rather than trying to come with hard facts, you prefer having some kind of poll and make an arbitary uninformed decision. Christophe

On Thu, Jul 9, 2015 at 8:05 AM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Wed, Jul 08, 2015 at 07:00:36PM +0100, Zeeshan Ali (Khattak) wrote:
On Wed, Jul 8, 2015 at 3:42 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
but you haven't brought anything forward to support that "ugly hack" statement in this specific case,
#ifdef based solution is going to be ugly, surely you know that. I never made any claims about the magnitude of ugliness, I always want to avoid ugly hacks whenever possible.
If it just requires 2 or 3 #ifdef, adding them and forgetting they existed would have been faster than this thread ;)
I agree but I want to clarify how we intend to proceed about this in future. I'm fine with 2 or 3 but with this kind of extremely strict definition of "too new libvirt dep", we'd need to keep on doing this and before you know it, we'll have lots of these ugly hacks.
nor any hard data regarding which distros could be impacted by a req bump. I'll stop this discussion until you bring some concrete datapoints to the table.
Fair enough! The main point of this discussion was not to convince you but rather to get a third opinion.
Honestly, this is a very weird attitude, rather than trying to come with hard facts, you prefer having some kind of poll and make an arbitary uninformed decision.
I regret having to resort to some sort of poll as well but this is not a purely objective discussion. I did present arguments but you maintain that I did not. So let's leave at that, shall we? I'll just proceed as Dan tell me to. It's his project in the end. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Thu, Jul 09, 2015 at 12:42:23PM +0100, Zeeshan Ali (Khattak) wrote:
Honestly, this is a very weird attitude, rather than trying to come with hard facts, you prefer having some kind of poll and make an arbitary uninformed decision.
I regret having to resort to some sort of poll as well but this is not a purely objective discussion. I did present arguments but you maintain that I did not. So let's leave at that, shall we?
Unless I missed important things, your arguments boiled down to "one year is old enough, we should not care about distros". I've asked what the impact would be on distros, no answer so far. I've asked what the impact would be in terms of #ifdef ugliness, no answer so far. Quite hard to make a decision with so few details ;)
I'll just proceed as Dan tell me to. It's his project in the end.
danpb is away for a while as I understand it, and my feeling is that we could resolve this on our own if you were at least trying to give more details about the various alternatives. Christophe

On Thu, Jul 9, 2015 at 12:56 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Thu, Jul 09, 2015 at 12:42:23PM +0100, Zeeshan Ali (Khattak) wrote:
Honestly, this is a very weird attitude, rather than trying to come with hard facts, you prefer having some kind of poll and make an arbitary uninformed decision.
I regret having to resort to some sort of poll as well but this is not a purely objective discussion. I did present arguments but you maintain that I did not. So let's leave at that, shall we?
Unless I missed important things, your arguments boiled down to "one year is old enough, we should not care about distros".
It's very hard to discuss if you over-exagerate my opinions to make them sound bad. I'm did not say we should not care about distros but rather that 1 year is plenty of care.
I've asked what the impact would be on distros, no answer so far.
The answer was that 1 year of grace time is enough and we shouldn't need to be bound by release cycles and packaging of individual distros. Also I pointed out the fact that it does not (in practical terms) make any sense to only upgrade to latest libvirt-glib but wanting to stay with an year old libvirt.
I've asked what the impact would be in terms of #ifdef ugliness, no answer so far.
The answer was that magnitude of ugliness is irrelevant. Surely you know that this is not anything objective. To me a single #ifdef is ugly enough but seems it's not for you so how do you expect either of us to convince each other with arguments? If you really need something more concrete, I see at least 12 #ifdefs needed. Pretty ugly for my taste at least.
Quite hard to make a decision with so few details ;)
All needed "details" are avaiable and it's only a matter of taste and amount of care we want to give to distros. Both are subjective matters.
I'll just proceed as Dan tell me to. It's his project in the end.
danpb is away for a while as I understand it, and my feeling is that we could resolve this on our own if you were at least trying to give more details about the various alternatives.
I don't know many alternatives. It's either bumping the dep or adding ugly #ifdef based solution. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Thu, Jul 09, 2015 at 02:41:45PM +0100, Zeeshan Ali (Khattak) wrote:
The answer was that magnitude of ugliness is irrelevant. Surely you know that this is not anything objective. To me a single #ifdef is ugly enough but seems it's not for you so how do you expect either of us to convince each other with arguments? If you really need something more concrete, I see at least 12 #ifdefs needed. Pretty ugly for my taste at least.
I'm just trying to have a discussion about something concrete. If just one #ifdef was needed, I guess you'll bear with me if I try to convince you to go this way, with 12 #ifdef, you've got a more understandable standing in opposing this.
Quite hard to make a decision with so few details ;)
All needed "details" are avaiable and it's only a matter of taste and amount of care we want to give to distros. Both are subjective matters.
Same deal as with the amount of #ifdef needed, if only EL6 has a too old libvirt, then you are in a much better position to convince me than if Debian stable and latest Ubuntu (making things up) have a too old libvirt. Ie let's know the exact tradeoffs we are discussing here from a technical point of view, maybe we won't have to agree to disagree and look for a tie breaker ;) Christophe

On Thu, Jul 9, 2015 at 3:01 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Thu, Jul 09, 2015 at 02:41:45PM +0100, Zeeshan Ali (Khattak) wrote:
The answer was that magnitude of ugliness is irrelevant. Surely you know that this is not anything objective. To me a single #ifdef is ugly enough but seems it's not for you so how do you expect either of us to convince each other with arguments? If you really need something more concrete, I see at least 12 #ifdefs needed. Pretty ugly for my taste at least.
I'm just trying to have a discussion about something concrete. If just one #ifdef was needed, I guess you'll bear with me if I try to convince you to go this way, with 12 #ifdef, you've got a more understandable standing in opposing this.
Quite hard to make a decision with so few details ;)
All needed "details" are avaiable and it's only a matter of taste and amount of care we want to give to distros. Both are subjective matters.
Same deal as with the amount of #ifdef needed, if only EL6 has a too old libvirt, then you are in a much better position to convince me than if Debian stable and latest Ubuntu (making things up) have a too old libvirt. Ie let's know the exact tradeoffs we are discussing here from a technical point of view, maybe we won't have to agree to disagree and look for a tie breaker ;)
I really don't see the point of evaluating possible but unlinkely[1] impact on any distro. As I said, we give distros enough time and that should be more than enough upstream could do. i-e these exact details are irrelevant to me. Since they are very relevant to you, I'd suggest you do the research and then let me know which solution you want and I will implement that. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/ [1] As I already mentioned already, it's very unlikely that any distro would want to upgrade Boxes and libvirt-glib to latest version but not want to update to even an year older libvirt.

On Fri, Jul 10, 2015 at 04:43:15PM +0100, Zeeshan Ali (Khattak) wrote:
I really don't see the point of evaluating possible but unlinkely[1] impact on any distro. As I said, we give distros enough time and that should be more than enough upstream could do. i-e these exact details are irrelevant to me. Since they are very relevant to you, I'd suggest you do the research and then let me know which solution you want and I will implement that.
Patches of yours broke the build, you have a strong opinion on the right way to fix it, in such situations I usually go the extra mile to convince others that it's the best way :) That's why I'm a bit surprised this drags for so long with no real attempt at finding some common ground. Christophe

On Fri, Jul 10, 2015 at 5:04 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Fri, Jul 10, 2015 at 04:43:15PM +0100, Zeeshan Ali (Khattak) wrote:
I really don't see the point of evaluating possible but unlinkely[1] impact on any distro. As I said, we give distros enough time and that should be more than enough upstream could do. i-e these exact details are irrelevant to me. Since they are very relevant to you, I'd suggest you do the research and then let me know which solution you want and I will implement that.
Patches of yours broke the build, you have a strong opinion on the right way to fix it, in such situations I usually go the extra mile to convince others that it's the best way :) That's why I'm a bit surprised this drags for so long with no real attempt at finding some common ground.
I gave you an easy way out of this dragging discussion and even promised to implement either of the solutions you want me to. You're still not happy so I'll just bump the dependencies now. Feel free to implement ugly hack solution. I'm out here.. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Mon, Jul 13, 2015 at 02:45:21PM +0100, Zeeshan Ali (Khattak) wrote:
On Fri, Jul 10, 2015 at 5:04 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
Patches of yours broke the build, you have a strong opinion on the right way to fix it, in such situations I usually go the extra mile to convince others that it's the best way :) That's why I'm a bit surprised this drags for so long with no real attempt at finding some common ground.
I gave you an easy way out of this dragging discussion and even promised to implement either of the solutions you want me to. You're still not happy so I'll just bump the dependencies now. Feel free to implement ugly hack solution. I'm out here..
Thanks a lot for pushing an unreviewed patch after not wanting to go through proper patch discussion (ie do a bit of research in order to address the concerns which were raised rather than making up excuses for not doing it), that's appreciated! After 10 minutes looking around, Ubuntu 14.04 LTS has libvirt 1.2.2 and SLES 12 has 1.2.5, both have long support cycles and a too old libvirt. Apart from these, supported Fedoras, latest Debian stable, opensuse 13.2 and EL7.1 all have new enough libvirt. With this data in mind, and unless people from the impacted distros speak up, raising the requirement is probably reasonable enough. Christophe

On Thu, Jul 16, 2015 at 10:11 AM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Mon, Jul 13, 2015 at 02:45:21PM +0100, Zeeshan Ali (Khattak) wrote:
On Fri, Jul 10, 2015 at 5:04 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
Patches of yours broke the build, you have a strong opinion on the right way to fix it, in such situations I usually go the extra mile to convince others that it's the best way :) That's why I'm a bit surprised this drags for so long with no real attempt at finding some common ground.
I gave you an easy way out of this dragging discussion and even promised to implement either of the solutions you want me to. You're still not happy so I'll just bump the dependencies now. Feel free to implement ugly hack solution. I'm out here..
Thanks a lot for pushing an unreviewed patch after not wanting to go through proper patch discussion (ie do a bit of research in order to address the concerns which were raised rather than making up excuses for not doing it), that's appreciated!
I did address all your arguments and you still insist I did not. I have no idea how I can possibly fix that. FWIW, the patch I pushed only fixes a bug: libvirt-glib was requiring a version of libvirt that it wasn't checking for in configure stage.
After 10 minutes looking around, Ubuntu 14.04 LTS has libvirt 1.2.2 and SLES 12 has 1.2.5, both have long support cycles and a too old libvirt. Apart from these, supported Fedoras, latest Debian stable, opensuse 13.2 and EL7.1 all have new enough libvirt. With this data in mind, and unless people from the impacted distros speak up, raising the requirement is probably reasonable enough.
And all that data is completely irrelevant for the reason I mentioned again and again. Please point to at least one actual example of any distro wanting to upgrade libvirt-glib to latest while wanting to keep an year old release of libvirt and you'll have a point. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Mon, Jul 20, 2015 at 05:24:30PM +0100, Zeeshan Ali (Khattak) wrote:
And all that data is completely irrelevant for the reason I mentioned again and again.
Now that we have the data, and that it goes your way, yes you can say it's irrelevant ;) What if instead, it turned out only f22 was shipping a new enough libvirt? I would have reverted your patch and added some #ifdef.
Please point to at least one actual example of any distro wanting to upgrade libvirt-glib to latest while wanting to keep an year old release of libvirt and you'll have a point.
The point of looking up that information was actually to be able to make an informed decision as to whether there may be distros wanting to do that or not. Which is why I was asking for that data, and I now feel more confident that this is indeed not going to be an issue. It really took 10 minutes to gather, much less time than arguing that this information is not needed ;) Christophe

On Mon, Jul 20, 2015 at 6:32 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
On Mon, Jul 20, 2015 at 05:24:30PM +0100, Zeeshan Ali (Khattak) wrote:
And all that data is completely irrelevant for the reason I mentioned again and again.
Now that we have the data, and that it goes your way, yes you can say it's irrelevant ;)
Not at all, I didn't even care to see if it goes "my way" or not. It's completely irrelevant and I'm getting tired of pointing out the very obvious reason why that is the case.
What if instead, it turned out only f22 was shipping a new enough libvirt? I would have reverted your patch and added some #ifdef.
That would have been fine by me, as already explained. What it did boil down in the end to was you being way too caring about downstream than me and hence ugly solutions are acceptable to you. I really don't see us able to change each other's mind on that and hence the reason I wanted a vote rather in the first place to avoid this discussion. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/

On Thu, Jul 16, 2015 at 11:11:01AM +0200, Christophe Fergeau wrote:
On Mon, Jul 13, 2015 at 02:45:21PM +0100, Zeeshan Ali (Khattak) wrote:
On Fri, Jul 10, 2015 at 5:04 PM, Christophe Fergeau <cfergeau@redhat.com> wrote:
Patches of yours broke the build, you have a strong opinion on the right way to fix it, in such situations I usually go the extra mile to convince others that it's the best way :) That's why I'm a bit surprised this drags for so long with no real attempt at finding some common ground.
I gave you an easy way out of this dragging discussion and even promised to implement either of the solutions you want me to. You're still not happy so I'll just bump the dependencies now. Feel free to implement ugly hack solution. I'm out here..
Thanks a lot for pushing an unreviewed patch after not wanting to go through proper patch discussion (ie do a bit of research in order to address the concerns which were raised rather than making up excuses for not doing it), that's appreciated!
After 10 minutes looking around, Ubuntu 14.04 LTS has libvirt 1.2.2 and SLES 12 has 1.2.5, both have long support cycles and a too old libvirt. Apart from these, supported Fedoras, latest Debian stable, opensuse 13.2 and EL7.1 all have new enough libvirt. With this data in mind, and unless people from the impacted distros speak up, raising the requirement is probably reasonable enough.
So for the record, my viewpoint is the time since the feature was released is pretty irrelevant. The important thing is what distros have the neccessary versions, as that directly impacts how easy it is for app developers to consume new libvirt-glib releases. If there is a tradeoff between ugly #ifdefs and app developers not being able to use libvirt-glib, then my preference is towards #ifdefs as that only inconveniences a handful of people (ie us) in a pretty limited manner, as opposed to inconveniencing potentially 100's or 1000's of potential developers. In the core libvirt we take this to the extreme and currently aim to build on *every* Linux distro since RHEL-5 vintage. In the libvirt-glib I think we have more flexibility, mostly because you really want to have gobject introspection, so that immediately rules out anything older than RHEL-7 vintage as an interesting distro target. In general though I'd still be against increasing the min required libvirt beyond the version in RHEL-7.0 and other comparable age distros. Since we've already increased the dep in this case though, I won't object / ask for revert. In future though, we should avoid increasing the min required dep on libvirt or glib beyond what's available in the distros mentioned above, because as I mention above it removes a small burden from us maintainers in favour of a large burden on downstream users/developers which is not a net benefit IMHO. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Hey, A 'changes since v4' section would have been nice ACK series. Christophe On Tue, Jul 07, 2015 at 03:17:31PM +0100, Zeeshan Ali (Khattak) wrote:
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..e088427 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++) { - if (g_cancellable_set_error_if_cancelled(cancellable, err)) - goto cleanup; - - virStoragePoolPtr vpool; + for (i = 0 ; i < npools; i++) { 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
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
participants (3)
-
Christophe Fergeau
-
Daniel P. Berrange
-
Zeeshan Ali (Khattak)