This just uses the existing plumping to update the guest XML to point at the chosen snapshot disk images. It requires the VM to be inactive. --- Reverting to a snapshot with children and then running the guest is probably unsafe, since the backing image will change state on the child snapshots. How do internal snapshots work around this? src/qemu/qemu_driver.c | 72 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9bf89bb..53f5340 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11205,6 +11205,65 @@ qemuDomainSnapshotRevertInactive(struct qemud_driver *driver, return ret > 0 ? -1 : ret; } +/* The domain is expected to be locked */ +static int qemuDomainRevertToSnapshotDisk(virDomainSnapshotObjPtr snap, + virDomainObjPtr vm, + virDomainDefPtr config, + unsigned int flags) +{ + int ret = -1; + int i; + + if (virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain must be stopped to revert to a " + "disk only snapshot")); + goto cleanup; + } + + if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING | + VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain can only be shutoff after reverting to a" + "disk only snapshot")); + goto cleanup; + } + + if (!config) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain XML must be present in the snapshot metadata")); + goto cleanup; + } + + for (i = 0; i < snap->def->ndisks; i++) { + virDomainDiskDefPtr vmdisk = config->disks[i]; + virDomainSnapshotDiskDefPtr snapdisk = &(snap->def->disks[i]); + char *src = NULL; + char *type = NULL; + + if (snapdisk->snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO) + continue; + + if (!(src = strdup(snapdisk->file)) || + !(type = strdup(snapdisk->driverType))) { + virReportOOMError(); + VIR_FREE(src); + VIR_FREE(type); + goto cleanup; + } + + VIR_FREE(vmdisk->src); + vmdisk->src = src; + VIR_FREE(vmdisk->driverType); + vmdisk->driverType = type; + } + + virDomainObjAssignDef(vm, config, false); + ret = 0; +cleanup: + return ret; +} + static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags) { @@ -11265,12 +11324,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, "to revert to inactive snapshot")); goto cleanup; } - if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("revert to external disk snapshot not supported " - "yet")); - goto cleanup; - } if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) { if (!snap->def->dom) { virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, @@ -11289,7 +11342,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } } - if (vm->current_snapshot) { vm->current_snapshot->def->current = false; if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot, @@ -11325,6 +11377,11 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; + if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) { + ret = qemuDomainRevertToSnapshotDisk(snap, vm, config, flags); + goto endjob; + } + if (snap->def->state == VIR_DOMAIN_RUNNING || snap->def->state == VIR_DOMAIN_PAUSED) { /* Transitions 2, 3, 5, 6, 8, 9 */ @@ -11522,7 +11579,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } ret = 0; - endjob: if (vm && qemuDomainObjEndJob(driver, vm) == 0) vm = NULL; -- 1.7.11.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list