* 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
_("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;
qemuDomainSnapshotCreateActive(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr *vmptr,
- virDomainSnapshotObjPtr snap)
+ virDomainSnapshotObjPtr snap,
+ unsigned int flags)
{
virDomainObjPtr vm = *vmptr;
qemuDomainObjPrivatePtr priv = vm->privateData;
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) &&
_("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;
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)) ||
"%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,
goto cleanup;
} else {
if (qemuDomainSnapshotCreateActive(domain->conn, driver,
- &vm, snap) < 0)
+ &vm, snap, flags) < 0)
goto cleanup;
}