Blame libvirt-gobject/libvirt-gobject-connection.c

Packit a07778
/*
Packit a07778
 * libvirt-gobject-connection.c: libvirt glib integration
Packit a07778
 *
Packit a07778
 * Copyright (C) 2008 Daniel P. Berrange
Packit a07778
 * Copyright (C) 2010-2011 Red Hat, Inc.
Packit a07778
 *
Packit a07778
 * This library is free software; you can redistribute it and/or
Packit a07778
 * modify it under the terms of the GNU Lesser General Public
Packit a07778
 * License as published by the Free Software Foundation; either
Packit a07778
 * version 2.1 of the License, or (at your option) any later version.
Packit a07778
 *
Packit a07778
 * This library is distributed in the hope that it will be useful,
Packit a07778
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a07778
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a07778
 * Lesser General Public License for more details.
Packit a07778
 *
Packit a07778
 * You should have received a copy of the GNU Lesser General Public
Packit a07778
 * License along with this library. If not, see
Packit a07778
 * <http://www.gnu.org/licenses/>.
Packit a07778
 *
Packit a07778
 * Author: Daniel P. Berrange <berrange@redhat.com>
Packit a07778
 */
Packit a07778
Packit a07778
#include <config.h>
Packit a07778
Packit a07778
#include <libvirt/libvirt.h>
Packit a07778
#include <string.h>
Packit a07778
Packit a07778
#include <glib/gi18n-lib.h>
Packit a07778
Packit a07778
#include "libvirt-glib/libvirt-glib.h"
Packit a07778
#include "libvirt-gobject/libvirt-gobject.h"
Packit a07778
#include "libvirt-gobject-compat.h"
Packit a07778
Packit a07778
#define GVIR_CONNECTION_GET_PRIVATE(obj)                         \
Packit a07778
        (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_CONNECTION, GVirConnectionPrivate))
Packit a07778
Packit a07778
struct _GVirConnectionPrivate
Packit a07778
{
Packit a07778
    GMutex *lock;
Packit a07778
    gchar *uri;
Packit a07778
    virConnectPtr conn;
Packit a07778
    gboolean read_only;
Packit a07778
Packit a07778
    GHashTable *domains;
Packit a07778
    GHashTable *pools;
Packit a07778
    GHashTable *interfaces;
Packit a07778
    GHashTable *networks;
Packit a07778
};
Packit a07778
Packit a07778
G_DEFINE_TYPE_WITH_PRIVATE(GVirConnection, gvir_connection, G_TYPE_OBJECT);
Packit a07778
Packit a07778
Packit a07778
enum {
Packit a07778
    PROP_0,
Packit a07778
    PROP_URI,
Packit a07778
    PROP_HANDLE,
Packit a07778
};
Packit a07778
Packit a07778
enum {
Packit a07778
    VIR_CONNECTION_OPENED,
Packit a07778
    VIR_CONNECTION_CLOSED,
Packit a07778
    VIR_DOMAIN_ADDED,
Packit a07778
    VIR_DOMAIN_REMOVED,
Packit a07778
    LAST_SIGNAL
Packit a07778
};
Packit a07778
Packit a07778
static gint signals[LAST_SIGNAL];
Packit a07778
Packit a07778
#define GVIR_CONNECTION_ERROR gvir_connection_error_quark()
Packit a07778
Packit a07778
static GQuark
Packit a07778
gvir_connection_error_quark(void)
Packit a07778
{
Packit a07778
    return g_quark_from_static_string("gvir-connection");
Packit a07778
}
Packit a07778
Packit a07778
static GVirNodeInfo *
Packit a07778
gvir_node_info_copy(GVirNodeInfo *info)
Packit a07778
{
Packit a07778
    return g_slice_dup(GVirNodeInfo, info);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_node_info_free(GVirNodeInfo *info)
Packit a07778
{
Packit a07778
    g_slice_free(GVirNodeInfo, info);
Packit a07778
}
Packit a07778
Packit a07778
G_DEFINE_BOXED_TYPE(GVirNodeInfo, gvir_node_info,
Packit a07778
                    gvir_node_info_copy, gvir_node_info_free)
Packit a07778
Packit a07778
static void gvir_connection_get_property(GObject *object,
Packit a07778
                                         guint prop_id,
Packit a07778
                                         GValue *value,
Packit a07778
                                         GParamSpec *pspec)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GVirConnectionPrivate *priv = conn->priv;
Packit a07778
Packit a07778
    switch (prop_id) {
Packit a07778
    case PROP_URI:
Packit a07778
        g_value_set_string(value, priv->uri);
Packit a07778
        break;
Packit a07778
    case PROP_HANDLE:
Packit a07778
        g_value_set_boxed(value, priv->conn);
Packit a07778
        break;
Packit a07778
Packit a07778
    default:
Packit a07778
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
Packit a07778
    }
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_connection_set_property(GObject *object,
Packit a07778
                                         guint prop_id,
Packit a07778
                                         const GValue *value,
Packit a07778
                                         GParamSpec *pspec)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GVirConnectionPrivate *priv = conn->priv;
Packit a07778
Packit a07778
    switch (prop_id) {
Packit a07778
    case PROP_URI:
Packit a07778
        g_free(priv->uri);
Packit a07778
        priv->uri = g_value_dup_string(value);
Packit a07778
        break;
Packit a07778
Packit a07778
    case PROP_HANDLE:
Packit a07778
        if (priv->conn)
Packit a07778
            virConnectClose(priv->conn);
Packit a07778
        priv->conn = g_value_dup_boxed(value);
Packit a07778
        break;
Packit a07778
Packit a07778
    default:
Packit a07778
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
Packit a07778
    }
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_connection_finalize(GObject *object)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GVirConnectionPrivate *priv = conn->priv;
Packit a07778
Packit a07778
    if (gvir_connection_is_open(conn))
Packit a07778
        gvir_connection_close(conn);
Packit a07778
Packit a07778
    g_mutex_free(priv->lock);
Packit a07778
    g_free(priv->uri);
Packit a07778
Packit a07778
    G_OBJECT_CLASS(gvir_connection_parent_class)->finalize(object);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static GVirStream* gvir_connection_stream_new(GVirConnection *self G_GNUC_UNUSED,
Packit a07778
                                             gpointer handle)
Packit a07778
{
Packit a07778
    return g_object_new(GVIR_TYPE_STREAM, "handle", handle, NULL);
Packit a07778
}
Packit a07778
Packit a07778
static void gvir_connection_class_init(GVirConnectionClass *klass)
Packit a07778
{
Packit a07778
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
Packit a07778
Packit a07778
    gvir_event_register();
Packit a07778
Packit a07778
    object_class->finalize = gvir_connection_finalize;
Packit a07778
    object_class->get_property = gvir_connection_get_property;
Packit a07778
    object_class->set_property = gvir_connection_set_property;
Packit a07778
Packit a07778
    klass->stream_new = gvir_connection_stream_new;
Packit a07778
Packit a07778
    g_object_class_install_property(object_class,
Packit a07778
                                    PROP_URI,
Packit a07778
                                    g_param_spec_string("uri",
Packit a07778
                                                        "URI",
Packit a07778
                                                        "The connection URI",
Packit a07778
                                                        NULL,
Packit a07778
                                                        G_PARAM_READABLE |
Packit a07778
                                                        G_PARAM_WRITABLE |
Packit a07778
                                                        G_PARAM_CONSTRUCT_ONLY |
Packit a07778
                                                        G_PARAM_STATIC_STRINGS));
Packit a07778
Packit a07778
    g_object_class_install_property(object_class,
Packit a07778
                                    PROP_HANDLE,
Packit a07778
                                    g_param_spec_boxed("handle",
Packit a07778
                                                       "Handle",
Packit a07778
                                                       "The connection handle",
Packit a07778
                                                       GVIR_TYPE_CONNECTION_HANDLE,
Packit a07778
                                                       G_PARAM_READABLE |
Packit a07778
                                                       G_PARAM_WRITABLE |
Packit a07778
                                                       G_PARAM_CONSTRUCT_ONLY |
Packit a07778
                                                       G_PARAM_STATIC_STRINGS));
Packit a07778
Packit a07778
    signals[VIR_CONNECTION_OPENED] = g_signal_new("connection-opened",
Packit a07778
                 G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                 G_SIGNAL_RUN_FIRST,
Packit a07778
                 G_STRUCT_OFFSET(GVirConnectionClass, connection_opened),
Packit a07778
                 NULL, NULL,
Packit a07778
                 g_cclosure_marshal_VOID__VOID,
Packit a07778
                 G_TYPE_NONE,
Packit a07778
                 0);
Packit a07778
Packit a07778
    signals[VIR_CONNECTION_CLOSED] = g_signal_new("connection-closed",
Packit a07778
                 G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                 G_SIGNAL_RUN_FIRST,
Packit a07778
                 G_STRUCT_OFFSET(GVirConnectionClass, connection_closed),
Packit a07778
                 NULL, NULL,
Packit a07778
                 g_cclosure_marshal_VOID__VOID,
Packit a07778
                 G_TYPE_NONE,
Packit a07778
                 0);
Packit a07778
Packit a07778
    signals[VIR_DOMAIN_ADDED] = g_signal_new("domain-added",
Packit a07778
                 G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                 G_SIGNAL_RUN_FIRST,
Packit a07778
                 G_STRUCT_OFFSET(GVirConnectionClass, domain_added),
Packit a07778
                 NULL, NULL,
Packit a07778
                 g_cclosure_marshal_VOID__OBJECT,
Packit a07778
                 G_TYPE_NONE,
Packit a07778
                 1,
Packit a07778
                 GVIR_TYPE_DOMAIN);
Packit a07778
Packit a07778
    signals[VIR_DOMAIN_REMOVED] = g_signal_new("domain-removed",
Packit a07778
                 G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                 G_SIGNAL_RUN_FIRST,
Packit a07778
                 G_STRUCT_OFFSET(GVirConnectionClass, domain_removed),
Packit a07778
                 NULL, NULL,
Packit a07778
                 g_cclosure_marshal_VOID__OBJECT,
Packit a07778
                 G_TYPE_NONE,
Packit a07778
                 1,
Packit a07778
                 GVIR_TYPE_DOMAIN);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_connection_init(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    priv = conn->priv = GVIR_CONNECTION_GET_PRIVATE(conn);
Packit a07778
Packit a07778
    priv->lock = g_mutex_new();
Packit a07778
    priv->domains = g_hash_table_new_full(g_str_hash,
Packit a07778
                                          g_str_equal,
Packit a07778
                                          NULL,
Packit a07778
                                          g_object_unref);
Packit a07778
    priv->pools = g_hash_table_new_full(g_str_hash,
Packit a07778
                                        g_str_equal,
Packit a07778
                                        NULL,
Packit a07778
                                        g_object_unref);
Packit a07778
    priv->interfaces = g_hash_table_new_full(g_str_hash,
Packit a07778
                                             g_str_equal,
Packit a07778
                                             NULL,
Packit a07778
                                             g_object_unref);
Packit a07778
    priv->networks = g_hash_table_new_full(g_str_hash,
Packit a07778
                                           g_str_equal,
Packit a07778
                                           NULL,
Packit a07778
                                           g_object_unref);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
GVirConnection *gvir_connection_new(const char *uri)
Packit a07778
{
Packit a07778
    return GVIR_CONNECTION(g_object_new(GVIR_TYPE_CONNECTION,
Packit a07778
                                         "uri", uri,
Packit a07778
                                         NULL));
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
Packit a07778
                           virDomainPtr dom,
Packit a07778
                           int event,
Packit a07778
                           int detail,
Packit a07778
                           void *opaque)
Packit a07778
{
Packit a07778
    gchar uuid[VIR_UUID_STRING_BUFLEN];
Packit a07778
    GHashTable *doms;
Packit a07778
    GVirConnection *gconn = opaque;
Packit a07778
    GVirDomain *gdom;
Packit a07778
    GVirConnectionPrivate *priv = gconn->priv;
Packit a07778
Packit a07778
    if (virDomainGetUUIDString(dom, uuid) < 0) {
Packit a07778
        gvir_warning("Failed to get domain UUID on %p", dom);
Packit a07778
        return 0;
Packit a07778
    }
Packit a07778
Packit a07778
    g_debug("%s: %s event:%d, detail:%d", G_STRFUNC, uuid, event, detail);
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    doms = g_hash_table_ref(priv->domains);
Packit a07778
    gdom = g_hash_table_lookup(doms, uuid);
Packit a07778
    if (gdom != NULL)
Packit a07778
        g_object_ref(G_OBJECT(gdom));
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    if (gdom == NULL) {
Packit a07778
        gdom = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN, "handle", dom, NULL));
Packit a07778
Packit a07778
        g_mutex_lock(priv->lock);
Packit a07778
        g_hash_table_insert(doms, (gpointer)gvir_domain_get_uuid(gdom),
Packit a07778
                            g_object_ref(G_OBJECT(gdom)));
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
    }
Packit a07778
Packit a07778
    switch (event) {
Packit a07778
        case VIR_DOMAIN_EVENT_DEFINED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_DEFINED_ADDED)
Packit a07778
                g_signal_emit(gconn, signals[VIR_DOMAIN_ADDED], 0, gdom);
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_DEFINED_UPDATED)
Packit a07778
                g_signal_emit_by_name(gdom, "updated");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_UNDEFINED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) {
Packit a07778
                g_mutex_lock(priv->lock);
Packit a07778
                g_hash_table_remove(doms, uuid);
Packit a07778
                g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
                g_signal_emit(gconn, signals[VIR_DOMAIN_REMOVED], 0, gdom);
Packit a07778
            } else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_STARTED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_STARTED_BOOTED) {
Packit a07778
                if (!virDomainIsPersistent(dom))
Packit a07778
                    g_signal_emit(gconn, signals[VIR_DOMAIN_ADDED], 0, gdom);
Packit a07778
                g_signal_emit_by_name(gdom, "started::booted");
Packit a07778
            } else if (detail == VIR_DOMAIN_EVENT_STARTED_MIGRATED)
Packit a07778
                g_signal_emit_by_name(gdom, "started::migrated");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STARTED_RESTORED)
Packit a07778
                g_signal_emit_by_name(gdom, "started::restored");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT)
Packit a07778
                g_signal_emit_by_name(gdom, "started::from-snapshot");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STARTED_WAKEUP)
Packit a07778
                g_signal_emit_by_name(gdom, "started::wakeup");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_SUSPENDED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_SUSPENDED_PAUSED)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::paused");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::migrated");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_SUSPENDED_IOERROR)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::ioerror");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::watchdog");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_SUSPENDED_RESTORED)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::restored");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT)
Packit a07778
                g_signal_emit_by_name(gdom, "suspended::from-snapshot");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_RESUMED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_RESUMED_UNPAUSED)
Packit a07778
                g_signal_emit_by_name(gdom, "resumed::unpaused");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_RESUMED_MIGRATED)
Packit a07778
                g_signal_emit_by_name(gdom, "resumed::migrated");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT)
Packit a07778
                g_signal_emit_by_name(gdom, "resumed::from-snapshot");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_STOPPED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::shutdown");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_DESTROYED)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::destroyed");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_CRASHED)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::crashed");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_MIGRATED)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::migrated");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_SAVED)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::saved");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_FAILED)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::failed");
Packit a07778
            else if (detail == VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT)
Packit a07778
                g_signal_emit_by_name(gdom, "stopped::from-snapshot");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
Packit a07778
            if (virDomainIsPersistent(dom) != 1) {
Packit a07778
                g_mutex_lock(priv->lock);
Packit a07778
                g_hash_table_remove(doms, uuid);
Packit a07778
                g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
                g_signal_emit(gconn, signals[VIR_DOMAIN_REMOVED], 0, gdom);
Packit a07778
            }
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_SHUTDOWN:
Packit a07778
            break;
Packit a07778
Packit a07778
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
Packit a07778
            if (detail == VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY)
Packit a07778
                g_signal_emit_by_name(gdom, "pmsuspended::memory");
Packit a07778
            else
Packit a07778
                g_warn_if_reached();
Packit a07778
            break;
Packit a07778
Packit a07778
        default:
Packit a07778
            g_warn_if_reached();
Packit a07778
    }
Packit a07778
Packit a07778
    g_object_unref(G_OBJECT(gdom));
Packit a07778
    g_hash_table_unref(doms);
Packit a07778
    return 0;
Packit a07778
}
Packit a07778
Packit a07778
static gboolean _gvir_connection_open(GVirConnection *conn,
Packit a07778
                                      gboolean read_only,
Packit a07778
                                      GCancellable *cancellable,
Packit a07778
                                      GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        return FALSE;
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->conn) {
Packit a07778
        g_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                    0,
Packit a07778
                    _("Connection %s is already open"),
Packit a07778
                    priv->uri);
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    if (read_only) {
Packit a07778
        priv->conn = virConnectOpenReadOnly(priv->uri);
Packit a07778
        priv->read_only = TRUE;
Packit a07778
    } else {
Packit a07778
        priv->conn = virConnectOpen(priv->uri);
Packit a07778
    }
Packit a07778
    if (!priv->conn) {
Packit a07778
        gvir_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                       0,
Packit a07778
                       _("Unable to open %s"),
Packit a07778
                       priv->uri);
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    if (!priv->uri) {
Packit a07778
        char *uri = virConnectGetURI(priv->conn);
Packit a07778
        if (!uri) {
Packit a07778
            gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                                   0,
Packit a07778
                                   _("Unable to get connection URI"));
Packit a07778
            virConnectClose(priv->conn);
Packit a07778
            priv->conn = NULL;
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return FALSE;
Packit a07778
        }
Packit a07778
        priv->uri = g_strdup(uri);
Packit a07778
        free(uri);
Packit a07778
    }
Packit a07778
Packit a07778
    if (virConnectDomainEventRegister(priv->conn, domain_event_cb, conn, NULL) == -1)
Packit a07778
        gvir_warning("Failed to register domain events, ignoring");
Packit a07778
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    g_signal_emit(conn, signals[VIR_CONNECTION_OPENED], 0);
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_open:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 */
Packit a07778
gboolean gvir_connection_open(GVirConnection *conn,
Packit a07778
                              GCancellable *cancellable,
Packit a07778
                              GError **err)
Packit a07778
{
Packit a07778
    return _gvir_connection_open(conn, FALSE, cancellable, err);
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_connection_open_read_only(GVirConnection *conn,
Packit a07778
                                        GCancellable *cancellable,
Packit a07778
                                        GError **err)
Packit a07778
{
Packit a07778
    return _gvir_connection_open(conn, TRUE, cancellable, err);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_open_helper(GTask *task,
Packit a07778
                            gpointer object,
Packit a07778
                            gpointer task_data G_GNUC_UNUSED,
Packit a07778
                            GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_open(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_open_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_open_async(GVirConnection *conn,
Packit a07778
                                GCancellable *cancellable,
Packit a07778
                                GAsyncReadyCallback callback,
Packit a07778
                                gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_open_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_open_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_open_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 */
Packit a07778
gboolean gvir_connection_open_finish(GVirConnection *conn,
Packit a07778
                                     GAsyncResult *result,
Packit a07778
                                     GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_open_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_open_read_only_helper(GTask *task,
Packit a07778
                                      gpointer object,
Packit a07778
                                      gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                      GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_open_read_only(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_open_read_only_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_open_read_only_async(GVirConnection *conn,
Packit a07778
                                GCancellable *cancellable,
Packit a07778
                                GAsyncReadyCallback callback,
Packit a07778
                                gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_open_read_only_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_open_read_only_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_open_read_only_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 */
Packit a07778
gboolean gvir_connection_open_read_only_finish(GVirConnection *conn,
Packit a07778
                                               GAsyncResult *result,
Packit a07778
                                               GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_open_read_only_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_connection_is_open(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    gboolean open = TRUE;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (!priv->conn)
Packit a07778
        open = FALSE;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
    return open;
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_connection_is_read_only(GVirConnection *conn)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
Packit a07778
    return conn->priv->read_only;
Packit a07778
}
Packit a07778
Packit a07778
void gvir_connection_close(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
Packit a07778
    g_debug("Close GVirConnection=%p", conn);
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
Packit a07778
    if (priv->domains) {
Packit a07778
        g_hash_table_unref(priv->domains);
Packit a07778
        priv->domains = NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    if (priv->pools) {
Packit a07778
        g_hash_table_unref(priv->pools);
Packit a07778
        priv->pools = NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    if (priv->interfaces) {
Packit a07778
        g_hash_table_unref(priv->interfaces);
Packit a07778
        priv->interfaces = NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    if (priv->networks) {
Packit a07778
        g_hash_table_unref(priv->networks);
Packit a07778
        priv->networks = NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    if (priv->conn) {
Packit a07778
        virConnectDomainEventDeregister(priv->conn, domain_event_cb);
Packit a07778
        virConnectClose(priv->conn);
Packit a07778
        priv->conn = NULL;
Packit a07778
    }
Packit a07778
    /* xxx signals */
Packit a07778
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    g_signal_emit(conn, signals[VIR_CONNECTION_CLOSED], 0);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_domains:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 *
Packit a07778
 * Use this method to fetch all domains managed by connection
Packit a07778
 * @conn. Use e.g. #gvir_connection_find_domain_by_id or
Packit a07778
 * #gvir_connection_get_domain afterwards to query the fetched
Packit a07778
 * domains.
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_domains(GVirConnection *conn,
Packit a07778
                                       GCancellable *cancellable,
Packit a07778
                                       GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTable *doms;
Packit a07778
    virDomainPtr *domains = NULL;
Packit a07778
    gint ndomains = 0;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
    gint i;
Packit a07778
    virConnectPtr vconn = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                            0,
Packit a07778
                            _("Connection is not open"));
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
    vconn = priv->conn;
Packit a07778
    /* Stop another thread closing the connection just at the minute */
Packit a07778
    virConnectRef(vconn);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ndomains = virConnectListAllDomains(vconn, &domains, 0);
Packit a07778
    if (ndomains < 0) {
Packit a07778
        gvir_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                       0,
Packit a07778
                       _("Failed to fetch list of domains"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    doms = g_hash_table_new_full(g_str_hash,
Packit a07778
                                 g_str_equal,
Packit a07778
                                 NULL,
Packit a07778
                                 g_object_unref);
Packit a07778
Packit a07778
    for (i = 0 ; i < ndomains; i++) {
Packit a07778
        GVirDomain *dom;
Packit a07778
Packit a07778
        dom = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN,
Packit a07778
                                       "handle", domains[i],
Packit a07778
                                       NULL));
Packit a07778
Packit a07778
        g_hash_table_insert(doms,
Packit a07778
                            (gpointer)gvir_domain_get_uuid(dom),
Packit a07778
                            dom);
Packit a07778
    }
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->domains)
Packit a07778
        g_hash_table_unref(priv->domains);
Packit a07778
    priv->domains = doms;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
Packit a07778
cleanup:
Packit a07778
    if (ndomains > 0) {
Packit a07778
        for (i = 0 ; i < ndomains; i++)
Packit a07778
            virDomainFree(domains[i]);
Packit a07778
        free(domains);
Packit a07778
    }
Packit a07778
    if (vconn != NULL)
Packit a07778
        virConnectClose(vconn);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_storage_pools:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 *
Packit a07778
 * Use this method to fetch all storage pools managed by connection
Packit a07778
 * @conn. Use e.g. #gvir_connection_find_storage_pool_by_name or
Packit a07778
 * #gvir_connection_get_storage_pools afterwards to query the fetched
Packit a07778
 * pools.
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn,
Packit a07778
                                             GCancellable *cancellable,
Packit a07778
                                             GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTable *pools;
Packit a07778
    virStoragePoolPtr *vpools = NULL;
Packit a07778
    gint npools = 0;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
    gint i;
Packit a07778
    virConnectPtr vconn = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                            0,
Packit a07778
                            _("Connection is not open"));
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
    vconn = priv->conn;
Packit a07778
    /* Stop another thread closing the connection just at the minute */
Packit a07778
    virConnectRef(vconn);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    npools = virConnectListAllStoragePools(vconn, &vpools, 0);
Packit a07778
    if (npools < 0) {
Packit a07778
        gvir_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                       0,
Packit a07778
                       _("Failed to fetch list of pools"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    pools = g_hash_table_new_full(g_str_hash,
Packit a07778
                                  g_str_equal,
Packit a07778
                                  NULL,
Packit a07778
                                  g_object_unref);
Packit a07778
Packit a07778
    for (i = 0 ; i < npools; i++) {
Packit a07778
        GVirStoragePool *pool;
Packit a07778
Packit a07778
        if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
            goto cleanup;
Packit a07778
Packit a07778
        pool = GVIR_STORAGE_POOL(g_object_new(GVIR_TYPE_STORAGE_POOL,
Packit a07778
                                              "handle", vpools[i],
Packit a07778
                                              NULL));
Packit a07778
        g_hash_table_insert(pools,
Packit a07778
                            (gpointer)gvir_storage_pool_get_uuid(pool),
Packit a07778
                            pool);
Packit a07778
    }
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->pools)
Packit a07778
        g_hash_table_unref(priv->pools);
Packit a07778
    priv->pools = pools;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
Packit a07778
cleanup:
Packit a07778
    if (npools > 0) {
Packit a07778
        for (i = 0 ; i < npools; i++)
Packit a07778
            virStoragePoolFree(vpools[i]);
Packit a07778
        free(vpools);
Packit a07778
    }
Packit a07778
    if (vconn != NULL)
Packit a07778
        virConnectClose(vconn);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_fetch_domains_helper(GTask *task,
Packit a07778
                                     gpointer object,
Packit a07778
                                     gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                     GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_fetch_domains(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_domains_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_fetch_domains_async(GVirConnection *conn,
Packit a07778
                                         GCancellable *cancellable,
Packit a07778
                                         GAsyncReadyCallback callback,
Packit a07778
                                         gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_fetch_domains_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_fetch_domains_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_domains_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_domains_finish(GVirConnection *conn,
Packit a07778
                                              GAsyncResult *result,
Packit a07778
                                              GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_fetch_domains_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_fetch_pools_helper(GTask *task,
Packit a07778
                                   gpointer object,
Packit a07778
                                   gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                   GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_fetch_storage_pools(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_storage_pools_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_fetch_storage_pools_async(GVirConnection *conn,
Packit a07778
                                               GCancellable *cancellable,
Packit a07778
                                               GAsyncReadyCallback callback,
Packit a07778
                                               gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_fetch_storage_pools_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_fetch_pools_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_storage_pools_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_storage_pools_finish(GVirConnection *conn,
Packit a07778
                                                    GAsyncResult *result,
Packit a07778
                                                    GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_fetch_storage_pools_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
const gchar *gvir_connection_get_uri(GVirConnection *conn)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    return conn->priv->uri;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_hypervisor_name:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Get name of current hypervisor used.
Packit a07778
 *
Packit a07778
 * Return value: new string that should be freed when no longer needed,
Packit a07778
 * or NULL upon error.
Packit a07778
 */
Packit a07778
gchar *
Packit a07778
gvir_connection_get_hypervisor_name(GVirConnection *conn,
Packit a07778
                                    GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    gchar *ret = NULL;
Packit a07778
    const char *type;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
Packit a07778
                            _("Connection is not opened"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    type = virConnectGetType(priv->conn);
Packit a07778
    if (!type) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
Packit a07778
                               _("Unable to get hypervisor name"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = g_strdup(type);
Packit a07778
Packit a07778
cleanup:
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_version:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Get version of current hypervisor used.
Packit a07778
 *
Packit a07778
 * Return value: version on success, 0 otherwise and @err set.
Packit a07778
 */
Packit a07778
gulong
Packit a07778
gvir_connection_get_version(GVirConnection *conn,
Packit a07778
                            GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    gulong ret = 0;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, 0);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
Packit a07778
                            _("Connection is not opened"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (virConnectGetVersion(priv->conn, &ret) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
Packit a07778
                               _("Unable to get hypervisor version"));
Packit a07778
    }
Packit a07778
Packit a07778
cleanup:
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
static void gvir_domain_ref(gpointer obj, gpointer ignore G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    g_object_ref(obj);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_domains:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 *
Packit a07778
 * Gets a list of the domains available through @conn.
Packit a07778
 *
Packit a07778
 * Return value: (element-type LibvirtGObject.Domain) (transfer full): List
Packit a07778
 * of #GVirDomain. The returned list should be freed with g_list_free(),
Packit a07778
 * after its elements have been unreffed with g_object_unref().
Packit a07778
 */
Packit a07778
GList *gvir_connection_get_domains(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GList *domains = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->domains != NULL) {
Packit a07778
        domains = g_hash_table_get_values(priv->domains);
Packit a07778
        g_list_foreach(domains, gvir_domain_ref, NULL);
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return domains;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_storage_pools:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 *
Packit a07778
 * Gets a list of the storage pools available through @conn.
Packit a07778
 *
Packit a07778
 * Return value: (element-type LibvirtGObject.StoragePool) (transfer full): List
Packit a07778
 * of #GVirStoragePool. The returned list should be freed with
Packit a07778
 * g_list_free(), after its elements have been unreffed with
Packit a07778
 * g_object_unref().
Packit a07778
 */
Packit a07778
GList *gvir_connection_get_storage_pools(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GList *pools = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->pools != NULL) {
Packit a07778
        pools = g_hash_table_get_values(priv->pools);
Packit a07778
        g_list_foreach(pools, gvir_domain_ref, NULL);
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return pools;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_domain:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @uuid: uuid string of the requested domain
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): the #GVirDomain, or NULL. The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomain *gvir_connection_get_domain(GVirConnection *conn,
Packit a07778
                                       const gchar *uuid)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GVirDomain *dom;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(uuid != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    dom = g_hash_table_lookup(priv->domains, uuid);
Packit a07778
    if (dom)
Packit a07778
        g_object_ref(dom);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
    return dom;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_storage_pool:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @uuid: uuid string of the requested storage pool
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): the #GVirStoragePool, or NULL. The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirStoragePool *gvir_connection_get_storage_pool(GVirConnection *conn,
Packit a07778
                                                  const gchar *uuid)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GVirStoragePool *pool;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(uuid != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    pool = g_hash_table_lookup(priv->pools, uuid);
Packit a07778
    if (pool)
Packit a07778
        g_object_ref(pool);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return pool;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_find_domain_by_id:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @id: id of the requested domain
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): the #GVirDomain, or NULL. The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomain *gvir_connection_find_domain_by_id(GVirConnection *conn,
Packit a07778
                                              gint id)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTableIter iter;
Packit a07778
    gpointer key, value;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_iter_init(&iter, priv->domains);
Packit a07778
Packit a07778
    while (g_hash_table_iter_next(&iter, &key, &value)) {
Packit a07778
        GVirDomain *dom = value;
Packit a07778
        gint thisid = gvir_domain_get_id(dom, NULL);
Packit a07778
Packit a07778
        if (thisid == id) {
Packit a07778
            g_object_ref(dom);
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return dom;
Packit a07778
        }
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return NULL;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_find_domain_by_name:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @name: name of the requested domain
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): the #GVirDomain, or NULL. The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomain *gvir_connection_find_domain_by_name(GVirConnection *conn,
Packit a07778
                                                const gchar *name)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTableIter iter;
Packit a07778
    gpointer key, value;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(name != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_iter_init(&iter, priv->domains);
Packit a07778
Packit a07778
    while (g_hash_table_iter_next(&iter, &key, &value)) {
Packit a07778
        GVirDomain *dom = value;
Packit a07778
        const gchar *thisname = gvir_domain_get_name(dom);
Packit a07778
Packit a07778
        if (thisname == NULL)
Packit a07778
            continue;
Packit a07778
Packit a07778
        if (strcmp(thisname, name) == 0) {
Packit a07778
            g_object_ref(dom);
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return dom;
Packit a07778
        }
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return NULL;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_find_storage_pool_by_name:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @name: name of the requested storage pool
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): the #GVirStoragePool, or NULL. The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirStoragePool *gvir_connection_find_storage_pool_by_name(GVirConnection *conn,
Packit a07778
                                                           const gchar *name)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTableIter iter;
Packit a07778
    gpointer key, value;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(name != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_iter_init(&iter, priv->pools);
Packit a07778
Packit a07778
    while (g_hash_table_iter_next(&iter, &key, &value)) {
Packit a07778
        GVirStoragePool *pool = value;
Packit a07778
        const gchar *thisname = gvir_storage_pool_get_name(pool);
Packit a07778
Packit a07778
        if (thisname == NULL)
Packit a07778
            continue;
Packit a07778
Packit a07778
        if (strcmp(thisname, name) == 0) {
Packit a07778
            g_object_ref(pool);
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return pool;
Packit a07778
        }
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return NULL;
Packit a07778
}
Packit a07778
Packit a07778
typedef struct virConnect GVirConnectionHandle;
Packit a07778
Packit a07778
static GVirConnectionHandle*
Packit a07778
gvir_connection_handle_copy(GVirConnectionHandle *src)
Packit a07778
{
Packit a07778
    virConnectRef((virConnectPtr)src);
Packit a07778
    return src;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_handle_free(GVirConnectionHandle *src)
Packit a07778
{
Packit a07778
    virConnectClose((virConnectPtr)src);
Packit a07778
}
Packit a07778
Packit a07778
G_DEFINE_BOXED_TYPE(GVirConnectionHandle, gvir_connection_handle,
Packit a07778
                    gvir_connection_handle_copy, gvir_connection_handle_free)
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_stream:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @flags: flags to use for the stream
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): a #GVirStream stream, or NULL.The returned
Packit a07778
 * object should be unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirStream *gvir_connection_get_stream(GVirConnection *self,
Packit a07778
                                       guint flags)
Packit a07778
{
Packit a07778
    GVirConnectionClass *klass;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(self), NULL);
Packit a07778
    g_return_val_if_fail(self->priv->conn, NULL);
Packit a07778
Packit a07778
    klass = GVIR_CONNECTION_GET_CLASS(self);
Packit a07778
    g_return_val_if_fail(klass->stream_new, NULL);
Packit a07778
Packit a07778
    virStreamPtr st = virStreamNew(self->priv->conn, flags | VIR_STREAM_NONBLOCK);
Packit a07778
Packit a07778
    return klass->stream_new(self, st);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_create_domain:
Packit a07778
 * @conn: a #GVirConnection on which to create the domain
Packit a07778
 * @conf: the configuration for the new domain
Packit a07778
 *
Packit a07778
 * Create the configuration file for a new persistent domain.
Packit a07778
 * The returned domain will initially be in the shutoff state.
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the newly created domain, or NULL if an error
Packit a07778
 * occurred. The returned object should be unreffed with g_object_unref()
Packit a07778
 * when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomain *gvir_connection_create_domain(GVirConnection *conn,
Packit a07778
                                          GVirConfigDomain *conf,
Packit a07778
                                          GError **err)
Packit a07778
{
Packit a07778
    gchar *xml;
Packit a07778
    virDomainPtr handle;
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(conf), NULL);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), NULL);
Packit a07778
Packit a07778
    xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(conf));
Packit a07778
Packit a07778
    g_return_val_if_fail(xml != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    handle = virDomainDefineXML(priv->conn, xml);
Packit a07778
    g_free(xml);
Packit a07778
    if (!handle) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Failed to create domain"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    GVirDomain *domain;
Packit a07778
Packit a07778
    domain = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN,
Packit a07778
                                       "handle", handle,
Packit a07778
                                       NULL));
Packit a07778
    virDomainFree(handle);
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_insert(priv->domains,
Packit a07778
                        (gpointer)gvir_domain_get_uuid(domain),
Packit a07778
                        g_object_ref(domain));
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return domain;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_start_domain:
Packit a07778
 * @conn: a #GVirConnection on which to create the domain
Packit a07778
 * @conf: the configuration for the new domain
Packit a07778
 *
Packit a07778
 * Start a new transient domain without persistent configuration.
Packit a07778
 * The returned domain will initially be running.
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the newly created domain, or NULL if an error
Packit a07778
 * occurred. The returned object should be unreffed with g_object_unref()
Packit a07778
 * when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomain *gvir_connection_start_domain(GVirConnection *conn,
Packit a07778
                                         GVirConfigDomain *conf,
Packit a07778
                                         guint flags,
Packit a07778
                                         GError **err)
Packit a07778
{
Packit a07778
    gchar *xml;
Packit a07778
    virDomainPtr handle;
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(conf), NULL);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), NULL);
Packit a07778
Packit a07778
    xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(conf));
Packit a07778
Packit a07778
    g_return_val_if_fail(xml != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    handle = virDomainCreateXML(priv->conn, xml, flags);
Packit a07778
    g_free(xml);
Packit a07778
    if (!handle) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Failed to create domain"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    GVirDomain *domain;
Packit a07778
Packit a07778
    domain = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN,
Packit a07778
                                       "handle", handle,
Packit a07778
                                       NULL));
Packit a07778
    virDomainFree(handle);
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_insert(priv->domains,
Packit a07778
                        (gpointer)gvir_domain_get_uuid(domain),
Packit a07778
                        g_object_ref(domain));
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return domain;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_interfaces:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @err: return location for any errors
Packit a07778
 *
Packit a07778
 * Use this method to fetch information on all network interfaces
Packit a07778
 * managed by connection @conn on host machine. Use
Packit a07778
 * #gvir_connection_get_interfaces or #gvir_connection_get_interface afterwards
Packit a07778
 * to query the fetched interfaces.
Packit a07778
 *
Packit a07778
 * Return value: %TRUE on success, %FALSE otherwise and @err is set.
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_interfaces(GVirConnection *conn,
Packit a07778
                                          GCancellable *cancellable,
Packit a07778
                                          GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTable *interfaces;
Packit a07778
    virInterfacePtr *ifaces = NULL;
Packit a07778
    gint ninterfaces = 0;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
    gint i;
Packit a07778
    virConnectPtr vconn = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                            0,
Packit a07778
                            _("Connection is not open"));
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
    vconn = priv->conn;
Packit a07778
    /* Stop another thread closing the connection just at the minute */
Packit a07778
    virConnectRef(vconn);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    ninterfaces = virConnectListAllInterfaces(vconn, &ifaces, 0);
Packit a07778
    if (ninterfaces < 0) {
Packit a07778
        gvir_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                       0,
Packit a07778
                       _("Failed to fetch list of interfaces"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    interfaces = g_hash_table_new_full(g_str_hash,
Packit a07778
                                       g_str_equal,
Packit a07778
                                       NULL,
Packit a07778
                                       g_object_unref);
Packit a07778
Packit a07778
    for (i = 0 ; i < ninterfaces; i++) {
Packit a07778
        GVirInterface *iface;
Packit a07778
Packit a07778
        if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
            goto cleanup;
Packit a07778
Packit a07778
        iface = GVIR_INTERFACE(g_object_new(GVIR_TYPE_INTERFACE,
Packit a07778
                                            "handle", ifaces[i],
Packit a07778
                                            NULL));
Packit a07778
Packit a07778
        g_hash_table_insert(interfaces,
Packit a07778
                            (gpointer)gvir_interface_get_name(iface),
Packit a07778
                            iface);
Packit a07778
    }
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->interfaces)
Packit a07778
        g_hash_table_unref(priv->interfaces);
Packit a07778
    priv->interfaces = interfaces;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
Packit a07778
cleanup:
Packit a07778
    if (ninterfaces > 0) {
Packit a07778
        for (i = 0 ; i < ninterfaces; i++)
Packit a07778
            virInterfaceFree(ifaces[i]);
Packit a07778
        free(ifaces);
Packit a07778
    }
Packit a07778
    if (vconn != NULL)
Packit a07778
        virConnectClose(vconn);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_fetch_interfaces_helper(GTask *task,
Packit a07778
                                        gpointer object,
Packit a07778
                                        gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                        GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_fetch_interfaces(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_interfaces_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_fetch_interfaces_async(GVirConnection *conn,
Packit a07778
                                            GCancellable *cancellable,
Packit a07778
                                            GAsyncReadyCallback callback,
Packit a07778
                                            gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_fetch_interfaces_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_fetch_interfaces_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_interfaces_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 * @err: return location for any errors
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_interfaces_finish(GVirConnection *conn,
Packit a07778
                                                 GAsyncResult *result,
Packit a07778
                                                 GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_fetch_interfaces_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_interfaces:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 *
Packit a07778
 * Get a list of all the network interfaces managed by connection @conn on
Packit a07778
 * host machine.
Packit a07778
 *
Packit a07778
 * Return value: (element-type LibvirtGObject.Interface) (transfer full): List
Packit a07778
 * of #GVirInterface. The returned list should be freed with g_list_free(),
Packit a07778
 * after its elements have been unreffed with g_object_unref().
Packit a07778
 */
Packit a07778
GList *gvir_connection_get_interfaces(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GList *interfaces = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->interfaces != NULL) {
Packit a07778
        interfaces = g_hash_table_get_values(priv->interfaces);
Packit a07778
        g_list_foreach(interfaces, gvir_domain_ref, NULL);
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return interfaces;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_interface:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @name: interface name to lookup
Packit a07778
 *
Packit a07778
 * Get a particular interface which has name @name.
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): A new reference to a #GVirInterface, or NULL
Packit a07778
 * if no interface exists with name @name. The returned object must be unreffed
Packit a07778
 * using g_object_unref() once used.
Packit a07778
 */
Packit a07778
GVirInterface *gvir_connection_get_interface(GVirConnection *conn,
Packit a07778
                                             const gchar *name)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GVirInterface *iface;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(name != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    iface = g_hash_table_lookup(priv->interfaces, name);
Packit a07778
    if (iface)
Packit a07778
        g_object_ref(iface);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return iface;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_find_interface_by_mac:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @macaddr: MAC address to lookup
Packit a07778
 *
Packit a07778
 * Get a particular interface which has MAC address @mac.
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): A new reference to a #GVirInterface, or NULL
Packit a07778
 * if no interface exists with MAC address @mac. The returned object must be
Packit a07778
 * unreffed using g_object_unref() once used.
Packit a07778
 */
Packit a07778
GVirInterface *gvir_connection_find_interface_by_mac(GVirConnection *conn,
Packit a07778
                                                     const gchar *mac)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTableIter iter;
Packit a07778
    gpointer key, value;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(mac != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_iter_init(&iter, priv->interfaces);
Packit a07778
Packit a07778
    while (g_hash_table_iter_next(&iter, &key, &value)) {
Packit a07778
        GVirInterface *iface = value;
Packit a07778
        const gchar *thismac = gvir_interface_get_mac(iface);
Packit a07778
Packit a07778
        if (g_strcmp0(thismac, mac) == 0) {
Packit a07778
            g_object_ref(iface);
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return iface;
Packit a07778
        }
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return NULL;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_networks:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 *
Packit a07778
 * Use this method to fetch all networks managed by connection
Packit a07778
 * @conn. Use e.g. #gvir_connection_find_network_by_name or
Packit a07778
 * #gvir_connection_get_networks afterwards to query the fetched
Packit a07778
 * domains.
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_networks(GVirConnection *conn,
Packit a07778
                                        GCancellable *cancellable,
Packit a07778
                                        GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTable *networks;
Packit a07778
    virNetworkPtr *vnetworks = NULL;
Packit a07778
    gint nnetworks = 0;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
    gint i;
Packit a07778
    virConnectPtr vconn = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (!priv->conn) {
Packit a07778
        g_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                            0,
Packit a07778
                            _("Connection is not open"));
Packit a07778
        g_mutex_unlock(priv->lock);
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
    vconn = priv->conn;
Packit a07778
    /* Stop another thread closing the connection just at the minute */
Packit a07778
    virConnectRef(vconn);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    nnetworks = virConnectListAllNetworks(vconn, &vnetworks, 0);
Packit a07778
    if (nnetworks < 0) {
Packit a07778
        gvir_set_error(err, GVIR_CONNECTION_ERROR,
Packit a07778
                       0,
Packit a07778
                       _("Failed to fetch list of networks"));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
        goto cleanup;
Packit a07778
Packit a07778
    networks = g_hash_table_new_full(g_str_hash,
Packit a07778
                                     g_str_equal,
Packit a07778
                                     NULL,
Packit a07778
                                     g_object_unref);
Packit a07778
Packit a07778
    for (i = 0 ; i < nnetworks; i++) {
Packit a07778
        GVirNetwork *network;
Packit a07778
Packit a07778
        if (g_cancellable_set_error_if_cancelled(cancellable, err))
Packit a07778
            goto cleanup;
Packit a07778
Packit a07778
        network = GVIR_NETWORK(g_object_new(GVIR_TYPE_NETWORK,
Packit a07778
                                            "handle", vnetworks[i],
Packit a07778
                                            NULL));
Packit a07778
        g_hash_table_insert(networks,
Packit a07778
                            (gpointer)gvir_network_get_uuid(network),
Packit a07778
                            network);
Packit a07778
    }
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->networks)
Packit a07778
        g_hash_table_unref(priv->networks);
Packit a07778
    priv->networks = networks;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
Packit a07778
cleanup:
Packit a07778
    if (nnetworks > 0) {
Packit a07778
        for (i = 0 ; i < nnetworks; i++)
Packit a07778
            virNetworkFree(vnetworks[i]);
Packit a07778
        free(vnetworks);
Packit a07778
    }
Packit a07778
    if (vconn != NULL)
Packit a07778
        virConnectClose(vconn);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_fetch_networks_helper(GTask *task,
Packit a07778
                                      gpointer object,
Packit a07778
                                      gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                      GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_connection_fetch_networks(conn, cancellable, &err))
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_networks_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_fetch_networks_async(GVirConnection *conn,
Packit a07778
                                          GCancellable *cancellable,
Packit a07778
                                          GAsyncReadyCallback callback,
Packit a07778
                                          gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                     cancellable,
Packit a07778
                     callback,
Packit a07778
                     user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_fetch_networks_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_fetch_networks_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_fetch_networks_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 * @err: return location for any errors
Packit a07778
 */
Packit a07778
gboolean gvir_connection_fetch_networks_finish(GVirConnection *conn,
Packit a07778
                                               GAsyncResult *result,
Packit a07778
                                               GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_fetch_networks_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_networks:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 *
Packit a07778
 * Get a list of all the network networks available through @conn.
Packit a07778
 *
Packit a07778
 * Return value: (element-type LibvirtGObject.Network) (transfer full): List
Packit a07778
 * of #GVirNetwork. The returned list should be freed with g_list_free(),
Packit a07778
 * after its elements have been unreffed with g_object_unref().
Packit a07778
 */
Packit a07778
GList *gvir_connection_get_networks(GVirConnection *conn)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GList *networks = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->networks != NULL) {
Packit a07778
        networks = g_hash_table_get_values(priv->networks);
Packit a07778
        g_list_foreach(networks, gvir_domain_ref, NULL);
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return networks;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_network:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @uuid: UUID of the network to lookup
Packit a07778
 *
Packit a07778
 * Get a particular network which has UUID @uuid.
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): A new reference to a #GVirNetwork, or NULL if
Packit a07778
 * no network exists with UUID @uuid. The returned object must be unreffed using
Packit a07778
 * g_object_unref() once used.
Packit a07778
 */
Packit a07778
GVirNetwork *gvir_connection_get_network(GVirConnection *conn,
Packit a07778
                                         const gchar *uuid)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GVirNetwork *network;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(uuid != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    network = g_hash_table_lookup(priv->networks, uuid);
Packit a07778
    if (network)
Packit a07778
        g_object_ref(network);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return network;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_find_network_by_name:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @name: name of the network to search for
Packit a07778
 *
Packit a07778
 * Get a particular network which has name @name.
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): A new reference to a #GVirNetwork, or NULL if
Packit a07778
 * no network exists with name @name. The returned object must be unreffed using
Packit a07778
 * g_object_unref() once used.
Packit a07778
 */
Packit a07778
GVirNetwork *gvir_connection_find_network_by_name(GVirConnection *conn,
Packit a07778
                                                  const gchar *name)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    GHashTableIter iter;
Packit a07778
    gpointer key, value;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(name != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_iter_init(&iter, priv->networks);
Packit a07778
Packit a07778
    while (g_hash_table_iter_next(&iter, &key, &value)) {
Packit a07778
        GVirNetwork *network = value;
Packit a07778
        const gchar *thisname = gvir_network_get_name(network);
Packit a07778
Packit a07778
        if (thisname == NULL)
Packit a07778
            continue;
Packit a07778
Packit a07778
        if (strcmp(thisname, name) == 0) {
Packit a07778
            g_object_ref(network);
Packit a07778
            g_mutex_unlock(priv->lock);
Packit a07778
            return network;
Packit a07778
        }
Packit a07778
    }
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return NULL;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_create_storage_pool:
Packit a07778
 * @conn: a #GVirConnection on which to create the pool
Packit a07778
 * @conf: the configuration for the new storage pool
Packit a07778
 * @flags:  the flags
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the newly created storage pool, or NULL if an
Packit a07778
 * error occurred. The returned list should be freed with g_list_free(),
Packit a07778
 * after its elements have been unreffed with g_object_unref().
Packit a07778
 */
Packit a07778
GVirStoragePool *gvir_connection_create_storage_pool
Packit a07778
                                (GVirConnection *conn,
Packit a07778
                                 GVirConfigStoragePool *conf,
Packit a07778
                                 guint flags,
Packit a07778
                                 GError **err) {
Packit a07778
    gchar *xml;
Packit a07778
    virStoragePoolPtr handle;
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(GVIR_CONFIG_IS_STORAGE_POOL(conf), NULL);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), NULL);
Packit a07778
Packit a07778
    xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(conf));
Packit a07778
Packit a07778
    g_return_val_if_fail(xml != NULL, NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    handle = virStoragePoolDefineXML(priv->conn, xml, flags);
Packit a07778
    g_free(xml);
Packit a07778
    if (!handle) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               flags,
Packit a07778
                               _("Failed to create storage pool"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    GVirStoragePool *pool;
Packit a07778
Packit a07778
    pool = GVIR_STORAGE_POOL(g_object_new(GVIR_TYPE_STORAGE_POOL,
Packit a07778
                                          "handle", handle,
Packit a07778
                                          NULL));
Packit a07778
    virStoragePoolFree(handle);
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    g_hash_table_insert(priv->pools,
Packit a07778
                        (gpointer)gvir_storage_pool_get_uuid(pool),
Packit a07778
                        pool);
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    return g_object_ref(pool);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_node_info:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the info, or NULL if an error occurred. The
Packit a07778
 * returned object should be unreffed with g_object_unref() when no longer
Packit a07778
 * needed.
Packit a07778
 */
Packit a07778
GVirNodeInfo *gvir_connection_get_node_info(GVirConnection *conn,
Packit a07778
                                            GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    virNodeInfo info;
Packit a07778
    GVirNodeInfo *ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), NULL);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
    if (virNodeGetInfo(priv->conn, &info) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Unable to get node info"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = g_slice_new(GVirNodeInfo);
Packit a07778
    g_strlcpy (ret->model, info.model, sizeof (ret->model));
Packit a07778
    ret->memory = info.memory;
Packit a07778
    ret->cpus = info.cpus;
Packit a07778
    ret->mhz = info.mhz;
Packit a07778
    ret->nodes = info.nodes;
Packit a07778
    ret->sockets = info.sockets;
Packit a07778
    ret->cores = info.cores;
Packit a07778
    ret->threads = info.threads;
Packit a07778
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_domain_capabilities:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @emulatorbin: (allow-none): path to emulator
Packit a07778
 * @arch: (allow-none): domain architecture
Packit a07778
 * @machine: (allow-none): machine type
Packit a07778
 * @virttype: (allow-none): virtualization type
Packit a07778
 * @flags: extra flags; not used yet, so callers should always pass 0
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): a #GVirConfigDomainCapabilities or NULL.
Packit a07778
 * The return object should be unreffed with g_object_unref() when no longer
Packit a07778
 * needed.
Packit a07778
 */
Packit a07778
GVirConfigDomainCapabilities *
Packit a07778
gvir_connection_get_domain_capabilities(GVirConnection *conn,
Packit a07778
                                        const gchar *emulatorbin,
Packit a07778
                                        const gchar *arch,
Packit a07778
                                        const gchar *machine,
Packit a07778
                                        const gchar *virttype,
Packit a07778
                                        guint flags,
Packit a07778
                                        GError **err)
Packit a07778
{
Packit a07778
    GVirConfigDomainCapabilities *domain_caps;
Packit a07778
    gchar *domain_caps_xml;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
    g_return_val_if_fail(conn->priv->conn, NULL);
Packit a07778
Packit a07778
    domain_caps_xml = virConnectGetDomainCapabilities(conn->priv->conn,
Packit a07778
                                                      emulatorbin,
Packit a07778
                                                      arch,
Packit a07778
                                                      machine,
Packit a07778
                                                      virttype,
Packit a07778
                                                      flags);
Packit a07778
    if (domain_caps_xml == NULL) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Unable to get domain capabilities"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    domain_caps = gvir_config_domain_capabilities_new_from_xml(domain_caps_xml, err);
Packit a07778
    free(domain_caps_xml);
Packit a07778
Packit a07778
    return domain_caps;
Packit a07778
}
Packit a07778
Packit a07778
typedef struct {
Packit a07778
    gchar *emulatorbin;
Packit a07778
    gchar *arch;
Packit a07778
    gchar *machine;
Packit a07778
    gchar *virttype;
Packit a07778
    guint flags;
Packit a07778
} GetDomainCapabilitiesData;
Packit a07778
Packit a07778
static void get_domain_capabilities_data_free(GetDomainCapabilitiesData *data)
Packit a07778
{
Packit a07778
    g_free(data->emulatorbin);
Packit a07778
    g_free(data->arch);
Packit a07778
    g_free(data->machine);
Packit a07778
    g_free(data->virttype);
Packit a07778
    g_slice_free(GetDomainCapabilitiesData, data);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_get_domain_capabilities_helper(GTask *task,
Packit a07778
                                               gpointer object,
Packit a07778
                                               gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                               GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GetDomainCapabilitiesData *data;
Packit a07778
    GError *err = NULL;
Packit a07778
    GVirConfigDomainCapabilities *domain_caps;
Packit a07778
Packit a07778
    data = (GetDomainCapabilitiesData *)task_data;
Packit a07778
Packit a07778
    domain_caps = gvir_connection_get_domain_capabilities(conn,
Packit a07778
                                                          data->emulatorbin,
Packit a07778
                                                          data->arch,
Packit a07778
                                                          data->machine,
Packit a07778
                                                          data->virttype,
Packit a07778
                                                          data->flags,
Packit a07778
                                                          &err;;
Packit a07778
    if (domain_caps == NULL) {
Packit a07778
        g_task_return_error(task, err);
Packit a07778
Packit a07778
        return;
Packit a07778
    }
Packit a07778
Packit a07778
    g_task_return_pointer(task, domain_caps, g_object_unref);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_domain_capabilities_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @emulatorbin: (allow-none): path to emulator
Packit a07778
 * @arch: (allow-none): domain architecture
Packit a07778
 * @machine: (allow-none): machine type
Packit a07778
 * @virttype: (allow-none): virtualization type
Packit a07778
 * @flags: extra flags; not used yet, so callers should always pass 0
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_get_domain_capabilities_async(GVirConnection *conn,
Packit a07778
                                                   const gchar *emulatorbin,
Packit a07778
                                                   const gchar *arch,
Packit a07778
                                                   const gchar *machine,
Packit a07778
                                                   const gchar *virttype,
Packit a07778
                                                   guint flags,
Packit a07778
                                                   GCancellable *cancellable,
Packit a07778
                                                   GAsyncReadyCallback callback,
Packit a07778
                                                   gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
    GetDomainCapabilitiesData *data;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    data = g_slice_new0(GetDomainCapabilitiesData);
Packit a07778
    data->emulatorbin = g_strdup(emulatorbin);
Packit a07778
    data->arch = g_strdup(arch);
Packit a07778
    data->machine = g_strdup(machine);
Packit a07778
    data->virttype = g_strdup(virttype);
Packit a07778
    data->flags = flags;
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_get_domain_capabilities_async);
Packit a07778
    g_task_set_task_data(task,
Packit a07778
                         data,
Packit a07778
                         (GDestroyNotify)get_domain_capabilities_data_free);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_get_domain_capabilities_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_domain_capabilities_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): a #GVirConfigDomainCapabilities or NULL.
Packit a07778
 * The returned object should be unreffed with g_object_unref() when no
Packit a07778
 * longer needed.
Packit a07778
 */
Packit a07778
GVirConfigDomainCapabilities *
Packit a07778
gvir_connection_get_domain_capabilities_finish(GVirConnection *conn,
Packit a07778
                                               GAsyncResult *result,
Packit a07778
                                               GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         NULL);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_get_domain_capabilities_async,
Packit a07778
                         NULL);
Packit a07778
Packit a07778
    return g_task_propagate_pointer(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_capabilities:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @err: return location for any #GError
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): a #GVirConfigCapabilities or NULL.  The
Packit a07778
 * returned object should be unreffed with g_object_unref() when no longer
Packit a07778
 * needed.
Packit a07778
 */
Packit a07778
GVirConfigCapabilities *gvir_connection_get_capabilities(GVirConnection *conn,
Packit a07778
                                                         GError **err)
Packit a07778
{
Packit a07778
    GVirConfigCapabilities *caps;
Packit a07778
    char *caps_xml;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
    g_return_val_if_fail(conn->priv->conn, NULL);
Packit a07778
Packit a07778
    caps_xml = virConnectGetCapabilities(conn->priv->conn);
Packit a07778
    if (caps_xml == NULL) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Unable to get capabilities"));
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    caps = gvir_config_capabilities_new_from_xml(caps_xml, err);
Packit a07778
    free(caps_xml);
Packit a07778
Packit a07778
    return caps;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_get_capabilities_helper(GTask *task,
Packit a07778
                                        gpointer object,
Packit a07778
                                        gpointer task_data G_GNUC_UNUSED,
Packit a07778
                                        GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    GError *err = NULL;
Packit a07778
    GVirConfigCapabilities *caps;
Packit a07778
Packit a07778
    caps = gvir_connection_get_capabilities(conn, &err;;
Packit a07778
    if (caps == NULL) {
Packit a07778
        g_task_return_error(task, err);
Packit a07778
Packit a07778
        return;
Packit a07778
    }
Packit a07778
Packit a07778
    g_task_return_pointer(task, caps, g_object_unref);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_capabilities_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @cancellable: (allow-none)(transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 */
Packit a07778
void gvir_connection_get_capabilities_async(GVirConnection *conn,
Packit a07778
                                            GCancellable *cancellable,
Packit a07778
                                            GAsyncReadyCallback callback,
Packit a07778
                                            gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_get_capabilities_async);
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_get_capabilities_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_get_capabilities_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 *
Packit a07778
 * Return value: (transfer full): a #GVirConfigCapabilities or NULL. The
Packit a07778
 * returned object should be unreffed with g_object_unref() when no longer
Packit a07778
 * needed.
Packit a07778
 */
Packit a07778
GVirConfigCapabilities *
Packit a07778
gvir_connection_get_capabilities_finish(GVirConnection *conn,
Packit a07778
                                        GAsyncResult *result,
Packit a07778
                                        GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         NULL);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_get_capabilities_async,
Packit a07778
                         NULL);
Packit a07778
Packit a07778
    return g_task_propagate_pointer(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_restore_domain_from_file:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @filename: path to input file
Packit a07778
 * @custom_conf: (allow-none): configuration for domain or NULL
Packit a07778
 * @flags: the flags
Packit a07778
 *
Packit a07778
 * Restores the domain saved with #gvir_domain_save_to_file
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success, FALSE otherwise
Packit a07778
 */
Packit a07778
gboolean gvir_connection_restore_domain_from_file(GVirConnection *conn,
Packit a07778
                                                  gchar *filename,
Packit a07778
                                                  GVirConfigDomain *custom_conf,
Packit a07778
                                                  guint flags,
Packit a07778
                                                  GError **err)
Packit a07778
{
Packit a07778
    GVirConnectionPrivate *priv;
Packit a07778
    int ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail((filename != NULL), FALSE);
Packit a07778
    g_return_val_if_fail((err == NULL) || (*err == NULL), FALSE);
Packit a07778
Packit a07778
    priv = conn->priv;
Packit a07778
Packit a07778
    if (flags || (custom_conf != NULL)) {
Packit a07778
        gchar *custom_xml = NULL;
Packit a07778
Packit a07778
       if (custom_conf != NULL)
Packit a07778
           custom_xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(custom_conf));
Packit a07778
Packit a07778
       ret = virDomainRestoreFlags(priv->conn, filename, custom_xml, flags);
Packit a07778
       g_free (custom_xml);
Packit a07778
    }
Packit a07778
    else {
Packit a07778
       ret = virDomainRestore(priv->conn, filename);
Packit a07778
    }
Packit a07778
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
Packit a07778
                               0,
Packit a07778
                               _("Unable to restore domain"));
Packit a07778
Packit a07778
       return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
typedef struct {
Packit a07778
    gchar *filename;
Packit a07778
    GVirConfigDomain *custom_conf;
Packit a07778
    guint flags;
Packit a07778
} RestoreDomainFromFileData;
Packit a07778
Packit a07778
static void restore_domain_from_file_data_free(RestoreDomainFromFileData *data)
Packit a07778
{
Packit a07778
    g_free(data->filename);
Packit a07778
    g_clear_object(&data->custom_conf);
Packit a07778
    g_slice_free(RestoreDomainFromFileData, data);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_connection_restore_domain_from_file_helper
Packit a07778
                               (GTask *task,
Packit a07778
                                gpointer object,
Packit a07778
                                gpointer task_data,
Packit a07778
                                GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirConnection *conn = GVIR_CONNECTION(object);
Packit a07778
    RestoreDomainFromFileData *data;
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    data = (RestoreDomainFromFileData *)task_data;
Packit a07778
Packit a07778
    if (!gvir_connection_restore_domain_from_file(conn,
Packit a07778
                                                  data->filename,
Packit a07778
                                                  data->custom_conf,
Packit a07778
                                                  data->flags,
Packit a07778
                                                  &err))
Packit a07778
       g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_restore_domain_from_file_async:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @filename: path to input file
Packit a07778
 * @custom_conf: (allow-none): configuration for domain
Packit a07778
 * @flags: the flags
Packit a07778
 * @cancellable: (allow-none) (transfer none): cancellation object
Packit a07778
 * @callback: (scope async): completion callback
Packit a07778
 * @user_data: (closure): opaque data for callback
Packit a07778
 *
Packit a07778
 * Asynchronous variant of #gvir_connection_restore_domain_from_file
Packit a07778
 */
Packit a07778
void
Packit a07778
gvir_connection_restore_domain_from_file_async(GVirConnection *conn,
Packit a07778
                                               gchar *filename,
Packit a07778
                                               GVirConfigDomain *custom_conf,
Packit a07778
                                               guint flags,
Packit a07778
                                               GCancellable *cancellable,
Packit a07778
                                               GAsyncReadyCallback callback,
Packit a07778
                                               gpointer user_data)
Packit a07778
{
Packit a07778
    GTask *task;
Packit a07778
    RestoreDomainFromFileData *data;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_CONNECTION(conn));
Packit a07778
    g_return_if_fail(filename != NULL);
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    data = g_slice_new0(RestoreDomainFromFileData);
Packit a07778
    data->filename = g_strdup(filename);
Packit a07778
    if (custom_conf != NULL)
Packit a07778
        data->custom_conf = g_object_ref(custom_conf);
Packit a07778
    data->flags = flags;
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(conn),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_source_tag(task,
Packit a07778
                          gvir_connection_restore_domain_from_file_async);
Packit a07778
    g_task_set_task_data(task,
Packit a07778
                         data,
Packit a07778
                         (GDestroyNotify)restore_domain_from_file_data_free);
Packit a07778
Packit a07778
    g_task_run_in_thread(task,
Packit a07778
                         gvir_connection_restore_domain_from_file_helper);
Packit a07778
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_connection_restore_domain_from_file_finish:
Packit a07778
 * @conn: a #GVirConnection
Packit a07778
 * @result: (transfer none): async method result
Packit a07778
 * @err: Place-holder for possible errors
Packit a07778
 *
Packit a07778
 * Finishes the operation started by #gvir_restore_domain_from_file_async.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain was restored successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean
Packit a07778
gvir_connection_restore_domain_from_file_finish(GVirConnection *conn,
Packit a07778
                                                GAsyncResult *result,
Packit a07778
                                                GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_CONNECTION(conn), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(conn)),
Packit a07778
                         FALSE);
Packit a07778
    g_return_val_if_fail(g_task_get_source_tag(G_TASK(result)) ==
Packit a07778
                         gvir_connection_restore_domain_from_file_async,
Packit a07778
                         FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}