Add API to query networks from a connection. --- libvirt-gobject/libvirt-gobject-connection.c | 226 +++++++++++++++++++++++++++ libvirt-gobject/libvirt-gobject-connection.h | 6 +- libvirt-gobject/libvirt-gobject.sym | 4 + 3 files changed, 234 insertions(+), 2 deletions(-) diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c index 20c43fc..eea2eed 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); @@ -1814,6 +1824,222 @@ 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; + gchar **inactive = NULL; + gint ninactive = 0; + gchar **active = NULL; + gint nactive = 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), + 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; + + active = fetch_list(vconn, + "Networks", + virConnectNumOfNetworks, + virConnectListNetworks, + cancellable, + &nactive, + &lerr); + if (lerr) { + g_propagate_error(err, lerr); + lerr = NULL; + goto cleanup; + } + + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + inactive = fetch_list(vconn, + "Networks", + virConnectNumOfDefinedNetworks, + virConnectListDefinedNetworks, + cancellable, + &ninactive, + &lerr); + if (lerr) { + g_propagate_error(err, lerr); + lerr = NULL; + goto cleanup; + } + + networks = 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; + + virNetworkPtr vnetwork; + GVirNetwork *network; + + vnetwork = virNetworkLookupByName(vconn, active[i]); + if (!vnetwork) + continue; + + network = GVIR_NETWORK(g_object_new(GVIR_TYPE_NETWORK, + "handle", vnetwork, + NULL)); + virNetworkFree(vnetwork); + + g_hash_table_insert(networks, + (gpointer)gvir_network_get_uuid(network), + network); + } + + for (i = 0 ; i < ninactive ; i++) { + if (g_cancellable_set_error_if_cancelled(cancellable, err)) + goto cleanup; + + virNetworkPtr vnetwork; + GVirNetwork *network; + + vnetwork = virNetworkLookupByName(vconn, inactive[i]); + if (!vnetwork) + continue; + + network = GVIR_NETWORK(g_object_new(GVIR_TYPE_NETWORK, + "handle", vnetwork, + NULL)); + virNetworkFree(vnetwork); + + 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; + virConnectClose(vconn); + g_mutex_unlock(priv->lock); + + 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); + return ret; +} + +/** + * gvir_connection_get_networks: + * @conn: a #GVirConnection + * + * Gets a list of all the network networks available through @conn. + * + * Return value: (element-type LibvirtGObject.Network) (transfer full): List + * of #GVirNetwork. The returned list should be freed with g_list_free(), + * after its elements have been unreffed with g_object_unref(). + */ +GList *gvir_connection_get_networks(GVirConnection *conn) +{ + GVirConnectionPrivate *priv; + GList *networks = NULL; + + g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL); + + priv = conn->priv; + g_mutex_lock(priv->lock); + if (priv->networks != NULL) { + networks = g_hash_table_get_values(priv->networks); + g_list_foreach(networks, gvir_domain_ref, NULL); + } + g_mutex_unlock(priv->lock); + + return networks; +} + +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; +} + +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 77079b6..89b062b 100644 --- a/libvirt-gobject/libvirt-gobject-connection.h +++ b/libvirt-gobject/libvirt-gobject-connection.h @@ -153,14 +153,16 @@ 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); 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 b7ce1d5..085c410 100644 --- a/libvirt-gobject/libvirt-gobject.sym +++ b/libvirt-gobject/libvirt-gobject.sym @@ -274,9 +274,13 @@ LIBVIRT_GOBJECT_0.2.1 { LIBVIRT_GOBJECT_0.2.2 { global: gvir_connection_fetch_interfaces; + gvir_connection_fetch_networks; 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.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list