提交 6f66423e 编写于 作者: E Eric Blake

snapshot: allow halting after snapshot

Since a snapshot is fully recoverable, it is useful to have a
snapshot as a means of hibernating a guest, then reverting to
the snapshot to wake the guest up.  This mode of usage is
similar to 'virsh save/virsh restore', except that virsh
save uses an external file while virsh snapshot keeps the
vm state internal to a qcow2 file.  However, it only works on
persistent domains.

In the usage pattern of snapshot/revert for hibernating a guest,
there is no need to keep the guest running between the two points
in time, especially since that would generate runtime state that
would just be discarded.  Add a flag to make it possible to
stop the domain after the snapshot has completed.

* include/libvirt/libvirt.h.in (VIR_DOMAIN_SNAPSHOT_CREATE_HALT):
New flag.
* src/libvirt.c (virDomainSnapshotCreateXML): Document it.
* src/qemu/qemu_driver.c (qemuDomainSnapshotCreateXML)
(qemuDomainSnapshotCreateActive): Implement it.
上级 ddc88273
...@@ -2567,6 +2567,8 @@ typedef enum { ...@@ -2567,6 +2567,8 @@ typedef enum {
snapshot current */ snapshot current */
VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA = (1 << 2), /* Make snapshot without VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA = (1 << 2), /* Make snapshot without
remembering it */ remembering it */
VIR_DOMAIN_SNAPSHOT_CREATE_HALT = (1 << 3), /* Stop running guest
after snapshot */
} virDomainSnapshotCreateFlags; } virDomainSnapshotCreateFlags;
/* Take a snapshot of the current VM state */ /* Take a snapshot of the current VM state */
......
...@@ -15637,6 +15637,12 @@ error: ...@@ -15637,6 +15637,12 @@ error:
* the just-created snapshot has its metadata deleted. This flag is * the just-created snapshot has its metadata deleted. This flag is
* incompatible with VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE. * 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.
*
* Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure. * Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure.
*/ */
virDomainSnapshotPtr virDomainSnapshotPtr
...@@ -15680,6 +15686,12 @@ virDomainSnapshotCreateXML(virDomainPtr domain, ...@@ -15680,6 +15686,12 @@ virDomainSnapshotCreateXML(virDomainPtr domain,
_("redefine and no metadata flags are mutually exclusive")); _("redefine and no metadata flags are mutually exclusive"));
goto error; goto error;
} }
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
(flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
virLibDomainError(VIR_ERR_INVALID_ARG,
_("redefine and halt flags are mutually exclusive"));
goto error;
}
if (conn->driver->domainSnapshotCreateXML) { if (conn->driver->domainSnapshotCreateXML) {
virDomainSnapshotPtr ret; virDomainSnapshotPtr ret;
......
...@@ -8693,7 +8693,8 @@ static int ...@@ -8693,7 +8693,8 @@ static int
qemuDomainSnapshotCreateActive(virConnectPtr conn, qemuDomainSnapshotCreateActive(virConnectPtr conn,
struct qemud_driver *driver, struct qemud_driver *driver,
virDomainObjPtr *vmptr, virDomainObjPtr *vmptr,
virDomainSnapshotObjPtr snap) virDomainSnapshotObjPtr snap,
unsigned int flags)
{ {
virDomainObjPtr vm = *vmptr; virDomainObjPtr vm = *vmptr;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
...@@ -8723,6 +8724,24 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, ...@@ -8723,6 +8724,24 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name); ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0)
goto cleanup;
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
virDomainEventPtr event;
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
virDomainAuditStop(vm, "from-snapshot");
/* We already filtered the _HALT flag for persistent domains
* only, so this end job never drops the last reference. */
ignore_value(qemuDomainObjEndJob(driver, vm));
resume = false;
vm = NULL;
if (event)
qemuDomainEventQueue(driver, event);
}
cleanup: cleanup:
if (resume && virDomainObjIsActive(vm) && if (resume && virDomainObjIsActive(vm) &&
...@@ -8734,7 +8753,7 @@ cleanup: ...@@ -8734,7 +8753,7 @@ cleanup:
_("resuming after snapshot failed")); _("resuming after snapshot failed"));
} }
if (qemuDomainObjEndJob(driver, vm) == 0) { if (vm && qemuDomainObjEndJob(driver, vm) == 0) {
/* Only possible if a transient vm quit while our locks were down, /* Only possible if a transient vm quit while our locks were down,
* in which case we don't want to save snapshot metadata. */ * in which case we don't want to save snapshot metadata. */
*vmptr = NULL; *vmptr = NULL;
...@@ -8761,7 +8780,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, ...@@ -8761,7 +8780,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE | virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT | VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL); VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
VIR_DOMAIN_SNAPSHOT_CREATE_HALT, NULL);
if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) && if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) || !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
...@@ -8784,6 +8804,11 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, ...@@ -8784,6 +8804,11 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
"%s", _("domain is marked for auto destroy")); "%s", _("domain is marked for auto destroy"));
goto cleanup; goto cleanup;
} }
if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot halt after transient domain snapshot"));
goto cleanup;
}
if (!(def = virDomainSnapshotDefParseString(xmlDesc, driver->caps, if (!(def = virDomainSnapshotDefParseString(xmlDesc, driver->caps,
QEMU_EXPECTED_VIRT_TYPES, QEMU_EXPECTED_VIRT_TYPES,
...@@ -8924,7 +8949,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, ...@@ -8924,7 +8949,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
goto cleanup; goto cleanup;
} else { } else {
if (qemuDomainSnapshotCreateActive(domain->conn, driver, if (qemuDomainSnapshotCreateActive(domain->conn, driver,
&vm, snap) < 0) &vm, snap, flags) < 0)
goto cleanup; goto cleanup;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册