[libvirt] [libvirt-glib PATCHv4 4/7] gobject: Add API to query connection interfaces

Zeeshan Ali (Khattak) zeeshanak at gnome.org
Wed Jul 1 20:40:48 UTC 2015


Add API to query network interfaces from a connection.
---
 libvirt-gobject/libvirt-gobject-connection.c | 265 +++++++++++++++++++++++++++
 libvirt-gobject/libvirt-gobject-connection.h |  13 +-
 libvirt-gobject/libvirt-gobject.sym          |   7 +
 3 files changed, 283 insertions(+), 2 deletions(-)

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




More information about the libvir-list mailing list