提交 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 {
snapshot current */
VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA = (1 << 2), /* Make snapshot without
remembering it */
VIR_DOMAIN_SNAPSHOT_CREATE_HALT = (1 << 3), /* Stop running guest
after snapshot */
} virDomainSnapshotCreateFlags;
/* Take a snapshot of the current VM state */
......
......@@ -15637,6 +15637,12 @@ error:
* 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.
*
* Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure.
*/
virDomainSnapshotPtr
......@@ -15680,6 +15686,12 @@ virDomainSnapshotCreateXML(virDomainPtr domain,
_("redefine and no metadata flags are mutually exclusive"));
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) {
virDomainSnapshotPtr ret;
......
......@@ -8693,7 +8693,8 @@ static int
qemuDomainSnapshotCreateActive(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr *vmptr,
virDomainSnapshotObjPtr snap)
virDomainSnapshotObjPtr snap,
unsigned int flags)
{
virDomainObjPtr vm = *vmptr;
qemuDomainObjPrivatePtr priv = vm->privateData;
......@@ -8723,6 +8724,24 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
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:
if (resume && virDomainObjIsActive(vm) &&
......@@ -8734,7 +8753,7 @@ cleanup:
_("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,
* in which case we don't want to save snapshot metadata. */
*vmptr = NULL;
......@@ -8761,7 +8780,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
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) &&
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
......@@ -8784,6 +8804,11 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
"%s", _("domain is marked for auto destroy"));
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,
QEMU_EXPECTED_VIRT_TYPES,
......@@ -8924,7 +8949,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
goto cleanup;
} else {
if (qemuDomainSnapshotCreateActive(domain->conn, driver,
&vm, snap) < 0)
&vm, snap, flags) < 0)
goto cleanup;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册