提交 af65695a 编写于 作者: E Eric Blake

snapshot: allow recreation of metadata

The first two flags are essential for being able to replicate
snapshot hierarchies across multiple hosts, which will come in
handy for supervised migrations.  It also allows a management app
to take a snapshot of a transient domain, save the metadata, stop
the domain, recreate a new transient domain by the same name,
redefine the snapshot, then revert to it.

This is not quite as convenient as leaving the metadata behind
after a domain is no longer around, but doing that has a few
problems: 1. the libvirt API can only delete snapshot metadata
if there is a valid domain handle to use to get to that snapshot
object - if stale data is left behind without a domain, there is
no way to request that the data be cleaned up. 2. creating a new
domain with the same name but different uuid than the older
domain where a snapshot existed cannot use the older snapshot
data; this risks confusing libvirt, and forbidding the stale
data is similar to the recent patch to forbid stale managed save.

The first two flags might be useful on hypervisors with no metadata,
but only for modifying the notion of the current snapshot;
however, I don't know how to do that for ESX or VBox.

The third flag is a convenience option, to combine a creation with
a delete metadata into one step.  It is trivial for hypervisors
with no metadata.

The qemu changes will be involved enough to warrant a separate patch.

* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)
(VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)
(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA): New flags.
* src/libvirt.c (virDomainSnapshotCreateXML): Document them, and
enforce mutual exclusion.
* src/esx/esx_driver.c (esxDomainSnapshotCreateXML): Trivial
implementation.
* src/vbox/vbox_tmpl.c (vboxDomainSnapshotCreateXML): Likewise.
* docs/formatsnapshot.html.in: Document re-creation.
上级 6b3801b0
......@@ -9,10 +9,26 @@
<p>
Attributes of libvirt snapshots are stored as child elements of
the <code>domainsnapshot</code> element. At snapshot creation
time, only the <code>name</code> and <code>description</code>
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 <code>name</code>
and <code>description</code> elements are settable; the rest of
the fields are ignored on creation, and will be filled in by
libvirt in for informational purposes
by <code>virDomainSnapshotGetXMLDesc()</code>. However, when
redefining a snapshot (<span class="since">since 0.9.5</span>),
with the <code>VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE</code> flag
of <code>virDomainSnapshotCreateXML()</code>, all of the XML
described here is relevant.
</p>
<p>
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.
</p>
<p>
The top-level <code>domainsnapshot</code> element may contain
......@@ -21,9 +37,10 @@
<dl>
<dt><code>name</code></dt>
<dd>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.
</dd>
<dt><code>description</code></dt>
<dd>A human-readable description of the snapshot. If the
......@@ -32,18 +49,18 @@
</dd>
<dt><code>creationTime</code></dt>
<dd>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.
</dd>
<dt><code>state</code></dt>
<dd>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.
<dd>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.
</dd>
<dt><code>parent</code></dt>
<dd>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.
</dd>
<dt><code>domain</code></dt>
<dd>The domain that this snapshot was taken against. This
......@@ -56,17 +73,17 @@
<h2><a name="example">Example</a></h2>
<pre>
&lt;domainsnapshot&gt;
&lt;name&gt;os-updates&lt;/name&gt;
&lt;description&gt;Snapshot of OS install and updates&lt;/description&gt;
&lt;state&gt;running&lt;/state&gt;
&lt;creationTime&gt;1270477159&lt;/creationTime&gt;
&lt;parent&gt;
&lt;name&gt;bare-os-install&lt;/name&gt;
&lt;/parent&gt;
&lt;domain&gt;
&lt;uuid&gt;93a5c045-6457-2c09-e56c-927cdf34e178&lt;/uuid&gt;
&lt;/domain&gt;
&lt;/domainsnapshot&gt;</pre>
&lt;domainsnapshot&gt;
&lt;name&gt;os-updates&lt;/name&gt;
&lt;description&gt;Snapshot of OS install and updates&lt;/description&gt;
&lt;state&gt;running&lt;/state&gt;
&lt;creationTime&gt;1270477159&lt;/creationTime&gt;
&lt;parent&gt;
&lt;name&gt;bare-os-install&lt;/name&gt;
&lt;/parent&gt;
&lt;domain&gt;
&lt;uuid&gt;93a5c045-6457-2c09-e56c-927cdf34e178&lt;/uuid&gt;
&lt;/domain&gt;
&lt;/domainsnapshot&gt;</pre>
</body>
</html>
......@@ -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,
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册