diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in index 79ed1d234a49f4a920c049278537c78557d9b1eb..dc5873a8225e4de9a33562c38e506ebc05017ef1 100644 --- a/docs/formatsnapshot.html.in +++ b/docs/formatsnapshot.html.in @@ -9,10 +9,26 @@

Attributes of libvirt snapshots are stored as child elements of the domainsnapshot element. At snapshot creation - time, only the name and description - elements are settable; the rest of the fields are informational - (and readonly) and will be filled in by libvirt when the - snapshot is created. + time, normally only the name + and description elements are settable; the rest of + the fields are ignored on creation, and will be filled in by + libvirt in for informational purposes + by virDomainSnapshotGetXMLDesc(). However, when + redefining a snapshot (since 0.9.5), + with the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE flag + of virDomainSnapshotCreateXML(), all of the XML + described here is relevant. +

+

+ Snapshots are maintained in a hierarchy. A domain can have a + current snapshot, which is the most recent snapshot compared to + the current state of the domain (although a domain might have + snapshots without a current snapshot, if snapshots have been + deleted in the meantime). Creating or reverting to a snapshot + sets that snapshot as current, and the prior current snapshot is + the parent of the new snapshot. Branches in the hierarchy can + be formed by reverting to a snapshot with a child, then creating + another snapshot.

The top-level domainsnapshot element may contain @@ -21,9 +37,10 @@

name
The name for this snapshot. If the name is specified when - initially creating the snapshot, then the snapshot will have - that particular name. If the name is omitted when initially - creating the snapshot, then libvirt will make up a name for the snapshot. + initially creating the snapshot, then the snapshot will have + that particular name. If the name is omitted when initially + creating the snapshot, then libvirt will make up a name for + the snapshot, based on the time when it was created.
description
A human-readable description of the snapshot. If the @@ -32,18 +49,18 @@
creationTime
The time this snapshot was created. The time is specified - in seconds since the Epoch, UTC (i.e. Unix time). Readonly. + in seconds since the Epoch, UTC (i.e. Unix time). Readonly.
state
-
The state of the domain at the time this snapshot was - taken. When the domain is reverted to this snapshot, the domain's state - will be set to whatever is in this field. Readonly. +
The state of the domain at the time this snapshot was taken. + When the domain is reverted to this snapshot, the domain's + state will default to whatever is in this field. Readonly.
parent
The parent of this snapshot. This element contains exactly - one child element, name. This specifies the name of the parent - snapshot of this snapshot, and is used to represent trees of - snapshots. Readonly. + one child element, name. This specifies the name of the parent + snapshot of this snapshot, and is used to represent trees of + snapshots, as described above. Readonly.
domain
The domain that this snapshot was taken against. This @@ -56,17 +73,17 @@

Example

-      <domainsnapshot>
-         <name>os-updates</name>
-         <description>Snapshot of OS install and updates</description>
-         <state>running</state>
-         <creationTime>1270477159</creationTime>
-         <parent>
-            <name>bare-os-install</name>
-         </parent>
-         <domain>
-            <uuid>93a5c045-6457-2c09-e56c-927cdf34e178</uuid>
-         </domain>
-      </domainsnapshot>
+<domainsnapshot> + <name>os-updates</name> + <description>Snapshot of OS install and updates</description> + <state>running</state> + <creationTime>1270477159</creationTime> + <parent> + <name>bare-os-install</name> + </parent> + <domain> + <uuid>93a5c045-6457-2c09-e56c-927cdf34e178</uuid> + </domain> +</domainsnapshot> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 257d9dec15d3fb74f9b0d7e1ef7ca3e1884e02db..59c9e63dacfb97332fb07a3de3a086765e904e06 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2554,6 +2554,15 @@ typedef struct _virDomainSnapshot virDomainSnapshot; */ typedef virDomainSnapshot *virDomainSnapshotPtr; +typedef enum { + VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE = (1 << 0), /* Restore or alter + metadata */ + VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT = (1 << 1), /* With redefine, make + snapshot current */ + VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA = (1 << 2), /* Make snapshot without + remembering it */ +} virDomainSnapshotCreateFlags; + /* Take a snapshot of the current VM state */ virDomainSnapshotPtr virDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 7cad03136007d8d5c6f132e544ae2b89ad495532..695fb0367436508cab372bd1ca0bf77eec136141 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4210,7 +4210,8 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, char *taskInfoErrorMessage = NULL; virDomainSnapshotPtr snapshot = NULL; - virCheckFlags(0, NULL); + /* ESX has no snapshot metadata, so this flag is trivial. */ + virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL); if (esxVI_EnsureSession(priv->primary) < 0) { return NULL; diff --git a/src/libvirt.c b/src/libvirt.c index 8cfac89ca92d08764484f1b17e3a6812bc3ff363..c1b154e59020769827247d845bb00cda0fa2d478 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -15576,11 +15576,46 @@ error: * virDomainSnapshotCreateXML: * @domain: a domain object * @xmlDesc: string containing an XML description of the domain - * @flags: unused flag parameters; callers should pass 0 + * @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. + * * Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure. */ virDomainSnapshotPtr @@ -15612,6 +15647,19 @@ virDomainSnapshotCreateXML(virDomainPtr domain, goto error; } + if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT) && + !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) { + virLibDomainError(VIR_ERR_INVALID_ARG, + _("use of current flag requires redefine flag")); + goto error; + } + if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) && + (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) { + virLibDomainError(VIR_ERR_INVALID_ARG, + _("redefine and no metadata flags are mutually exclusive")); + goto error; + } + if (conn->driver->domainSnapshotCreateXML) { virDomainSnapshotPtr ret; ret = conn->driver->domainSnapshotCreateXML(domain, xmlDesc, flags); diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index fc9739e3025cfba46ffe076422cf9e154ff7f7f2..afe951ccde42ad597222cbac267b84d696f69fdf 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -5652,7 +5652,8 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, PRInt32 result; #endif - virCheckFlags(0, NULL); + /* VBox has no snapshot metadata, so this flag is trivial. */ + virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL); if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1))) goto cleanup;