[libvirt] [PATCH 03/12] Move virDomainSnapshot related APIs out of libvirt.c

Daniel P. Berrange berrange at redhat.com
Wed Oct 22 17:14:53 UTC 2014


Introduce a src/libvirt-domain-snapshot.c file to hold all the
methods related to the virDomainSnapshot type.
---
 docs/apibuild.py              |    1 +
 po/POTFILES.in                |    1 +
 src/Makefile.am               |    2 +
 src/datatypes.h               |    1 +
 src/libvirt-domain-snapshot.c | 1222 +++++++++++++++++++++++++++++++++++++++++
 src/libvirt.c                 | 1194 ----------------------------------------
 6 files changed, 1227 insertions(+), 1194 deletions(-)
 create mode 100644 src/libvirt-domain-snapshot.c

diff --git a/docs/apibuild.py b/docs/apibuild.py
index 30e224d..b5bd936 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -24,6 +24,7 @@ included_files = {
   "libvirt.h": "header with general libvirt API definitions",
   "virterror.h": "header with error specific API definitions",
   "libvirt.c": "Main interfaces for the libvirt library",
+  "libvirt-domain-snapshot.c": "Domain snapshot interfaces for the libvirt library",
   "virerror.c": "implements error handling and reporting code for libvirt",
   "virevent.c": "event loop for monitoring file handles",
   "virtypedparam.c": "virTypedParameters APIs",
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 59be2e6..6f88a15 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -57,6 +57,7 @@ src/interface/interface_backend_netcf.c
 src/interface/interface_backend_udev.c
 src/internal.h
 src/libvirt.c
+src/libvirt-domain-snapshot.c
 src/libvirt-lxc.c
 src/libvirt-qemu.c
 src/locking/lock_daemon.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7521bde..1b0a97d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -189,6 +189,7 @@ DRIVER_SOURCES =							\
 		fdstream.c fdstream.h					\
 		$(NODE_INFO_SOURCES)					\
 		libvirt.c libvirt_internal.h				\
+		libvirt-domain-snapshot.c 				\
 		locking/lock_manager.c locking/lock_manager.h		\
 		locking/lock_driver.h					\
 		locking/lock_driver_nop.h locking/lock_driver_nop.c	\
@@ -2186,6 +2187,7 @@ libvirt_setuid_rpc_client_la_SOURCES = 		\
 		remote/lxc_protocol.c		\
 		datatypes.c			\
 		libvirt.c			\
+		libvirt-domain-snapshot.c	\
 		libvirt-lxc.c			\
 		$(NULL)
 
diff --git a/src/datatypes.h b/src/datatypes.h
index 5868ce3..1d6c382 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -27,6 +27,7 @@
 # include "driver.h"
 # include "virthread.h"
 # include "virobject.h"
+# include "viruuid.h"
 
 extern virClassPtr virConnectClass;
 extern virClassPtr virDomainClass;
diff --git a/src/libvirt-domain-snapshot.c b/src/libvirt-domain-snapshot.c
new file mode 100644
index 0000000..3b41a37
--- /dev/null
+++ b/src/libvirt-domain-snapshot.c
@@ -0,0 +1,1222 @@
+/*
+ * libvirt-domain-snapshot.c: entry points for virDomainSnapshotPtr APIs
+ *
+ * Copyright (C) 2006-2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "datatypes.h"
+#include "virlog.h"
+
+VIR_LOG_INIT("libvirt.domain-snapshot");
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+/**
+ * virDomainSnapshotGetName:
+ * @snapshot: a snapshot object
+ *
+ * Get the public name for that snapshot
+ *
+ * Returns a pointer to the name or NULL, the string need not be deallocated
+ * as its lifetime will be the same as the snapshot object.
+ */
+const char *
+virDomainSnapshotGetName(virDomainSnapshotPtr snapshot)
+{
+    VIR_DEBUG("snapshot=%p", snapshot);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, NULL);
+
+    return snapshot->name;
+}
+
+
+/**
+ * virDomainSnapshotGetDomain:
+ * @snapshot: a snapshot object
+ *
+ * Provides the domain pointer associated with a snapshot.  The
+ * reference counter on the domain is not increased by this
+ * call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do not use this
+ * function.  Instead, store the domain and the snapshot object together.
+ *
+ * Returns the domain or NULL.
+ */
+virDomainPtr
+virDomainSnapshotGetDomain(virDomainSnapshotPtr snapshot)
+{
+    VIR_DEBUG("snapshot=%p", snapshot);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, NULL);
+
+    return snapshot->domain;
+}
+
+
+/**
+ * virDomainSnapshotGetConnect:
+ * @snapshot: a snapshot object
+ *
+ * Provides the connection pointer associated with a snapshot.  The
+ * reference counter on the connection is not increased by this
+ * call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do not use this
+ * function.  Instead, store the connection and the snapshot object together.
+ *
+ * Returns the connection or NULL.
+ */
+virConnectPtr
+virDomainSnapshotGetConnect(virDomainSnapshotPtr snapshot)
+{
+    VIR_DEBUG("snapshot=%p", snapshot);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, NULL);
+
+    return snapshot->domain->conn;
+}
+
+
+/**
+ * virDomainSnapshotCreateXML:
+ * @domain: a domain object
+ * @xmlDesc: string containing an XML description of the domain
+ * @flags: bitwise-OR of virDomainSnapshotCreateFlags
+ *
+ * Creates a new snapshot of a domain based on the snapshot xml
+ * contained in xmlDesc.
+ *
+ * If @flags is 0, the domain can be active, in which case the
+ * snapshot will be a system checkpoint (both disk state and runtime
+ * VM state such as RAM contents), where reverting to the snapshot is
+ * the same as resuming from hibernation (TCP connections may have
+ * timed out, but everything else picks up where it left off); or
+ * the domain can be inactive, in which case the snapshot includes
+ * just the disk state prior to booting.  The newly created snapshot
+ * becomes current (see virDomainSnapshotCurrent()), and is a child
+ * of any previous current snapshot.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, then this
+ * is a request to reinstate snapshot metadata that was previously
+ * discarded, rather than creating a new snapshot.  This can be used
+ * to recreate a snapshot hierarchy on a destination, then remove it
+ * on the source, in order to allow migration (since migration
+ * normally fails if snapshot metadata still remains on the source
+ * machine).  When redefining snapshot metadata, the current snapshot
+ * will not be altered unless the VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT
+ * flag is also present.  It is an error to request the
+ * VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flag without
+ * VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.  On some hypervisors,
+ * redefining an existing snapshot can be used to alter host-specific
+ * portions of the domain XML to be used during revert (such as
+ * backing filenames associated with disk devices), but must not alter
+ * guest-visible layout.  When redefining a snapshot name that does
+ * not exist, the hypervisor may validate that reverting to the
+ * snapshot appears to be possible (for example, disk images have
+ * snapshot contents by the requested name).  Not all hypervisors
+ * support these flags.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, then the
+ * domain's disk images are modified according to @xmlDesc, but then
+ * the just-created snapshot has its metadata deleted.  This flag is
+ * incompatible with VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_HALT, then the domain
+ * will be inactive after the snapshot completes, regardless of whether
+ * it was active before; otherwise, a running domain will still be
+ * running after the snapshot.  This flag is invalid on transient domains,
+ * and is incompatible with VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, then the domain
+ * is not paused while creating the snapshot. This increases the size
+ * of the memory dump file, but reduces downtime of the guest while
+ * taking the snapshot. Some hypervisors only support this flag during
+ * external checkpoints.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, then the
+ * snapshot will be limited to the disks described in @xmlDesc, and no
+ * VM state will be saved.  For an active guest, the disk image may be
+ * inconsistent (as if power had been pulled), and specifying this
+ * with the VIR_DOMAIN_SNAPSHOT_CREATE_HALT flag risks data loss.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, then the
+ * libvirt will attempt to use guest agent to freeze and thaw all
+ * file systems in use within domain OS. However, if the guest agent
+ * is not present, an error is thrown. Moreover, this flag requires
+ * VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY to be passed as well.
+ *
+ * By default, if the snapshot involves external files, and any of the
+ * destination files already exist as a non-empty regular file, the
+ * snapshot is rejected to avoid losing contents of those files.
+ * However, if @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT,
+ * then the destination files must be pre-created manually with
+ * the correct image format and metadata including backing store path
+ * (this allows a management app to pre-create files with relative backing
+ * file names, rather than the default of creating with absolute backing
+ * file names). Note that setting incorrect metadata in the pre-created
+ * image may lead to the VM being unable to start.
+ *
+ * Be aware that although libvirt prefers to report errors up front with
+ * no other effect, some hypervisors have certain types of failures where
+ * the overall command can easily fail even though the guest configuration
+ * was partially altered (for example, if a disk snapshot request for two
+ * disks fails on the second disk, but the first disk alteration cannot be
+ * rolled back).  If this API call fails, it is therefore normally
+ * necessary to follow up with virDomainGetXMLDesc() and check each disk
+ * to determine if any partial changes occurred.  However, if @flags
+ * contains VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, then libvirt guarantees
+ * that this command will not alter any disks unless the entire set of
+ * changes can be done atomically, making failure recovery simpler (note
+ * that it is still possible to fail after disks have changed, but only
+ * in the much rarer cases of running out of memory or disk space).
+ *
+ * Some hypervisors may prevent this operation if there is a current
+ * block copy operation; in that case, use virDomainBlockJobAbort()
+ * to stop the block copy first.
+ *
+ * virDomainSnapshotFree should be used to free the resources after the
+ * snapshot object is no longer needed.
+ *
+ * Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotCreateXML(virDomainPtr domain,
+                           const char *xmlDesc,
+                           unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=%x", xmlDesc, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(xmlDesc, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT) &&
+        !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
+        virReportInvalidArg(flags,
+                            _("use of 'current' flag in %s requires "
+                              "'redefine' flag"),
+                            __FUNCTION__);
+        goto error;
+    }
+    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
+        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
+        virReportInvalidArg(flags,
+                            _("'redefine' and 'no metadata' flags in %s are "
+                              "mutually exclusive"),
+                            __FUNCTION__);
+        goto error;
+    }
+    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
+        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
+        virReportInvalidArg(flags,
+                            _("'redefine' and 'halt' flags in %s are mutually "
+                              "exclusive"),
+                            __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainSnapshotCreateXML) {
+        virDomainSnapshotPtr ret;
+        ret = conn->driver->domainSnapshotCreateXML(domain, xmlDesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainSnapshotGetXMLDesc:
+ * @snapshot: a domain snapshot object
+ * @flags: bitwise-OR of subset of virDomainXMLFlags
+ *
+ * Provide an XML description of the domain snapshot.
+ *
+ * No security-sensitive data will be included unless @flags contains
+ * VIR_DOMAIN_XML_SECURE; this flag is rejected on read-only
+ * connections.  For this API, @flags should not contain either
+ * VIR_DOMAIN_XML_INACTIVE or VIR_DOMAIN_XML_UPDATE_CPU.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+char *
+virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+                            unsigned int flags)
+{
+    virConnectPtr conn;
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, NULL);
+    conn = snapshot->domain->conn;
+
+    if ((conn->flags & VIR_CONNECT_RO) && (flags & VIR_DOMAIN_XML_SECURE)) {
+        virReportError(VIR_ERR_OPERATION_DENIED, "%s",
+                       _("virDomainSnapshotGetXMLDesc with secure flag"));
+        goto error;
+    }
+
+    if (conn->driver->domainSnapshotGetXMLDesc) {
+        char *ret;
+        ret = conn->driver->domainSnapshotGetXMLDesc(snapshot, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainSnapshotNum:
+ * @domain: a domain object
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Provides the number of domain snapshots for this domain.
+ *
+ * By default, this command covers all snapshots; it is also possible to
+ * limit things to just snapshots with no parents, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ */
+int
+virDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+
+    conn = domain->conn;
+    if (conn->driver->domainSnapshotNum) {
+        int ret = conn->driver->domainSnapshotNum(domain, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotListNames:
+ * @domain: a domain object
+ * @names: array to collect the list of names of snapshots
+ * @nameslen: size of @names
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots for the given domain, and store
+ * their names in @names.  The value to use for @nameslen can be determined
+ * by virDomainSnapshotNum() with the same @flags.
+ *
+ * By default, this command covers all snapshots; it is also possible to
+ * limit things to just snapshots with no parents, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Note that this command is inherently racy: another connection can
+ * define a new snapshot between a call to virDomainSnapshotNum() and
+ * this call.  You are only guaranteed that all currently defined
+ * snapshots were listed if the return is less than @nameslen.  Likewise,
+ * you should be prepared for virDomainSnapshotLookupByName() to fail when
+ * converting a name from this call into a snapshot object, if another
+ * connection deletes the snapshot in the meantime.  For more control over
+ * the results, see virDomainListAllSnapshots().
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ * The caller is responsible to call free() for each member of the array.
+ */
+int
+virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
+                           unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "names=%p, nameslen=%d, flags=%x",
+                     names, nameslen, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(names, error);
+    virCheckNonNegativeArgGoto(nameslen, error);
+
+    if (conn->driver->domainSnapshotListNames) {
+        int ret = conn->driver->domainSnapshotListNames(domain, names,
+                                                        nameslen, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainListAllSnapshots:
+ * @domain: a domain object
+ * @snaps: pointer to variable to store the array containing snapshot objects,
+ *         or NULL if the list is not required (just returns number of
+ *         snapshots)
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots for the given domain, and allocate
+ * an array to store those objects.  This API solves the race inherent in
+ * virDomainSnapshotListNames().
+ *
+ * By default, this command covers all snapshots; it is also possible to
+ * limit things to just snapshots with no parents, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Returns the number of domain snapshots found or -1 and sets @snaps to
+ * NULL in case of error.  On success, the array stored into @snaps is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier.  The caller is responsible
+ * for calling virDomainSnapshotFree() on each array element, then calling
+ * free() on @snaps.
+ */
+int
+virDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps,
+                          unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "snaps=%p, flags=%x", snaps, flags);
+
+    virResetLastError();
+
+    if (snaps)
+        *snaps = NULL;
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    if (conn->driver->domainListAllSnapshots) {
+        int ret = conn->driver->domainListAllSnapshots(domain, snaps, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotNumChildren:
+ * @snapshot: a domain snapshot object
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Provides the number of child snapshots for this domain snapshot.
+ *
+ * By default, this command covers only direct children; it is also possible
+ * to expand things to cover all descendants, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ */
+int
+virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotNumChildren) {
+        int ret = conn->driver->domainSnapshotNumChildren(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotListChildrenNames:
+ * @snapshot: a domain snapshot object
+ * @names: array to collect the list of names of snapshots
+ * @nameslen: size of @names
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots that are children of the given
+ * snapshot, and store their names in @names.  The value to use for
+ * @nameslen can be determined by virDomainSnapshotNumChildren() with
+ * the same @flags.
+ *
+ * By default, this command covers only direct children; it is also possible
+ * to expand things to cover all descendants, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ * Note that this command is inherently racy: another connection can
+ * define a new snapshot between a call to virDomainSnapshotNumChildren()
+ * and this call.  You are only guaranteed that all currently defined
+ * snapshots were listed if the return is less than @nameslen.  Likewise,
+ * you should be prepared for virDomainSnapshotLookupByName() to fail when
+ * converting a name from this call into a snapshot object, if another
+ * connection deletes the snapshot in the meantime.  For more control over
+ * the results, see virDomainSnapshotListAllChildren().
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ * The caller is responsible to call free() for each member of the array.
+ */
+int
+virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
+                                   char **names, int nameslen,
+                                   unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, names=%p, nameslen=%d, flags=%x",
+              snapshot, names, nameslen, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    virCheckNonNullArgGoto(names, error);
+    virCheckNonNegativeArgGoto(nameslen, error);
+
+    if (conn->driver->domainSnapshotListChildrenNames) {
+        int ret = conn->driver->domainSnapshotListChildrenNames(snapshot,
+                                                                names,
+                                                                nameslen,
+                                                                flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotListAllChildren:
+ * @snapshot: a domain snapshot object
+ * @snaps: pointer to variable to store the array containing snapshot objects,
+ *         or NULL if the list is not required (just returns number of
+ *         snapshots)
+ * @flags: bitwise-OR of supported virDomainSnapshotListFlags
+ *
+ * Collect the list of domain snapshots that are children of the given
+ * snapshot, and allocate an array to store those objects.  This API solves
+ * the race inherent in virDomainSnapshotListChildrenNames().
+ *
+ * By default, this command covers only direct children; it is also possible
+ * to expand things to cover all descendants, when @flags includes
+ * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
+ * groups, where each group contains bits that describe mutually exclusive
+ * attributes of a snapshot, and where all bits within a group describe
+ * all possible snapshots.  Some hypervisors might reject explicit bits
+ * from a group where the hypervisor cannot make a distinction.  For a
+ * group supported by a given hypervisor, the behavior when no bits of a
+ * group are set is identical to the behavior when all bits in that group
+ * are set.  When setting bits from more than one group, it is possible to
+ * select an impossible combination, in that case a hypervisor may return
+ * either 0 or an error.
+ *
+ * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
+ * have no further children (a leaf snapshot).
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
+ * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
+ * whether they have metadata that would prevent the removal of the last
+ * reference to a domain.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ * for filtering snapshots based on what domain state is tracked by the
+ * snapshot.
+ *
+ * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
+ * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
+ * whether the snapshot is stored inside the disk images or as
+ * additional files.
+ *
+ * Returns the number of domain snapshots found or -1 and sets @snaps to
+ * NULL in case of error.  On success, the array stored into @snaps is
+ * guaranteed to have an extra allocated element set to NULL but not included
+ * in the return count, to make iteration easier.  The caller is responsible
+ * for calling virDomainSnapshotFree() on each array element, then calling
+ * free() on @snaps.
+ */
+int
+virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
+                                 virDomainSnapshotPtr **snaps,
+                                 unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, snaps=%p, flags=%x", snapshot, snaps, flags);
+
+    virResetLastError();
+
+    if (snaps)
+        *snaps = NULL;
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotListAllChildren) {
+        int ret = conn->driver->domainSnapshotListAllChildren(snapshot, snaps,
+                                                              flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotLookupByName:
+ * @domain: a domain object
+ * @name: name for the domain snapshot
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Try to lookup a domain snapshot based on its name.
+ *
+ * Returns a domain snapshot object or NULL in case of failure.  If the
+ * domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
+ * error is raised.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotLookupByName(virDomainPtr domain,
+                              const char *name,
+                              unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "name=%s, flags=%x", name, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(name, error);
+
+    if (conn->driver->domainSnapshotLookupByName) {
+        virDomainSnapshotPtr dom;
+        dom = conn->driver->domainSnapshotLookupByName(domain, name, flags);
+        if (!dom)
+            goto error;
+        return dom;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainHasCurrentSnapshot:
+ * @domain: pointer to the domain object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the domain has a current snapshot.
+ *
+ * Returns 1 if such snapshot exists, 0 if it doesn't, -1 on error.
+ */
+int
+virDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, -1);
+    conn = domain->conn;
+
+    if (conn->driver->domainHasCurrentSnapshot) {
+        int ret = conn->driver->domainHasCurrentSnapshot(domain, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotCurrent:
+ * @domain: a domain object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the current snapshot for a domain, if any.
+ *
+ * virDomainSnapshotFree should be used to free the resources after the
+ * snapshot object is no longer needed.
+ *
+ * Returns a domain snapshot object or NULL in case of failure.  If the
+ * current domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
+ * error is raised.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotCurrent(virDomainPtr domain,
+                         unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    if (conn->driver->domainSnapshotCurrent) {
+        virDomainSnapshotPtr snap;
+        snap = conn->driver->domainSnapshotCurrent(domain, flags);
+        if (!snap)
+            goto error;
+        return snap;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainSnapshotGetParent:
+ * @snapshot: a snapshot object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the parent snapshot for @snapshot, if any.
+ *
+ * virDomainSnapshotFree should be used to free the resources after the
+ * snapshot object is no longer needed.
+ *
+ * Returns a domain snapshot object or NULL in case of failure.  If the
+ * given snapshot is a root (no parent), then the VIR_ERR_NO_DOMAIN_SNAPSHOT
+ * error is raised.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
+                           unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, NULL);
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotGetParent) {
+        virDomainSnapshotPtr snap;
+        snap = conn->driver->domainSnapshotGetParent(snapshot, flags);
+        if (!snap)
+            goto error;
+        return snap;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainSnapshotIsCurrent:
+ * @snapshot: a snapshot object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the given snapshot is the domain's current snapshot.  See
+ * also virDomainHasCurrentSnapshot().
+ *
+ * Returns 1 if current, 0 if not current, or -1 on error.
+ */
+int
+virDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
+                           unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotIsCurrent) {
+        int ret;
+        ret = conn->driver->domainSnapshotIsCurrent(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotHasMetadata:
+ * @snapshot: a snapshot object
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Determine if the given snapshot is associated with libvirt metadata
+ * that would prevent the deletion of the domain.
+ *
+ * Returns 1 if the snapshot has metadata, 0 if the snapshot exists without
+ * help from libvirt, or -1 on error.
+ */
+int
+virDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
+                             unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    if (conn->driver->domainSnapshotHasMetadata) {
+        int ret;
+        ret = conn->driver->domainSnapshotHasMetadata(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainRevertToSnapshot:
+ * @snapshot: a domain snapshot object
+ * @flags: bitwise-OR of virDomainSnapshotRevertFlags
+ *
+ * Revert the domain to a given snapshot.
+ *
+ * Normally, the domain will revert to the same state the domain was
+ * in while the snapshot was taken (whether inactive, running, or
+ * paused), except that disk snapshots default to reverting to
+ * inactive state.  Including VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING in
+ * @flags overrides the snapshot state to guarantee a running domain
+ * after the revert; or including VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED in
+ * @flags guarantees a paused domain after the revert.  These two
+ * flags are mutually exclusive.  While a persistent domain does not
+ * need either flag, it is not possible to revert a transient domain
+ * into an inactive state, so transient domains require the use of one
+ * of these two flags.
+ *
+ * Reverting to any snapshot discards all configuration changes made since
+ * the last snapshot.  Additionally, reverting to a snapshot from a running
+ * domain is a form of data loss, since it discards whatever is in the
+ * guest's RAM at the time.  Since the very nature of keeping snapshots
+ * implies the intent to roll back state, no additional confirmation is
+ * normally required for these lossy effects.
+ *
+ * However, there are two particular situations where reverting will
+ * be refused by default, and where @flags must include
+ * VIR_DOMAIN_SNAPSHOT_REVERT_FORCE to acknowledge the risks.  1) Any
+ * attempt to revert to a snapshot that lacks the metadata to perform
+ * ABI compatibility checks (generally the case for snapshots that
+ * lack a full <domain> when listed by virDomainSnapshotGetXMLDesc(),
+ * such as those created prior to libvirt 0.9.5).  2) Any attempt to
+ * revert a running domain to an active state that requires starting a
+ * new hypervisor instance rather than reusing the existing hypervisor
+ * (since this would terminate all connections to the domain, such as
+ * such as VNC or Spice graphics) - this condition arises from active
+ * snapshots that are provably ABI incomaptible, as well as from
+ * inactive snapshots with a @flags request to start the domain after
+ * the revert.
+ *
+ * Returns 0 if the creation is successful, -1 on error.
+ */
+int
+virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+                          unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if ((flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
+        (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
+        virReportInvalidArg(flags,
+                            _("running and paused flags in %s are mutually "
+                              "exclusive"),
+                            __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainRevertToSnapshot) {
+        int ret = conn->driver->domainRevertToSnapshot(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotDelete:
+ * @snapshot: a domain snapshot object
+ * @flags: bitwise-OR of supported virDomainSnapshotDeleteFlags
+ *
+ * Delete the snapshot.
+ *
+ * If @flags is 0, then just this snapshot is deleted, and changes
+ * from this snapshot are automatically merged into children
+ * snapshots.  If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN,
+ * then this snapshot and any descendant snapshots are deleted.  If
+ * @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, then any
+ * descendant snapshots are deleted, but this snapshot remains.  These
+ * two flags are mutually exclusive.
+ *
+ * If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then
+ * any snapshot metadata tracked by libvirt is removed while keeping
+ * the snapshot contents intact; if a hypervisor does not require any
+ * libvirt metadata to track snapshots, then this flag is silently
+ * ignored.
+ *
+ * Returns 0 if the selected snapshot(s) were successfully deleted,
+ * -1 on error.
+ */
+int
+virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
+                        unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+    conn = snapshot->domain->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if ((flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) &&
+        (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
+        virReportInvalidArg(flags,
+                            _("children and children_only flags in %s are "
+                              "mutually exclusive"),
+                            __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainSnapshotDelete) {
+        int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virDomainSnapshotRef:
+ * @snapshot: the snapshot to hold a reference on
+ *
+ * Increment the reference count on the snapshot. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virDomainSnapshotFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection and domain remain open until all threads have finished
+ * using the snapshot. ie, each new thread using a snapshot would
+ * increment the reference count.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainSnapshotRef(virDomainSnapshotPtr snapshot)
+{
+    VIR_DEBUG("snapshot=%p, refs=%d", snapshot,
+              snapshot ? snapshot->object.u.s.refs : 0);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+
+    virObjectRef(snapshot);
+    return 0;
+}
+
+
+/**
+ * virDomainSnapshotFree:
+ * @snapshot: a domain snapshot object
+ *
+ * Free the domain snapshot object.  The snapshot itself is not modified.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainSnapshotFree(virDomainSnapshotPtr snapshot)
+{
+    VIR_DEBUG("snapshot=%p", snapshot);
+
+    virResetLastError();
+
+    virCheckDomainSnapshotReturn(snapshot, -1);
+
+    virObjectUnref(snapshot);
+    return 0;
+}
diff --git a/src/libvirt.c b/src/libvirt.c
index c6af39d..f02f0d9 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18269,1200 +18269,6 @@ virDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
 }
 
 
-/**
- * virDomainSnapshotGetName:
- * @snapshot: a snapshot object
- *
- * Get the public name for that snapshot
- *
- * Returns a pointer to the name or NULL, the string need not be deallocated
- * as its lifetime will be the same as the snapshot object.
- */
-const char *
-virDomainSnapshotGetName(virDomainSnapshotPtr snapshot)
-{
-    VIR_DEBUG("snapshot=%p", snapshot);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, NULL);
-
-    return snapshot->name;
-}
-
-
-/**
- * virDomainSnapshotGetDomain:
- * @snapshot: a snapshot object
- *
- * Provides the domain pointer associated with a snapshot.  The
- * reference counter on the domain is not increased by this
- * call.
- *
- * WARNING: When writing libvirt bindings in other languages, do not use this
- * function.  Instead, store the domain and the snapshot object together.
- *
- * Returns the domain or NULL.
- */
-virDomainPtr
-virDomainSnapshotGetDomain(virDomainSnapshotPtr snapshot)
-{
-    VIR_DEBUG("snapshot=%p", snapshot);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, NULL);
-
-    return snapshot->domain;
-}
-
-
-/**
- * virDomainSnapshotGetConnect:
- * @snapshot: a snapshot object
- *
- * Provides the connection pointer associated with a snapshot.  The
- * reference counter on the connection is not increased by this
- * call.
- *
- * WARNING: When writing libvirt bindings in other languages, do not use this
- * function.  Instead, store the connection and the snapshot object together.
- *
- * Returns the connection or NULL.
- */
-virConnectPtr
-virDomainSnapshotGetConnect(virDomainSnapshotPtr snapshot)
-{
-    VIR_DEBUG("snapshot=%p", snapshot);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, NULL);
-
-    return snapshot->domain->conn;
-}
-
-
-/**
- * virDomainSnapshotCreateXML:
- * @domain: a domain object
- * @xmlDesc: string containing an XML description of the domain
- * @flags: bitwise-OR of virDomainSnapshotCreateFlags
- *
- * Creates a new snapshot of a domain based on the snapshot xml
- * contained in xmlDesc.
- *
- * If @flags is 0, the domain can be active, in which case the
- * snapshot will be a system checkpoint (both disk state and runtime
- * VM state such as RAM contents), where reverting to the snapshot is
- * the same as resuming from hibernation (TCP connections may have
- * timed out, but everything else picks up where it left off); or
- * the domain can be inactive, in which case the snapshot includes
- * just the disk state prior to booting.  The newly created snapshot
- * becomes current (see virDomainSnapshotCurrent()), and is a child
- * of any previous current snapshot.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, then this
- * is a request to reinstate snapshot metadata that was previously
- * discarded, rather than creating a new snapshot.  This can be used
- * to recreate a snapshot hierarchy on a destination, then remove it
- * on the source, in order to allow migration (since migration
- * normally fails if snapshot metadata still remains on the source
- * machine).  When redefining snapshot metadata, the current snapshot
- * will not be altered unless the VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT
- * flag is also present.  It is an error to request the
- * VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flag without
- * VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.  On some hypervisors,
- * redefining an existing snapshot can be used to alter host-specific
- * portions of the domain XML to be used during revert (such as
- * backing filenames associated with disk devices), but must not alter
- * guest-visible layout.  When redefining a snapshot name that does
- * not exist, the hypervisor may validate that reverting to the
- * snapshot appears to be possible (for example, disk images have
- * snapshot contents by the requested name).  Not all hypervisors
- * support these flags.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, then the
- * domain's disk images are modified according to @xmlDesc, but then
- * the just-created snapshot has its metadata deleted.  This flag is
- * incompatible with VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_HALT, then the domain
- * will be inactive after the snapshot completes, regardless of whether
- * it was active before; otherwise, a running domain will still be
- * running after the snapshot.  This flag is invalid on transient domains,
- * and is incompatible with VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, then the domain
- * is not paused while creating the snapshot. This increases the size
- * of the memory dump file, but reduces downtime of the guest while
- * taking the snapshot. Some hypervisors only support this flag during
- * external checkpoints.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, then the
- * snapshot will be limited to the disks described in @xmlDesc, and no
- * VM state will be saved.  For an active guest, the disk image may be
- * inconsistent (as if power had been pulled), and specifying this
- * with the VIR_DOMAIN_SNAPSHOT_CREATE_HALT flag risks data loss.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, then the
- * libvirt will attempt to use guest agent to freeze and thaw all
- * file systems in use within domain OS. However, if the guest agent
- * is not present, an error is thrown. Moreover, this flag requires
- * VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY to be passed as well.
- *
- * By default, if the snapshot involves external files, and any of the
- * destination files already exist as a non-empty regular file, the
- * snapshot is rejected to avoid losing contents of those files.
- * However, if @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT,
- * then the destination files must be pre-created manually with
- * the correct image format and metadata including backing store path
- * (this allows a management app to pre-create files with relative backing
- * file names, rather than the default of creating with absolute backing
- * file names). Note that setting incorrect metadata in the pre-created
- * image may lead to the VM being unable to start.
- *
- * Be aware that although libvirt prefers to report errors up front with
- * no other effect, some hypervisors have certain types of failures where
- * the overall command can easily fail even though the guest configuration
- * was partially altered (for example, if a disk snapshot request for two
- * disks fails on the second disk, but the first disk alteration cannot be
- * rolled back).  If this API call fails, it is therefore normally
- * necessary to follow up with virDomainGetXMLDesc() and check each disk
- * to determine if any partial changes occurred.  However, if @flags
- * contains VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, then libvirt guarantees
- * that this command will not alter any disks unless the entire set of
- * changes can be done atomically, making failure recovery simpler (note
- * that it is still possible to fail after disks have changed, but only
- * in the much rarer cases of running out of memory or disk space).
- *
- * Some hypervisors may prevent this operation if there is a current
- * block copy operation; in that case, use virDomainBlockJobAbort()
- * to stop the block copy first.
- *
- * virDomainSnapshotFree should be used to free the resources after the
- * snapshot object is no longer needed.
- *
- * Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure.
- */
-virDomainSnapshotPtr
-virDomainSnapshotCreateXML(virDomainPtr domain,
-                           const char *xmlDesc,
-                           unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=%x", xmlDesc, flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, NULL);
-    conn = domain->conn;
-
-    virCheckNonNullArgGoto(xmlDesc, error);
-    virCheckReadOnlyGoto(conn->flags, error);
-
-    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT) &&
-        !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
-        virReportInvalidArg(flags,
-                            _("use of 'current' flag in %s requires "
-                              "'redefine' flag"),
-                            __FUNCTION__);
-        goto error;
-    }
-    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
-        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
-        virReportInvalidArg(flags,
-                            _("'redefine' and 'no metadata' flags in %s are "
-                              "mutually exclusive"),
-                            __FUNCTION__);
-        goto error;
-    }
-    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
-        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
-        virReportInvalidArg(flags,
-                            _("'redefine' and 'halt' flags in %s are mutually "
-                              "exclusive"),
-                            __FUNCTION__);
-        goto error;
-    }
-
-    if (conn->driver->domainSnapshotCreateXML) {
-        virDomainSnapshotPtr ret;
-        ret = conn->driver->domainSnapshotCreateXML(domain, xmlDesc, flags);
-        if (!ret)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return NULL;
-}
-
-
-/**
- * virDomainSnapshotGetXMLDesc:
- * @snapshot: a domain snapshot object
- * @flags: bitwise-OR of subset of virDomainXMLFlags
- *
- * Provide an XML description of the domain snapshot.
- *
- * No security-sensitive data will be included unless @flags contains
- * VIR_DOMAIN_XML_SECURE; this flag is rejected on read-only
- * connections.  For this API, @flags should not contain either
- * VIR_DOMAIN_XML_INACTIVE or VIR_DOMAIN_XML_UPDATE_CPU.
- *
- * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
- *         the caller must free() the returned value.
- */
-char *
-virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
-                            unsigned int flags)
-{
-    virConnectPtr conn;
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, NULL);
-    conn = snapshot->domain->conn;
-
-    if ((conn->flags & VIR_CONNECT_RO) && (flags & VIR_DOMAIN_XML_SECURE)) {
-        virReportError(VIR_ERR_OPERATION_DENIED, "%s",
-                       _("virDomainSnapshotGetXMLDesc with secure flag"));
-        goto error;
-    }
-
-    if (conn->driver->domainSnapshotGetXMLDesc) {
-        char *ret;
-        ret = conn->driver->domainSnapshotGetXMLDesc(snapshot, flags);
-        if (!ret)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return NULL;
-}
-
-
-/**
- * virDomainSnapshotNum:
- * @domain: a domain object
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Provides the number of domain snapshots for this domain.
- *
- * By default, this command covers all snapshots; it is also possible to
- * limit things to just snapshots with no parents, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Returns the number of domain snapshots found or -1 in case of error.
- */
-int
-virDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, -1);
-
-    conn = domain->conn;
-    if (conn->driver->domainSnapshotNum) {
-        int ret = conn->driver->domainSnapshotNum(domain, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotListNames:
- * @domain: a domain object
- * @names: array to collect the list of names of snapshots
- * @nameslen: size of @names
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Collect the list of domain snapshots for the given domain, and store
- * their names in @names.  The value to use for @nameslen can be determined
- * by virDomainSnapshotNum() with the same @flags.
- *
- * By default, this command covers all snapshots; it is also possible to
- * limit things to just snapshots with no parents, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Note that this command is inherently racy: another connection can
- * define a new snapshot between a call to virDomainSnapshotNum() and
- * this call.  You are only guaranteed that all currently defined
- * snapshots were listed if the return is less than @nameslen.  Likewise,
- * you should be prepared for virDomainSnapshotLookupByName() to fail when
- * converting a name from this call into a snapshot object, if another
- * connection deletes the snapshot in the meantime.  For more control over
- * the results, see virDomainListAllSnapshots().
- *
- * Returns the number of domain snapshots found or -1 in case of error.
- * The caller is responsible to call free() for each member of the array.
- */
-int
-virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
-                           unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "names=%p, nameslen=%d, flags=%x",
-                     names, nameslen, flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, -1);
-    conn = domain->conn;
-
-    virCheckNonNullArgGoto(names, error);
-    virCheckNonNegativeArgGoto(nameslen, error);
-
-    if (conn->driver->domainSnapshotListNames) {
-        int ret = conn->driver->domainSnapshotListNames(domain, names,
-                                                        nameslen, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainListAllSnapshots:
- * @domain: a domain object
- * @snaps: pointer to variable to store the array containing snapshot objects,
- *         or NULL if the list is not required (just returns number of
- *         snapshots)
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Collect the list of domain snapshots for the given domain, and allocate
- * an array to store those objects.  This API solves the race inherent in
- * virDomainSnapshotListNames().
- *
- * By default, this command covers all snapshots; it is also possible to
- * limit things to just snapshots with no parents, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_ROOTS.  Additional filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Returns the number of domain snapshots found or -1 and sets @snaps to
- * NULL in case of error.  On success, the array stored into @snaps is
- * guaranteed to have an extra allocated element set to NULL but not included
- * in the return count, to make iteration easier.  The caller is responsible
- * for calling virDomainSnapshotFree() on each array element, then calling
- * free() on @snaps.
- */
-int
-virDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps,
-                          unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "snaps=%p, flags=%x", snaps, flags);
-
-    virResetLastError();
-
-    if (snaps)
-        *snaps = NULL;
-
-    virCheckDomainReturn(domain, -1);
-    conn = domain->conn;
-
-    if (conn->driver->domainListAllSnapshots) {
-        int ret = conn->driver->domainListAllSnapshots(domain, snaps, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotNumChildren:
- * @snapshot: a domain snapshot object
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Provides the number of child snapshots for this domain snapshot.
- *
- * By default, this command covers only direct children; it is also possible
- * to expand things to cover all descendants, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Returns the number of domain snapshots found or -1 in case of error.
- */
-int
-virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    if (conn->driver->domainSnapshotNumChildren) {
-        int ret = conn->driver->domainSnapshotNumChildren(snapshot, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotListChildrenNames:
- * @snapshot: a domain snapshot object
- * @names: array to collect the list of names of snapshots
- * @nameslen: size of @names
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Collect the list of domain snapshots that are children of the given
- * snapshot, and store their names in @names.  The value to use for
- * @nameslen can be determined by virDomainSnapshotNumChildren() with
- * the same @flags.
- *
- * By default, this command covers only direct children; it is also possible
- * to expand things to cover all descendants, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Returns the number of domain snapshots found or -1 in case of error.
- * Note that this command is inherently racy: another connection can
- * define a new snapshot between a call to virDomainSnapshotNumChildren()
- * and this call.  You are only guaranteed that all currently defined
- * snapshots were listed if the return is less than @nameslen.  Likewise,
- * you should be prepared for virDomainSnapshotLookupByName() to fail when
- * converting a name from this call into a snapshot object, if another
- * connection deletes the snapshot in the meantime.  For more control over
- * the results, see virDomainSnapshotListAllChildren().
- *
- * Returns the number of domain snapshots found or -1 in case of error.
- * The caller is responsible to call free() for each member of the array.
- */
-int
-virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
-                                   char **names, int nameslen,
-                                   unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, names=%p, nameslen=%d, flags=%x",
-              snapshot, names, nameslen, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    virCheckNonNullArgGoto(names, error);
-    virCheckNonNegativeArgGoto(nameslen, error);
-
-    if (conn->driver->domainSnapshotListChildrenNames) {
-        int ret = conn->driver->domainSnapshotListChildrenNames(snapshot,
-                                                                names,
-                                                                nameslen,
-                                                                flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotListAllChildren:
- * @snapshot: a domain snapshot object
- * @snaps: pointer to variable to store the array containing snapshot objects,
- *         or NULL if the list is not required (just returns number of
- *         snapshots)
- * @flags: bitwise-OR of supported virDomainSnapshotListFlags
- *
- * Collect the list of domain snapshots that are children of the given
- * snapshot, and allocate an array to store those objects.  This API solves
- * the race inherent in virDomainSnapshotListChildrenNames().
- *
- * By default, this command covers only direct children; it is also possible
- * to expand things to cover all descendants, when @flags includes
- * VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS.  Also, some filters are provided in
- * groups, where each group contains bits that describe mutually exclusive
- * attributes of a snapshot, and where all bits within a group describe
- * all possible snapshots.  Some hypervisors might reject explicit bits
- * from a group where the hypervisor cannot make a distinction.  For a
- * group supported by a given hypervisor, the behavior when no bits of a
- * group are set is identical to the behavior when all bits in that group
- * are set.  When setting bits from more than one group, it is possible to
- * select an impossible combination, in that case a hypervisor may return
- * either 0 or an error.
- *
- * The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
- * have no further children (a leaf snapshot).
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
- * VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
- * whether they have metadata that would prevent the removal of the last
- * reference to a domain.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
- * VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, and VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
- * for filtering snapshots based on what domain state is tracked by the
- * snapshot.
- *
- * The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL and
- * VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, for filtering snapshots based on
- * whether the snapshot is stored inside the disk images or as
- * additional files.
- *
- * Returns the number of domain snapshots found or -1 and sets @snaps to
- * NULL in case of error.  On success, the array stored into @snaps is
- * guaranteed to have an extra allocated element set to NULL but not included
- * in the return count, to make iteration easier.  The caller is responsible
- * for calling virDomainSnapshotFree() on each array element, then calling
- * free() on @snaps.
- */
-int
-virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
-                                 virDomainSnapshotPtr **snaps,
-                                 unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, snaps=%p, flags=%x", snapshot, snaps, flags);
-
-    virResetLastError();
-
-    if (snaps)
-        *snaps = NULL;
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    if (conn->driver->domainSnapshotListAllChildren) {
-        int ret = conn->driver->domainSnapshotListAllChildren(snapshot, snaps,
-                                                              flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotLookupByName:
- * @domain: a domain object
- * @name: name for the domain snapshot
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Try to lookup a domain snapshot based on its name.
- *
- * Returns a domain snapshot object or NULL in case of failure.  If the
- * domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
- * error is raised.
- */
-virDomainSnapshotPtr
-virDomainSnapshotLookupByName(virDomainPtr domain,
-                              const char *name,
-                              unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "name=%s, flags=%x", name, flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, NULL);
-    conn = domain->conn;
-
-    virCheckNonNullArgGoto(name, error);
-
-    if (conn->driver->domainSnapshotLookupByName) {
-        virDomainSnapshotPtr dom;
-        dom = conn->driver->domainSnapshotLookupByName(domain, name, flags);
-        if (!dom)
-            goto error;
-        return dom;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return NULL;
-}
-
-
-/**
- * virDomainHasCurrentSnapshot:
- * @domain: pointer to the domain object
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Determine if the domain has a current snapshot.
- *
- * Returns 1 if such snapshot exists, 0 if it doesn't, -1 on error.
- */
-int
-virDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, -1);
-    conn = domain->conn;
-
-    if (conn->driver->domainHasCurrentSnapshot) {
-        int ret = conn->driver->domainHasCurrentSnapshot(domain, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotCurrent:
- * @domain: a domain object
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Get the current snapshot for a domain, if any.
- *
- * virDomainSnapshotFree should be used to free the resources after the
- * snapshot object is no longer needed.
- *
- * Returns a domain snapshot object or NULL in case of failure.  If the
- * current domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
- * error is raised.
- */
-virDomainSnapshotPtr
-virDomainSnapshotCurrent(virDomainPtr domain,
-                         unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
-
-    virResetLastError();
-
-    virCheckDomainReturn(domain, NULL);
-    conn = domain->conn;
-
-    if (conn->driver->domainSnapshotCurrent) {
-        virDomainSnapshotPtr snap;
-        snap = conn->driver->domainSnapshotCurrent(domain, flags);
-        if (!snap)
-            goto error;
-        return snap;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return NULL;
-}
-
-
-/**
- * virDomainSnapshotGetParent:
- * @snapshot: a snapshot object
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Get the parent snapshot for @snapshot, if any.
- *
- * virDomainSnapshotFree should be used to free the resources after the
- * snapshot object is no longer needed.
- *
- * Returns a domain snapshot object or NULL in case of failure.  If the
- * given snapshot is a root (no parent), then the VIR_ERR_NO_DOMAIN_SNAPSHOT
- * error is raised.
- */
-virDomainSnapshotPtr
-virDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
-                           unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, NULL);
-    conn = snapshot->domain->conn;
-
-    if (conn->driver->domainSnapshotGetParent) {
-        virDomainSnapshotPtr snap;
-        snap = conn->driver->domainSnapshotGetParent(snapshot, flags);
-        if (!snap)
-            goto error;
-        return snap;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return NULL;
-}
-
-
-/**
- * virDomainSnapshotIsCurrent:
- * @snapshot: a snapshot object
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Determine if the given snapshot is the domain's current snapshot.  See
- * also virDomainHasCurrentSnapshot().
- *
- * Returns 1 if current, 0 if not current, or -1 on error.
- */
-int
-virDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
-                           unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    if (conn->driver->domainSnapshotIsCurrent) {
-        int ret;
-        ret = conn->driver->domainSnapshotIsCurrent(snapshot, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotHasMetadata:
- * @snapshot: a snapshot object
- * @flags: extra flags; not used yet, so callers should always pass 0
- *
- * Determine if the given snapshot is associated with libvirt metadata
- * that would prevent the deletion of the domain.
- *
- * Returns 1 if the snapshot has metadata, 0 if the snapshot exists without
- * help from libvirt, or -1 on error.
- */
-int
-virDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
-                             unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    if (conn->driver->domainSnapshotHasMetadata) {
-        int ret;
-        ret = conn->driver->domainSnapshotHasMetadata(snapshot, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainRevertToSnapshot:
- * @snapshot: a domain snapshot object
- * @flags: bitwise-OR of virDomainSnapshotRevertFlags
- *
- * Revert the domain to a given snapshot.
- *
- * Normally, the domain will revert to the same state the domain was
- * in while the snapshot was taken (whether inactive, running, or
- * paused), except that disk snapshots default to reverting to
- * inactive state.  Including VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING in
- * @flags overrides the snapshot state to guarantee a running domain
- * after the revert; or including VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED in
- * @flags guarantees a paused domain after the revert.  These two
- * flags are mutually exclusive.  While a persistent domain does not
- * need either flag, it is not possible to revert a transient domain
- * into an inactive state, so transient domains require the use of one
- * of these two flags.
- *
- * Reverting to any snapshot discards all configuration changes made since
- * the last snapshot.  Additionally, reverting to a snapshot from a running
- * domain is a form of data loss, since it discards whatever is in the
- * guest's RAM at the time.  Since the very nature of keeping snapshots
- * implies the intent to roll back state, no additional confirmation is
- * normally required for these lossy effects.
- *
- * However, there are two particular situations where reverting will
- * be refused by default, and where @flags must include
- * VIR_DOMAIN_SNAPSHOT_REVERT_FORCE to acknowledge the risks.  1) Any
- * attempt to revert to a snapshot that lacks the metadata to perform
- * ABI compatibility checks (generally the case for snapshots that
- * lack a full <domain> when listed by virDomainSnapshotGetXMLDesc(),
- * such as those created prior to libvirt 0.9.5).  2) Any attempt to
- * revert a running domain to an active state that requires starting a
- * new hypervisor instance rather than reusing the existing hypervisor
- * (since this would terminate all connections to the domain, such as
- * such as VNC or Spice graphics) - this condition arises from active
- * snapshots that are provably ABI incomaptible, as well as from
- * inactive snapshots with a @flags request to start the domain after
- * the revert.
- *
- * Returns 0 if the creation is successful, -1 on error.
- */
-int
-virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
-                          unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    virCheckReadOnlyGoto(conn->flags, error);
-
-    if ((flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
-        (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
-        virReportInvalidArg(flags,
-                            _("running and paused flags in %s are mutually "
-                              "exclusive"),
-                            __FUNCTION__);
-        goto error;
-    }
-
-    if (conn->driver->domainRevertToSnapshot) {
-        int ret = conn->driver->domainRevertToSnapshot(snapshot, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotDelete:
- * @snapshot: a domain snapshot object
- * @flags: bitwise-OR of supported virDomainSnapshotDeleteFlags
- *
- * Delete the snapshot.
- *
- * If @flags is 0, then just this snapshot is deleted, and changes
- * from this snapshot are automatically merged into children
- * snapshots.  If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN,
- * then this snapshot and any descendant snapshots are deleted.  If
- * @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, then any
- * descendant snapshots are deleted, but this snapshot remains.  These
- * two flags are mutually exclusive.
- *
- * If @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then
- * any snapshot metadata tracked by libvirt is removed while keeping
- * the snapshot contents intact; if a hypervisor does not require any
- * libvirt metadata to track snapshots, then this flag is silently
- * ignored.
- *
- * Returns 0 if the selected snapshot(s) were successfully deleted,
- * -1 on error.
- */
-int
-virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
-                        unsigned int flags)
-{
-    virConnectPtr conn;
-
-    VIR_DEBUG("snapshot=%p, flags=%x", snapshot, flags);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-    conn = snapshot->domain->conn;
-
-    virCheckReadOnlyGoto(conn->flags, error);
-
-    if ((flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) &&
-        (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
-        virReportInvalidArg(flags,
-                            _("children and children_only flags in %s are "
-                              "mutually exclusive"),
-                            __FUNCTION__);
-        goto error;
-    }
-
-    if (conn->driver->domainSnapshotDelete) {
-        int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
-        if (ret < 0)
-            goto error;
-        return ret;
-    }
-
-    virReportUnsupportedError();
- error:
-    virDispatchError(conn);
-    return -1;
-}
-
-
-/**
- * virDomainSnapshotRef:
- * @snapshot: the snapshot to hold a reference on
- *
- * Increment the reference count on the snapshot. For each
- * additional call to this method, there shall be a corresponding
- * call to virDomainSnapshotFree to release the reference count, once
- * the caller no longer needs the reference to this object.
- *
- * This method is typically useful for applications where multiple
- * threads are using a connection, and it is required that the
- * connection and domain remain open until all threads have finished
- * using the snapshot. ie, each new thread using a snapshot would
- * increment the reference count.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-int
-virDomainSnapshotRef(virDomainSnapshotPtr snapshot)
-{
-    VIR_DEBUG("snapshot=%p, refs=%d", snapshot,
-              snapshot ? snapshot->object.u.s.refs : 0);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-
-    virObjectRef(snapshot);
-    return 0;
-}
-
-
-/**
- * virDomainSnapshotFree:
- * @snapshot: a domain snapshot object
- *
- * Free the domain snapshot object.  The snapshot itself is not modified.
- * The data structure is freed and should not be used thereafter.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-int
-virDomainSnapshotFree(virDomainSnapshotPtr snapshot)
-{
-    VIR_DEBUG("snapshot=%p", snapshot);
-
-    virResetLastError();
-
-    virCheckDomainSnapshotReturn(snapshot, -1);
-
-    virObjectUnref(snapshot);
-    return 0;
-}
-
 
 /**
  * virDomainOpenConsole:
-- 
2.1.0




More information about the libvir-list mailing list