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