This patch adds support for external disk snapshots of inactive domains. The snapshot is created by calling qemu-img create -o backing_file=/path/to/disk /path/snapshot_file on each of the disks selected for snapshotting. --- src/qemu/qemu_driver.c | 108 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ff3c57f..2ac079b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10627,13 +10627,100 @@ qemuDomainSnapshotFSThaw(struct qemud_driver *driver, /* The domain is expected to be locked and inactive. */ static int -qemuDomainSnapshotCreateInactive(struct qemud_driver *driver, - virDomainObjPtr vm, - virDomainSnapshotObjPtr snap) +qemuDomainSnapshotCreateInactiveInternal(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainSnapshotObjPtr snap) { return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false); } +/* The domain is expected to be locked and inactive. */ +static int +qemuDomainSnapshotCreateInactiveExternal(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainSnapshotObjPtr snap, + bool reuse) +{ + const char *qemuimgarg[] = { NULL, "create", "-f", NULL, "-o", NULL, NULL, NULL }; + int i = 0; + char *backingFileArg = NULL; + virDomainSnapshotDiskDefPtr snapdisk; + virDomainDiskDefPtr defdisk; + + int ret = -1; + + qemuimgarg[0] = qemuFindQemuImgBinary(driver); + if (qemuimgarg[0] == NULL) { + /* qemuFindQemuImgBinary set the error */ + return -1; + } + + for (i = 0; i < snap->def->ndisks; i++) { + snapdisk = &(snap->def->disks[i]); + defdisk = snap->def->dom->disks[snapdisk->index]; + + if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { + VIR_FREE(backingFileArg); + + /* remove old disk image */ + if (reuse && virFileExists(snapdisk->file) && + unlink(snapdisk->file) < 0) { + virReportSystemError(errno, + _("Failed to remove image file '%s'"), + snapdisk->file); + goto cleanup; + } + + if (virAsprintf(&backingFileArg, "backing_file=%s", defdisk->src) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!snapdisk->format) + snapdisk->format = VIR_STORAGE_FILE_QCOW2; + + qemuimgarg[3] = virStorageFileFormatTypeToString(snapdisk->format); + qemuimgarg[5] = backingFileArg; + qemuimgarg[6] = snapdisk->file; + + if (virRun(qemuimgarg, NULL) < 0) + goto cleanup; + } + } + + /* update disk definitions */ + for (i = 0; i < snap->def->ndisks; i++) { + snapdisk = &(snap->def->disks[i]); + defdisk = vm->def->disks[snapdisk->index]; + + if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { + VIR_FREE(defdisk->src); + if (!(defdisk->src = strdup(snapdisk->file))) { + virReportOOMError(); + goto cleanup; + } + defdisk->format = snapdisk->format; + } + } + + ret = 0; + +cleanup: + /* unlink images if creation has failed */ + if (ret < 0 && i > 0) { + for (; i > 0; i--) { + snapdisk = &(snap->def->disks[i]); + if (unlink(snapdisk->file) < 0) + VIR_WARN("Failed to remove snapshot image '%s'", + snapdisk->file); + } + } + + VIR_FREE(backingFileArg); + + return ret; +} + /* The domain is expected to be locked and active. */ static int @@ -11412,12 +11499,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, goto cleanup; if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) { - if (!virDomainObjIsActive(vm)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("disk snapshots of inactive domains not " - "implemented yet")); - goto cleanup; - } align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL; align_match = false; def->state = VIR_DOMAIN_DISK_SNAPSHOT; @@ -11480,8 +11561,13 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, } } else { /* inactive */ - if (qemuDomainSnapshotCreateInactive(driver, vm, snap) < 0) - goto cleanup; + if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) { + if (qemuDomainSnapshotCreateInactiveExternal(driver, vm, snap, false) < 0) + goto cleanup; + } else { + if (qemuDomainSnapshotCreateInactiveInternal(driver, vm, snap) < 0) + goto cleanup; + } } /* If we fail after this point, there's not a whole lot we can -- 1.7.12.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list