[libvirt] [libvirt-glib PATCHv4 4/7] gobject: Add API to query connection interfaces
Christophe Fergeau
cfergeau at redhat.com
Tue Jul 7 08:56:41 UTC 2015
On Wed, Jul 01, 2015 at 09:40:48PM +0100, Zeeshan Ali (Khattak) wrote:
> 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
s/on/about ?
> + * managed by connection @conn on host machine. Use
> + * #gvir_connection_get_interfaces or #gvir_connection_get_interface after
> + * wards to query the fetched interfaces.
'afterwards' is a single word
> + *
> + * 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;
> +
I'd put this before the cancellable check.
> + iface = GVIR_INTERFACE(g_object_new(GVIR_TYPE_INTERFACE,
> + "handle", ifaces[i],
> + NULL));
> +
parameter alignment is off here
> + 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;
GTask *task; would be great
> +
> + 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);
Same comment as in the other patch regarding unneeded
g_task_set_source_tag() (or adding a check in gvir_connection_fetch_interfaces_helper)
> + 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.
I think most other documentation blocks in this patch use "Get a list"
rather than "Gets a list"
> + *
> + * 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;
>
All in all looks good apart from these minor comments, ACK.
> --
> 2.4.3
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150707/aa4bcff7/attachment-0001.sig>
More information about the libvir-list
mailing list