diff --git a/docs/apibuild.py b/docs/apibuild.py index 30e224dd4d..b5bd93695a 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 59be2e6750..6f88a15ce6 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 7521bded77..1b0a97dc95 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 171ec872ca..d2025979e5 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 0000000000..9feb669975 --- /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 + * . + */ + +#include + +#include "datatypes.h" +#include "virlog.h" + +VIR_LOG_INIT("libvirt.domain-snapshot"); + +#define VIR_FROM_THIS VIR_FROM_DOMAIN_SNAPSHOT + +/** + * 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 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 c6af39d6c5..f02f0d9a19 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 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: