Blame libvirt-gobject/libvirt-gobject-domain.c

Packit a07778
/*
Packit a07778
 * libvirt-gobject-domain.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 <glib.h>
Packit a07778
#include <libvirt/virterror.h>
Packit a07778
#include <string.h>
Packit a07778
#if !defined(HAVE_VIR_DOMAIN_OPEN_GRAPHICS_FD) && !defined(G_OS_WIN32)
Packit a07778
#include <sys/socket.h>
Packit a07778
#endif
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
#include "libvirt-gobject/libvirt-gobject-domain-device-private.h"
Packit a07778
Packit a07778
#define GVIR_DOMAIN_GET_PRIVATE(obj)                         \
Packit a07778
        (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_DOMAIN, GVirDomainPrivate))
Packit a07778
Packit a07778
struct _GVirDomainPrivate
Packit a07778
{
Packit a07778
    virDomainPtr handle;
Packit a07778
    gchar uuid[VIR_UUID_STRING_BUFLEN];
Packit a07778
    GHashTable *snapshots;
Packit a07778
    GMutex *lock;
Packit a07778
};
Packit a07778
Packit a07778
G_DEFINE_TYPE_WITH_PRIVATE(GVirDomain, gvir_domain, G_TYPE_OBJECT);
Packit a07778
Packit a07778
Packit a07778
enum {
Packit a07778
    PROP_0,
Packit a07778
    PROP_HANDLE,
Packit a07778
    PROP_PERSISTENT,
Packit a07778
};
Packit a07778
Packit a07778
enum {
Packit a07778
    VIR_STARTED,
Packit a07778
    VIR_SUSPENDED,
Packit a07778
    VIR_RESUMED,
Packit a07778
    VIR_STOPPED,
Packit a07778
    VIR_UPDATED,
Packit a07778
    VIR_PMSUSPENDED,
Packit a07778
    LAST_SIGNAL
Packit a07778
};
Packit a07778
Packit a07778
typedef struct {
Packit a07778
    guint create_flags;
Packit a07778
    GVirConfigDomainSnapshot *snapshot_config;
Packit a07778
} SnapshotCreateData;
Packit a07778
Packit a07778
static void snapshot_create_data_free (SnapshotCreateData *data) {
Packit a07778
    g_clear_object (&data->snapshot_config);
Packit a07778
    g_slice_free (SnapshotCreateData, data);
Packit a07778
}
Packit a07778
Packit a07778
static gint signals[LAST_SIGNAL];
Packit a07778
Packit a07778
#define GVIR_DOMAIN_ERROR gvir_domain_error_quark()
Packit a07778
Packit a07778
Packit a07778
static GQuark
Packit a07778
gvir_domain_error_quark(void)
Packit a07778
{
Packit a07778
    return g_quark_from_static_string("gvir-domain");
Packit a07778
}
Packit a07778
Packit a07778
static void gvir_domain_get_property(GObject *object,
Packit a07778
                                     guint prop_id,
Packit a07778
                                     GValue *value,
Packit a07778
                                     GParamSpec *pspec)
Packit a07778
{
Packit a07778
    GVirDomain *domain = GVIR_DOMAIN(object);
Packit a07778
    GVirDomainPrivate *priv = domain->priv;
Packit a07778
Packit a07778
    switch (prop_id) {
Packit a07778
    case PROP_HANDLE:
Packit a07778
        g_value_set_boxed(value, priv->handle);
Packit a07778
        break;
Packit a07778
Packit a07778
    case PROP_PERSISTENT:
Packit a07778
        g_value_set_boolean(value, gvir_domain_get_persistent (domain));
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_domain_set_property(GObject *object,
Packit a07778
                                     guint prop_id,
Packit a07778
                                     const GValue *value,
Packit a07778
                                     GParamSpec *pspec)
Packit a07778
{
Packit a07778
    GVirDomain *domain = GVIR_DOMAIN(object);
Packit a07778
    GVirDomainPrivate *priv = domain->priv;
Packit a07778
Packit a07778
    switch (prop_id) {
Packit a07778
    case PROP_HANDLE:
Packit a07778
        if (priv->handle)
Packit a07778
            virDomainFree(priv->handle);
Packit a07778
        priv->handle = 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_domain_finalize(GObject *object)
Packit a07778
{
Packit a07778
    GVirDomain *domain = GVIR_DOMAIN(object);
Packit a07778
    GVirDomainPrivate *priv = domain->priv;
Packit a07778
Packit a07778
    if (priv->snapshots) {
Packit a07778
        g_hash_table_unref(priv->snapshots);
Packit a07778
    }
Packit a07778
    g_mutex_free(priv->lock);
Packit a07778
Packit a07778
    virDomainFree(priv->handle);
Packit a07778
Packit a07778
    G_OBJECT_CLASS(gvir_domain_parent_class)->finalize(object);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_domain_constructed(GObject *object)
Packit a07778
{
Packit a07778
    GVirDomain *domain = GVIR_DOMAIN(object);
Packit a07778
    GVirDomainPrivate *priv = domain->priv;
Packit a07778
Packit a07778
    G_OBJECT_CLASS(gvir_domain_parent_class)->constructed(object);
Packit a07778
Packit a07778
    /* xxx we may want to turn this into an initable */
Packit a07778
    if (virDomainGetUUIDString(priv->handle, priv->uuid) < 0)
Packit a07778
        gvir_warning("Failed to get domain UUID on %p", priv->handle);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_domain_class_init(GVirDomainClass *klass)
Packit a07778
{
Packit a07778
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit a07778
Packit a07778
    object_class->finalize = gvir_domain_finalize;
Packit a07778
    object_class->get_property = gvir_domain_get_property;
Packit a07778
    object_class->set_property = gvir_domain_set_property;
Packit a07778
    object_class->constructed = gvir_domain_constructed;
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 domain handle",
Packit a07778
                                                       GVIR_TYPE_DOMAIN_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
    g_object_class_install_property(object_class,
Packit a07778
                                    PROP_PERSISTENT,
Packit a07778
                                    g_param_spec_boolean("persistent",
Packit a07778
                                                         "Persistent",
Packit a07778
                                                         "If domain is persistent",
Packit a07778
                                                         TRUE,
Packit a07778
                                                         G_PARAM_READABLE |
Packit a07778
                                                         G_PARAM_STATIC_STRINGS));
Packit a07778
Packit a07778
    signals[VIR_STARTED] = g_signal_new("started",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
Packit a07778
                                        G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, started),
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_SUSPENDED] = g_signal_new("suspended",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
Packit a07778
                                        G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, suspended),
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_RESUMED] = g_signal_new("resumed",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
Packit a07778
                                        G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, resumed),
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_STOPPED] = g_signal_new("stopped",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
Packit a07778
                                        G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, stopped),
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_UPDATED] = g_signal_new("updated",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, updated),
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_PMSUSPENDED] = g_signal_new("pmsuspended",
Packit a07778
                                        G_OBJECT_CLASS_TYPE(object_class),
Packit a07778
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
Packit a07778
                                        G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
Packit a07778
                                        G_STRUCT_OFFSET(GVirDomainClass, pmsuspended),
Packit a07778
                                        NULL, NULL,
Packit a07778
                                        g_cclosure_marshal_VOID__VOID,
Packit a07778
                                        G_TYPE_NONE,
Packit a07778
                                        0);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void gvir_domain_init(GVirDomain *domain)
Packit a07778
{
Packit a07778
    domain->priv = GVIR_DOMAIN_GET_PRIVATE(domain);
Packit a07778
    domain->priv->lock = g_mutex_new();
Packit a07778
}
Packit a07778
Packit a07778
typedef struct virDomain GVirDomainHandle;
Packit a07778
Packit a07778
static GVirDomainHandle*
Packit a07778
gvir_domain_handle_copy(GVirDomainHandle *src)
Packit a07778
{
Packit a07778
    virDomainRef((virDomainPtr)src);
Packit a07778
    return src;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_handle_free(GVirDomainHandle *src)
Packit a07778
{
Packit a07778
    virDomainFree((virDomainPtr)src);
Packit a07778
}
Packit a07778
Packit a07778
G_DEFINE_BOXED_TYPE(GVirDomainHandle, gvir_domain_handle,
Packit a07778
                    gvir_domain_handle_copy, gvir_domain_handle_free)
Packit a07778
Packit a07778
static GVirDomainInfo *
Packit a07778
gvir_domain_info_copy(GVirDomainInfo *info)
Packit a07778
{
Packit a07778
    return g_slice_dup(GVirDomainInfo, info);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_info_free(GVirDomainInfo *info)
Packit a07778
{
Packit a07778
    g_slice_free(GVirDomainInfo, info);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
G_DEFINE_BOXED_TYPE(GVirDomainInfo, gvir_domain_info,
Packit a07778
                    gvir_domain_info_copy, gvir_domain_info_free)
Packit a07778
Packit a07778
Packit a07778
const gchar *gvir_domain_get_name(GVirDomain *dom)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    const char *name;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (!(name = virDomainGetName(priv->handle))) {
Packit a07778
        gvir_warning("Failed to get domain name on %p", priv->handle);
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    return name;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
const gchar *gvir_domain_get_uuid(GVirDomain *dom)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
Packit a07778
    return dom->priv->uuid;
Packit a07778
}
Packit a07778
Packit a07778
gint gvir_domain_get_id(GVirDomain *dom,
Packit a07778
                        GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    gint ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), -1);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, -1);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if ((ret = virDomainGetID(priv->handle)) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to get ID for domain");
Packit a07778
    }
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_start:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags:  the flags
Packit a07778
 */
Packit a07778
gboolean gvir_domain_start(GVirDomain *dom,
Packit a07778
                           guint flags,
Packit a07778
                           GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    int ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (flags)
Packit a07778
        ret = virDomainCreateWithFlags(priv->handle, flags);
Packit a07778
    else
Packit a07778
        ret = virDomainCreate(priv->handle);
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to start domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_start_helper(GTask *task,
Packit a07778
                         gpointer source_object,
Packit a07778
                         gpointer task_data,
Packit a07778
                         GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    guint flags = GPOINTER_TO_UINT(task_data);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_start(dom, flags, &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_domain_start_async:
Packit a07778
 * @dom: the 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_domain_start.
Packit a07778
 */
Packit a07778
void gvir_domain_start_async(GVirDomain *dom,
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
Packit a07778
    g_return_if_fail(GVIR_IS_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_task_data(task, GUINT_TO_POINTER(flags), NULL);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_start_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_domain_start_finish(GVirDomain *dom,
Packit a07778
                                  GAsyncResult *result,
Packit a07778
                                  GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_resume:
Packit a07778
 * @dom: the domain
Packit a07778
 * @err: Place-holder for possible errors
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success
Packit a07778
 */
Packit a07778
gboolean gvir_domain_resume(GVirDomain *dom,
Packit a07778
                            GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (virDomainResume(priv->handle) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to resume domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_resume_helper(GTask *task,
Packit a07778
                          gpointer source_object,
Packit a07778
                          gpointer task_data G_GNUC_UNUSED,
Packit a07778
                          GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_resume(dom, &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_domain_resume_async:
Packit a07778
 * @dom: the domain to resume
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_domain_resume.
Packit a07778
 */
Packit a07778
void gvir_domain_resume_async(GVirDomain *dom,
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_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_resume_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_domain_resume_finish(GVirDomain *dom,
Packit a07778
                                   GAsyncResult *result,
Packit a07778
                                   GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_wakeup:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags: placeholder for flags, pass 0
Packit a07778
 * @err: Place-holder for possible errors
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success
Packit a07778
 */
Packit a07778
gboolean gvir_domain_wakeup(GVirDomain *dom,
Packit a07778
                            guint flags,
Packit a07778
                            GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (virDomainPMWakeup(priv->handle, flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to wakeup domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_wakeup_helper(GTask *task,
Packit a07778
                          gpointer source_object,
Packit a07778
                          gpointer task_data,
Packit a07778
                          GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    guint flags = GPOINTER_TO_UINT(task_data);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_wakeup(dom, flags, &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_domain_wakeup_async:
Packit a07778
 * @dom: the domain to wakeup
Packit a07778
 * @flags: placeholder for flags, 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
 * Asynchronous variant of #gvir_domain_wakeup.
Packit a07778
 */
Packit a07778
void gvir_domain_wakeup_async(GVirDomain *dom,
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
Packit a07778
    g_return_if_fail(GVIR_IS_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_task_data(task, GUINT_TO_POINTER(flags), NULL);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_wakeup_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
gboolean gvir_domain_wakeup_finish(GVirDomain *dom,
Packit a07778
                                   GAsyncResult *result,
Packit a07778
                                   GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_stop:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags:  the flags
Packit a07778
 */
Packit a07778
gboolean gvir_domain_stop(GVirDomain *dom,
Packit a07778
                          guint flags,
Packit a07778
                          GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    int ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (flags)
Packit a07778
        ret = virDomainDestroyFlags(priv->handle, flags);
Packit a07778
    else
Packit a07778
        ret = virDomainDestroy(priv->handle);
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to stop domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_delete:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags:  the flags
Packit a07778
 */
Packit a07778
gboolean gvir_domain_delete(GVirDomain *dom,
Packit a07778
                            guint flags,
Packit a07778
                            GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    int ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (flags)
Packit a07778
        ret = virDomainUndefineFlags(priv->handle, flags);
Packit a07778
    else
Packit a07778
        ret = virDomainUndefine(priv->handle);
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to delete domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_shutdown:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags:  the %GVirDomainShutdownFlags flags
Packit a07778
 */
Packit a07778
gboolean gvir_domain_shutdown(GVirDomain *dom,
Packit a07778
                              guint flags,
Packit a07778
                              GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (virDomainShutdownFlags(priv->handle, flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to shutdown domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_reboot:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags: the %GVirDomainRebootFlags flags
Packit a07778
 */
Packit a07778
gboolean gvir_domain_reboot(GVirDomain *dom,
Packit a07778
                            guint flags,
Packit a07778
                            GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (virDomainReboot(priv->handle, flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to reboot domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_save_to_file:
Packit a07778
 * @dom: the domain
Packit a07778
 * @filename: path to the output file
Packit a07778
 * @custom_conf: (allow-none): configuration for domain or NULL
Packit a07778
 * @flags: the flags
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success, FALSE otherwise
Packit a07778
 */
Packit a07778
gboolean gvir_domain_save_to_file(GVirDomain *dom,
Packit a07778
                                  gchar *filename,
Packit a07778
                                  GVirConfigDomain *custom_conf,
Packit a07778
                                  guint flags,
Packit a07778
                                  GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    int ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), 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 = dom->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 = virDomainSaveFlags(priv->handle, filename, custom_xml, flags);
Packit a07778
        g_free(custom_xml);
Packit a07778
    }
Packit a07778
    else {
Packit a07778
        ret = virDomainSave(priv->handle, filename);
Packit a07778
    }
Packit a07778
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to save domain to file");
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
} DomainSaveToFileData;
Packit a07778
Packit a07778
static void domain_save_to_file_data_free(DomainSaveToFileData *data)
Packit a07778
{
Packit a07778
    g_free(data->filename);
Packit a07778
    g_clear_object(&data->custom_conf);
Packit a07778
    g_slice_free(DomainSaveToFileData, data);
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_save_to_file_helper(GTask *task,
Packit a07778
                                gpointer source_object,
Packit a07778
                                gpointer task_data,
Packit a07778
                                GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    DomainSaveToFileData *data = (DomainSaveToFileData *) task_data;
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_save_to_file(dom, data->filename, data->custom_conf, data->flags, &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_domain_save_to_file_async:
Packit a07778
 * @dom: the domain
Packit a07778
 * @filename: path to output file
Packit a07778
 * @custom_conf: (allow-none): configuration for domain or NULL
Packit a07778
 * @flags: the flags
Packit a07778
 * @cancellable: (allow-none) (transfer none): cancallation 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_domain_save_to_file
Packit a07778
 */
Packit a07778
void gvir_domain_save_to_file_async(GVirDomain *dom,
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
    DomainSaveToFileData *data;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_DOMAIN(dom));
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(DomainSaveToFileData);
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(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_task_data(task,
Packit a07778
                         data,
Packit a07778
                         (GDestroyNotify) domain_save_to_file_data_free);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_save_to_file_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_save_to_file_finish:
Packit a07778
 * @dom: the domain to save
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_domain_save_to_file_async.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain was saved successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_save_to_file_finish(GVirDomain *dom,
Packit a07778
                                         GAsyncResult *result,
Packit a07778
                                         GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_config:
Packit a07778
 * @dom: the domain
Packit a07778
 * @flags: the %GVirDomainXMLFlags flags
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the config. The returned object should be
Packit a07778
 * unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirConfigDomain *gvir_domain_get_config(GVirDomain *dom,
Packit a07778
                                         guint flags,
Packit a07778
                                         GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    gchar *xml;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (!(xml = virDomainGetXMLDesc(priv->handle, flags))) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to get domain XML config");
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    GVirConfigDomain *conf = gvir_config_domain_new_from_xml(xml, err);
Packit a07778
    g_free(xml);
Packit a07778
    if ((err != NULL) && (*err != NULL))
Packit a07778
        return NULL;
Packit a07778
Packit a07778
    return conf;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_set_config:
Packit a07778
 * @domain: the domain
Packit a07778
 * @conf: the new configuration for the domain
Packit a07778
 * @err: (allow-none): Place-holder for error or NULL
Packit a07778
 *
Packit a07778
 * Resets configuration of an existing domain.
Packit a07778
 *
Packit a07778
 * Note: If domain is already running, the new configuration will not take
Packit a07778
 * affect until domain reboots.
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success, FALSE if an error occurred.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_set_config(GVirDomain *domain,
Packit a07778
                                GVirConfigDomain *conf,
Packit a07778
                                GError **err)
Packit a07778
{
Packit a07778
    gchar *xml;
Packit a07778
    virConnectPtr conn;
Packit a07778
    virDomainPtr handle;
Packit a07778
    gchar uuid[VIR_UUID_STRING_BUFLEN];
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN (domain), FALSE);
Packit a07778
    g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN (conf), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = domain->priv;
Packit a07778
    xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(conf));
Packit a07778
Packit a07778
    g_return_val_if_fail(xml != NULL, FALSE);
Packit a07778
Packit a07778
    if ((conn = virDomainGetConnect(priv->handle)) == NULL) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Failed to get domain connection");
Packit a07778
        g_free (xml);
Packit a07778
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    handle = virDomainDefineXML(conn, xml);
Packit a07778
    g_free (xml);
Packit a07778
Packit a07778
    if (handle == NULL) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Failed to set "
Packit a07778
                               "domain configuration");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    virDomainGetUUIDString(handle, uuid);
Packit a07778
    virDomainFree(handle);
Packit a07778
Packit a07778
    if (g_strcmp0 (uuid, priv->uuid) != 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Failed to set "
Packit a07778
                               "domain configuration");
Packit a07778
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_info:
Packit a07778
 * @dom: the domain
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the info. The returned structure should be
Packit a07778
 * freed using #g_boxed_free() with GVIR_TYPE_DOMAIN_INFO as the first argument
Packit a07778
 * when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomainInfo *gvir_domain_get_info(GVirDomain *dom,
Packit a07778
                                     GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    virDomainInfo info;
Packit a07778
    GVirDomainInfo *ret;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    if (virDomainGetInfo(priv->handle, &info) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to get domain info");
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = g_slice_new(GVirDomainInfo);
Packit a07778
    ret->state = info.state;
Packit a07778
    ret->maxMem = info.maxMem;
Packit a07778
    ret->memory = info.memory;
Packit a07778
    ret->nrVirtCpu = info.nrVirtCpu;
Packit a07778
    ret->cpuTime = info.cpuTime;
Packit a07778
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_get_info_helper(GTask *task,
Packit a07778
                            gpointer source_object,
Packit a07778
                            gpointer task_data G_GNUC_UNUSED,
Packit a07778
                            GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    GVirDomainInfo *info;
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    info = gvir_domain_get_info(dom, &err;;
Packit a07778
    if (err)
Packit a07778
        g_task_return_error(task, err);
Packit a07778
    else
Packit a07778
        g_task_return_pointer(task,
Packit a07778
                              info,
Packit a07778
                              (GDestroyNotify) gvir_domain_info_free);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_info_async:
Packit a07778
 * @dom: the domain
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_domain_get_info.
Packit a07778
 */
Packit a07778
void gvir_domain_get_info_async(GVirDomain *dom,
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_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_get_info_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_info_finish:
Packit a07778
 * @dom: the domain
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_domain_get_info_async.
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): the info. The returned object should be
Packit a07778
 * unreffed with g_object_unref() when no longer needed.
Packit a07778
 */
Packit a07778
GVirDomainInfo *gvir_domain_get_info_finish(GVirDomain *dom,
Packit a07778
                                            GAsyncResult *result,
Packit a07778
                                            GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    return g_task_propagate_pointer(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_screenshot:
Packit a07778
 * @stream: stream to use as output
Packit a07778
 * @monitor_id: monitor ID to take screenshot from
Packit a07778
 * @flags: extra flags, currently unused
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): a newly allocated string containing the
Packit a07778
 * mime-type of the image format, or NULL upon error.
Packit a07778
 */
Packit a07778
gchar *gvir_domain_screenshot(GVirDomain *dom,
Packit a07778
                              GVirStream *stream,
Packit a07778
                              guint monitor_id,
Packit a07778
                              guint flags,
Packit a07778
                              GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    virStreamPtr st = NULL;
Packit a07778
    gchar *mime = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
    g_return_val_if_fail(GVIR_IS_STREAM(stream), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    g_object_get(stream, "handle", &st, NULL);
Packit a07778
Packit a07778
    if (!(mime = virDomainScreenshot(priv->handle,
Packit a07778
                                     st,
Packit a07778
                                     monitor_id,
Packit a07778
                                     flags))) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to take a screenshot");
Packit a07778
        goto end;
Packit a07778
    }
Packit a07778
end:
Packit a07778
    if (st != NULL)
Packit a07778
        virStreamFree(st);
Packit a07778
    return mime;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_open_console:
Packit a07778
 * @dom: (transfer none): the domain
Packit a07778
 * @devname: (transfer none)(allow-none): the device name
Packit a07778
 * @stream: (transfer none): stream to use as output
Packit a07778
 * @flags: extra flags, currently unused
Packit a07778
 *
Packit a07778
 * Open a text console for the domain @dom, connecting it to the
Packit a07778
 * stream @stream. If @devname is NULL, the default console will
Packit a07778
 * be opened, otherwise @devname can be used to specify a non-default
Packit a07778
 * console device.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if the console was opened, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_open_console(GVirDomain *dom,
Packit a07778
                                  GVirStream *stream,
Packit a07778
                                  const gchar *devname,
Packit a07778
                                  guint flags,
Packit a07778
                                  GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    virStreamPtr st = NULL;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(GVIR_IS_STREAM(stream), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
    g_object_get(stream, "handle", &st, NULL);
Packit a07778
Packit a07778
    if (virDomainOpenConsole(priv->handle,
Packit a07778
                             devname,
Packit a07778
                             st,
Packit a07778
                             flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to open console");
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
cleanup:
Packit a07778
    if (st != NULL)
Packit a07778
        virStreamFree(st);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_open_graphics:
Packit a07778
 * @dom: the domain
Packit a07778
 * @idx: the graphics index
Packit a07778
 * @fd: pre-opened socket pair
Packit a07778
 * @flags: extra flags, currently unused
Packit a07778
 *
Packit a07778
 * Open a connection to the local graphics display, connecting it to the
Packit a07778
 * socket pair file descriptor passed in as @fd.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if the graphics connection was opened, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_open_graphics(GVirDomain *dom,
Packit a07778
                                   guint idx,
Packit a07778
                                   int fd,
Packit a07778
                                   unsigned int flags,
Packit a07778
                                   GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
Packit a07778
    if (virDomainOpenGraphics(priv->handle,
Packit a07778
                              idx,
Packit a07778
                              fd,
Packit a07778
                              flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to open graphics");
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
cleanup:
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_open_graphics_fd:
Packit a07778
 * @dom: the domain
Packit a07778
 * @idx: the graphics index
Packit a07778
 * @flags: extra flags, currently unused
Packit a07778
 *
Packit a07778
 * This will create a socket pair connected to the graphics backend of @dom. One
Packit a07778
 * end of the socket will be returned on success, and the other end is handed to
Packit a07778
 * the hypervisor. If @dom has multiple graphics backends configured, then @idx
Packit a07778
 * will determine which one is opened, starting from @idx 0.
Packit a07778
 *
Packit a07778
 * Returns: An fd on success, -1 on failure.
Packit a07778
 *
Packit a07778
 * Since: 0.2.0
Packit a07778
 */
Packit a07778
#if defined(HAVE_VIR_DOMAIN_OPEN_GRAPHICS_FD) || !defined(G_OS_WIN32)
Packit a07778
int gvir_domain_open_graphics_fd(GVirDomain *dom,
Packit a07778
                                 guint idx,
Packit a07778
                                 unsigned int flags,
Packit a07778
                                 GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    int ret = -1;
Packit a07778
#ifndef HAVE_VIR_DOMAIN_OPEN_GRAPHICS_FD
Packit a07778
    int pair[2];
Packit a07778
#endif
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), -1);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, -1);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
Packit a07778
#ifdef HAVE_VIR_DOMAIN_OPEN_GRAPHICS_FD
Packit a07778
    ret = virDomainOpenGraphicsFD(priv->handle, idx, flags);
Packit a07778
    if (ret <= 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to open graphics");
Packit a07778
        goto end;
Packit a07778
    }
Packit a07778
Packit a07778
#else
Packit a07778
    if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) < 0) {
Packit a07778
        g_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                            0,
Packit a07778
                            "Failed to create socket pair");
Packit a07778
        goto end;
Packit a07778
    }
Packit a07778
Packit a07778
    if (virDomainOpenGraphics(priv->handle, idx, pair[0], flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to open graphics");
Packit a07778
        close(pair[0]);
Packit a07778
        close(pair[1]);
Packit a07778
Packit a07778
        goto end;
Packit a07778
    }
Packit a07778
    close(pair[0]);
Packit a07778
    ret = pair[1];
Packit a07778
#endif
Packit a07778
Packit a07778
end:
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
#else
Packit a07778
int gvir_domain_open_graphics_fd(GVirDomain *dom G_GNUC_UNUSED,
Packit a07778
                                 guint idx G_GNUC_UNUSED,
Packit a07778
                                 unsigned int flags G_GNUC_UNUSED,
Packit a07778
                                 GError **err)
Packit a07778
{
Packit a07778
    g_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                        0,
Packit a07778
                        "Unable to create socketpair on this platform");
Packit a07778
    return -1;
Packit a07778
}
Packit a07778
#endif
Packit a07778
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_suspend:
Packit a07778
 * @dom: the domain to suspend
Packit a07778
 * @err: Place-holder for possible errors
Packit a07778
 *
Packit a07778
 * Suspends an active domain, the process is frozen without further access to
Packit a07778
 * CPU resources and I/O but the memory used by the domain at the hypervisor
Packit a07778
 * level will stay allocated. Use gvir_domain_resume() to reactivate the domain.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain was suspended successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_suspend (GVirDomain *dom,
Packit a07778
                              GError **err)
Packit a07778
{
Packit a07778
    gboolean ret = FALSE;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    if (virDomainSuspend(dom->priv->handle) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to suspend domain");
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
cleanup:
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_save:
Packit a07778
 * @dom: the domain to save
Packit a07778
 * @flags: extra flags, currently unused
Packit a07778
 * @err: Place-holder for possible errors
Packit a07778
 *
Packit a07778
 * Saves the state of the domain on disk and stops it. Use #gvir_domain_start
Packit a07778
 * to restore the saved state of the domain. A saved domain can be restored
Packit a07778
 * even after shutdown/reboot of host machine.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain was saved successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_save (GVirDomain *dom,
Packit a07778
                           unsigned int flags,
Packit a07778
                           GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    if (virDomainManagedSave(dom->priv->handle, flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to save domain");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_save_helper(GTask *task,
Packit a07778
                        gpointer source_object,
Packit a07778
                        gpointer task_data,
Packit a07778
                        GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(source_object);
Packit a07778
    guint flags = GPOINTER_TO_UINT(task_data);
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_save(dom, flags, &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_domain_save_async:
Packit a07778
 * @dom: the domain to save
Packit a07778
 * @flags: extra flags, currently unused
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_domain_save.
Packit a07778
 */
Packit a07778
void gvir_domain_save_async (GVirDomain *dom,
Packit a07778
                             unsigned int flags,
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_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    g_task_set_task_data(task, GUINT_TO_POINTER(flags), NULL);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_save_helper);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_save_finish:
Packit a07778
 * @dom: the domain to save
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_domain_save_async.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain was saved successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_save_finish (GVirDomain *dom,
Packit a07778
                                  GAsyncResult *result,
Packit a07778
                                  GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_persistent:
Packit a07778
 * @dom: the domain
Packit a07778
 *
Packit a07778
 * Returns: TRUE if domain is persistent, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_get_persistent(GVirDomain *dom)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
Packit a07778
    return virDomainIsPersistent(dom->priv->handle) == 1;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_saved:
Packit a07778
 * @dom: the domain
Packit a07778
 *
Packit a07778
 * Returns: TRUE if a stopped domain has a saved state to which it can be
Packit a07778
 * restored to using #gvir_domain_start, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_get_saved(GVirDomain *dom)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
Packit a07778
    return virDomainHasManagedSaveImage(dom->priv->handle, 0) == 1;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_devices:
Packit a07778
 * @domain: the domain
Packit a07778
 * @err: place-holder for possible errors, or NULL
Packit a07778
 *
Packit a07778
 * Gets the list of devices attached to @domain. The returned list should
Packit a07778
 * be freed with g_list_free(), after its elements have been unreffed with
Packit a07778
 * g_object_unref().
Packit a07778
 *
Packit a07778
 * Returns: (element-type LibvirtGObject.DomainDevice) (transfer full): a newly
Packit a07778
 * allocated #GList of #GVirDomainDevice.
Packit a07778
 */
Packit a07778
GList *gvir_domain_get_devices(GVirDomain *domain,
Packit a07778
                               GError **err)
Packit a07778
{
Packit a07778
    GVirConfigDomain *config;
Packit a07778
    GList *config_devices;
Packit a07778
    GList *node;
Packit a07778
    GList *ret = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(domain), NULL);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    config = gvir_domain_get_config(domain, 0, err);
Packit a07778
    if (config == NULL)
Packit a07778
        return NULL;
Packit a07778
Packit a07778
    config_devices = gvir_config_domain_get_devices(config);
Packit a07778
    for (node = config_devices; node != NULL; node = node->next) {
Packit a07778
        GVirConfigDomainDevice *device_config;
Packit a07778
        GVirDomainDevice *device;
Packit a07778
Packit a07778
        device_config = GVIR_CONFIG_DOMAIN_DEVICE(node->data);
Packit a07778
        device = gvir_domain_device_new(domain, device_config);
Packit a07778
        if (device != NULL)
Packit a07778
             ret = g_list_prepend(ret, device);
Packit a07778
Packit a07778
        g_object_unref (device_config);
Packit a07778
    }
Packit a07778
    g_list_free (config_devices);
Packit a07778
Packit a07778
    return g_list_reverse (ret);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_update_device:
Packit a07778
 * @dom: the domain
Packit a07778
 * @device: A modified device config
Packit a07778
 * @flags: bitwise-OR of #GVirDomainUpdateDeviceFlags
Packit a07778
 * @err: (allow-none):Place-holder for error or NULL
Packit a07778
 *
Packit a07778
 * Update the configuration of a device.
Packit a07778
 *
Packit a07778
 * Returns: TRUE if device was updated successfully, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean
Packit a07778
gvir_domain_update_device(GVirDomain *dom,
Packit a07778
                          GVirConfigDomainDevice *device,
Packit a07778
                          guint flags,
Packit a07778
                          GError **err)
Packit a07778
{
Packit a07778
    gchar *xml;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
    g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_DEVICE(device), FALSE);
Packit a07778
Packit a07778
    xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(device));
Packit a07778
    g_return_val_if_fail(xml != NULL, FALSE);
Packit a07778
Packit a07778
    if (virDomainUpdateDeviceFlags(dom->priv->handle,
Packit a07778
                                   xml, flags) < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Failed to update device");
Packit a07778
        g_free (xml);
Packit a07778
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    g_free (xml);
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_create_snapshot:
Packit a07778
 * @dom: the domain
Packit a07778
 * @custom_conf: (allow-none): configuration of snapshot or NULL
Packit a07778
 * @flags: bitwise-OR of #GVirDomainSnapshotCreateFlags
Packit a07778
 * @err: (allow-none):Place-holder for error or NULL
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): snapshot of domain. The returned object should be
Packit a07778
 * unreffed when no longer needed
Packit a07778
 */
Packit a07778
GVirDomainSnapshot *
Packit a07778
gvir_domain_create_snapshot(GVirDomain *dom,
Packit a07778
                             GVirConfigDomainSnapshot *custom_conf,
Packit a07778
                             guint flags,
Packit a07778
                             GError **err)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    virDomainSnapshot *snapshot;
Packit a07778
    GVirDomainSnapshot *dom_snapshot;
Packit a07778
    gchar *custom_xml = NULL;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
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
    if (!(snapshot = virDomainSnapshotCreateXML(priv->handle,
Packit a07778
                                                custom_xml,
Packit a07778
                                                flags))) {
Packit a07778
        const gchar *domain_name = NULL;
Packit a07778
        domain_name = gvir_domain_get_name(dom);
Packit a07778
Packit a07778
        gvir_set_error(err, GVIR_DOMAIN_ERROR,
Packit a07778
                       0,
Packit a07778
                      "Unable to create snapshot of %s", domain_name);
Packit a07778
Packit a07778
        g_free(custom_xml);
Packit a07778
        return NULL;
Packit a07778
    }
Packit a07778
Packit a07778
    dom_snapshot = GVIR_DOMAIN_SNAPSHOT(g_object_new(GVIR_TYPE_DOMAIN_SNAPSHOT,
Packit a07778
                                                     "handle",
Packit a07778
                                                     snapshot,
Packit a07778
                                                     NULL));
Packit a07778
Packit a07778
    g_free(custom_xml);
Packit a07778
    return dom_snapshot;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
static void _create_snapshot_async_thread(GTask *task,
Packit a07778
                                          gpointer source_object,
Packit a07778
                                          gpointer task_data,
Packit a07778
                                          GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GError *error = NULL;
Packit a07778
    GVirDomainSnapshot *snapshot;
Packit a07778
    SnapshotCreateData *create_data = task_data;
Packit a07778
Packit a07778
    snapshot = gvir_domain_create_snapshot(source_object,
Packit a07778
                                           create_data->snapshot_config,
Packit a07778
                                           create_data->create_flags,
Packit a07778
                                           &error);
Packit a07778
    if (snapshot)
Packit a07778
        g_task_return_pointer(task, snapshot, g_object_unref);
Packit a07778
    else
Packit a07778
        g_task_return_error(task, error);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_create_snapshot_async:
Packit a07778
 * @dom: The #GVirDomain
Packit a07778
 * @custom_conf: (allow-none): Configuration of snapshot or %NULL
Packit a07778
 * @flags: Bitwise-OR of #GVirDomainSnapshotCreateFlags
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_domain_create_snapshot_async(GVirDomain *dom,
Packit a07778
                                       GVirConfigDomainSnapshot *custom_conf,
Packit a07778
                                       guint flags,
Packit a07778
                                       GCancellable *cancellable,
Packit a07778
                                       GAsyncReadyCallback callback,
Packit a07778
                                       gpointer user_data)
Packit a07778
{
Packit a07778
    SnapshotCreateData *create_data;
Packit a07778
    GTask *task;
Packit a07778
Packit a07778
    g_return_if_fail(GVIR_IS_DOMAIN(dom));
Packit a07778
    g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_SNAPSHOT(custom_conf));
Packit a07778
Packit a07778
    create_data = g_slice_new(SnapshotCreateData);
Packit a07778
    create_data->create_flags = flags;
Packit a07778
    create_data->snapshot_config = g_object_ref (custom_conf);
Packit a07778
Packit a07778
    task = g_task_new(dom, cancellable, callback, user_data);
Packit a07778
    g_task_set_task_data(task, create_data, (GDestroyNotify)snapshot_create_data_free);
Packit a07778
    g_task_run_in_thread(task, _create_snapshot_async_thread);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_create_snapshot_finish:
Packit a07778
 * @domain: A #GVirDomain
Packit a07778
 * @result: (transfer none): Async method result
Packit a07778
 * @error: (allow-none): Error placeholder
Packit a07778
 *
Packit a07778
 * Returns: (transfer full): The created snapshot
Packit a07778
 */
Packit a07778
GVirDomainSnapshot *gvir_domain_create_snapshot_finish(GVirDomain  *domain,
Packit a07778
                                                       GAsyncResult *result,
Packit a07778
                                                       GError **error)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, domain), NULL);
Packit a07778
    g_return_val_if_fail(error == NULL || *error == NULL, NULL);
Packit a07778
Packit a07778
    return g_task_propagate_pointer(G_TASK(result), error);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_fetch_snapshots:
Packit a07778
 * @dom: The domain
Packit a07778
 * @list_flags: bitwise-OR of #GVirDomainSnapshotListFlags
Packit a07778
 * @cancellable: (allow-none) (transfer none): cancellation object
Packit a07778
 * @error: (allow-none): Place-holder for error or %NULL
Packit a07778
 *
Packit a07778
 * Returns: %TRUE on success, %FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_fetch_snapshots(GVirDomain *dom,
Packit a07778
                                     guint list_flags,
Packit a07778
                                     GCancellable *cancellable,
Packit a07778
                                     GError **error)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    virDomainSnapshotPtr *snapshots = NULL;
Packit a07778
    GVirDomainSnapshot *snap;
Packit a07778
    GHashTable *snap_table;
Packit a07778
    int n_snaps = 0;
Packit a07778
    int i;
Packit a07778
    gboolean ret = FALSE;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
Packit a07778
    snap_table = 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
    n_snaps = virDomainListAllSnapshots(priv->handle, &snapshots, list_flags);
Packit a07778
Packit a07778
    if (g_cancellable_set_error_if_cancelled(cancellable, error)) {
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    if (n_snaps < 0) {
Packit a07778
        gvir_set_error(error, GVIR_DOMAIN_ERROR, 0,
Packit a07778
                       "Unable to fetch snapshots of %s",
Packit a07778
                       gvir_domain_get_name(dom));
Packit a07778
        goto cleanup;
Packit a07778
    }
Packit a07778
Packit a07778
    for (i = 0; i < n_snaps; i ++) {
Packit a07778
        if (g_cancellable_set_error_if_cancelled(cancellable, error)) {
Packit a07778
            goto cleanup;
Packit a07778
        }
Packit a07778
        snap = GVIR_DOMAIN_SNAPSHOT(g_object_new(GVIR_TYPE_DOMAIN_SNAPSHOT,
Packit a07778
                                                 "handle", snapshots[i],
Packit a07778
                                                 NULL));
Packit a07778
        g_hash_table_insert(snap_table,
Packit a07778
                            (gpointer)gvir_domain_snapshot_get_name(snap),
Packit a07778
                            snap);
Packit a07778
    }
Packit a07778
Packit a07778
Packit a07778
    g_mutex_lock(priv->lock);
Packit a07778
    if (priv->snapshots != NULL)
Packit a07778
        g_hash_table_unref(priv->snapshots);
Packit a07778
    priv->snapshots = snap_table;
Packit a07778
    snap_table = NULL;
Packit a07778
    g_mutex_unlock(priv->lock);
Packit a07778
Packit a07778
    ret = TRUE;
Packit a07778
Packit a07778
cleanup:
Packit a07778
    free(snapshots);
Packit a07778
    if (snap_table != NULL)
Packit a07778
        g_hash_table_unref(snap_table);
Packit a07778
    return ret;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_snapshots:
Packit a07778
 * @dom: The domain
Packit a07778
 * Returns: (element-type LibvirtGObject.DomainSnapshot) (transfer full): A
Packit a07778
 * list of all the snapshots available for the given domain. The returned
Packit a07778
 * list should be freed with g_list_free(), after its elements have been
Packit a07778
 * unreffed with g_object_unref().
Packit a07778
 */
Packit a07778
GList *gvir_domain_get_snapshots(GVirDomain *dom)
Packit a07778
{
Packit a07778
    GVirDomainPrivate *priv;
Packit a07778
    GList *snapshots = NULL;
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), NULL);
Packit a07778
Packit a07778
    priv = dom->priv;
Packit a07778
Packit a07778
    g_mutex_lock (priv->lock);
Packit a07778
    if (dom->priv->snapshots != NULL) {
Packit a07778
        snapshots = g_hash_table_get_values(priv->snapshots);
Packit a07778
        g_list_foreach(snapshots, (GFunc)g_object_ref, NULL);
Packit a07778
    }
Packit a07778
    g_mutex_unlock (priv->lock);
Packit a07778
Packit a07778
    return snapshots;
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
Packit a07778
static void _fetch_snapshots_async_thread(GTask *task,
Packit a07778
                                          gpointer source_object,
Packit a07778
                                          gpointer task_data,
Packit a07778
                                          GCancellable *cancellable)
Packit a07778
{
Packit a07778
    GError *error = NULL;
Packit a07778
    gboolean status;
Packit a07778
Packit a07778
    status = gvir_domain_fetch_snapshots(source_object,
Packit a07778
                                         GPOINTER_TO_UINT(task_data),
Packit a07778
                                         cancellable,
Packit a07778
                                         &error);
Packit a07778
    if (status)
Packit a07778
        g_task_return_boolean(task, TRUE);
Packit a07778
    else
Packit a07778
        g_task_return_error(task, error);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_fetch_snapshots_async:
Packit a07778
 * @dom: The domain
Packit a07778
 * @list_flags: bitwise-OR of #GVirDomainSnapshotListFlags
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_domain_fetch_snapshots_async(GVirDomain *dom,
Packit a07778
                                       guint list_flags,
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_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
Packit a07778
    task = g_task_new(dom, cancellable, callback, user_data);
Packit a07778
    g_task_set_task_data(task, GUINT_TO_POINTER(list_flags), NULL);
Packit a07778
    g_task_run_in_thread(task, _fetch_snapshots_async_thread);
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_fetch_snapshots_finish:
Packit a07778
 * @dom: a #GVirDomain
Packit a07778
 * @res: (transfer none): async method result
Packit a07778
 *
Packit a07778
 * Returns: TRUE on success, FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_fetch_snapshots_finish(GVirDomain *dom,
Packit a07778
                                            GAsyncResult *res,
Packit a07778
                                            GError **error)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(res, dom), FALSE);
Packit a07778
    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(res), error);
Packit a07778
}
Packit a07778
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_get_has_current_snapshot:
Packit a07778
 * @dom: a #GVirDomain
Packit a07778
 * @flags: Unused, pass 0
Packit a07778
 * @has_current_snapshot: (out): Will be set to %TRUE if the given domain
Packit a07778
 * has a current snapshot and to %FALSE otherwise.
Packit a07778
 * @error: (allow-none): Place-holder for error or %NULL
Packit a07778
 *
Packit a07778
 * Returns: %TRUE on success, %FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_get_has_current_snapshot(GVirDomain *dom,
Packit a07778
                                              guint flags,
Packit a07778
                                              gboolean *has_current_snapshot,
Packit a07778
                                              GError **error)
Packit a07778
{
Packit a07778
    int status;
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(has_current_snapshot != NULL, FALSE);
Packit a07778
    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
Packit a07778
Packit a07778
    status = virDomainHasCurrentSnapshot(dom->priv->handle,
Packit a07778
                                         flags);
Packit a07778
Packit a07778
    if (status == -1) {
Packit a07778
        gvir_set_error(error, GVIR_DOMAIN_ERROR, 0,
Packit a07778
                       "Unable to check if domain `%s' has a current snapshot",
Packit a07778
                       gvir_domain_get_name(dom));
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    *has_current_snapshot = status;
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_set_time:
Packit a07778
 * @dom: the domain
Packit a07778
 * @date_time: (allow-none)(transfer none): the time to set as #GDateTime.
Packit a07778
 * @flags: Unused, pass 0.
Packit a07778
 * @err: (allow-none): Place-holder for error or %NULL
Packit a07778
 *
Packit a07778
 * This function tries to set guest time to the given value. The passed
Packit a07778
 * time must in UTC.
Packit a07778
 *
Packit a07778
 * If @date_time is %NULL, the time is reset using the domain's RTC.
Packit a07778
 *
Packit a07778
 * Please note that some hypervisors may require guest agent to be configured
Packit a07778
 * and running in order for this function to work.
Packit a07778
 *
Packit a07778
 * Returns: %TRUE on success, %FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_set_time(GVirDomain *dom,
Packit a07778
                              GDateTime *date_time,
Packit a07778
                              guint flags,
Packit a07778
                              GError **err)
Packit a07778
{
Packit a07778
    int ret;
Packit a07778
    GTimeVal tv;
Packit a07778
    glong seconds;
Packit a07778
    glong nseconds;
Packit a07778
    guint settime_flags;
Packit a07778
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
    g_return_val_if_fail(flags == 0, FALSE);
Packit a07778
Packit a07778
    if (date_time != NULL) {
Packit a07778
        if (!g_date_time_to_timeval(date_time, &tv)) {
Packit a07778
            g_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                                0,
Packit a07778
                                "Failed to parse given time argument");
Packit a07778
            return FALSE;
Packit a07778
        }
Packit a07778
Packit a07778
        seconds = tv.tv_sec;
Packit a07778
        nseconds = tv.tv_usec * 1000;
Packit a07778
        settime_flags = 0;
Packit a07778
    } else {
Packit a07778
        seconds = 0;
Packit a07778
        nseconds = 0;
Packit a07778
        settime_flags = VIR_DOMAIN_TIME_SYNC;
Packit a07778
    }
Packit a07778
Packit a07778
    ret = virDomainSetTime(dom->priv->handle, seconds, nseconds, settime_flags);
Packit a07778
    if (ret < 0) {
Packit a07778
        gvir_set_error_literal(err, GVIR_DOMAIN_ERROR,
Packit a07778
                               0,
Packit a07778
                               "Unable to set domain time");
Packit a07778
        return FALSE;
Packit a07778
    }
Packit a07778
Packit a07778
    return TRUE;
Packit a07778
}
Packit a07778
Packit a07778
static void
Packit a07778
gvir_domain_set_time_helper(GTask *task,
Packit a07778
                            gpointer object,
Packit a07778
                            gpointer task_data,
Packit a07778
                            GCancellable *cancellable G_GNUC_UNUSED)
Packit a07778
{
Packit a07778
    GVirDomain *dom = GVIR_DOMAIN(object);
Packit a07778
    GDateTime *date_time = (GDateTime *) task_data;
Packit a07778
    GError *err = NULL;
Packit a07778
Packit a07778
    if (!gvir_domain_set_time(dom, date_time, 0, &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_domain_set_time_async:
Packit a07778
 * @dom: the domain
Packit a07778
 * @date_time: (allow-none)(transfer none): the time to set as #GDateTime.
Packit a07778
 * @flags: bitwise-OR of #GVirDomainSetTimeFlags.
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_domain_set_time.
Packit a07778
 */
Packit a07778
void gvir_domain_set_time_async(GVirDomain *dom,
Packit a07778
                                GDateTime *date_time,
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
Packit a07778
    g_return_if_fail(GVIR_IS_DOMAIN(dom));
Packit a07778
    g_return_if_fail((cancellable == NULL) || G_IS_CANCELLABLE(cancellable));
Packit a07778
    g_return_if_fail(flags == 0);
Packit a07778
Packit a07778
    task = g_task_new(G_OBJECT(dom),
Packit a07778
                      cancellable,
Packit a07778
                      callback,
Packit a07778
                      user_data);
Packit a07778
    if (date_time != NULL)
Packit a07778
        g_task_set_task_data(task,
Packit a07778
                             g_date_time_ref(date_time),
Packit a07778
                             (GDestroyNotify)g_date_time_unref);
Packit a07778
    g_task_run_in_thread(task, gvir_domain_set_time_helper);
Packit a07778
Packit a07778
    g_object_unref(task);
Packit a07778
}
Packit a07778
Packit a07778
/**
Packit a07778
 * gvir_domain_set_time_finish:
Packit a07778
 * @dom: the domain
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_domain_set_time_async.
Packit a07778
 *
Packit a07778
 * Returns: %TRUE on success, %FALSE otherwise.
Packit a07778
 */
Packit a07778
gboolean gvir_domain_set_time_finish(GVirDomain *dom,
Packit a07778
                                     GAsyncResult *result,
Packit a07778
                                     GError **err)
Packit a07778
{
Packit a07778
    g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
Packit a07778
    g_return_val_if_fail(g_task_is_valid(result, G_OBJECT(dom)), FALSE);
Packit a07778
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
Packit a07778
Packit a07778
    return g_task_propagate_boolean(G_TASK(result), err);
Packit a07778
}