mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
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.
This commit is contained in:
parent
ddc882733a
commit
6f66423e17
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user