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 -f backing_file=/path/to/backing/file,backing_fmt=format_of_backing_file on each of the disks selected for snapshotting. --- Diff to v1: -added probing of backing file type -switched to virCommand --- src/qemu/qemu_driver.c | 124 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04906d4..4cea78f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10663,13 +10663,116 @@ 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) +{ + int i = 0; + char *backingFileArg = NULL; + virDomainSnapshotDiskDefPtr snapdisk; + virDomainDiskDefPtr defdisk; + virCommandPtr cmd = NULL; + const char *qemuImgPath; + + int ret = -1; + + if (!(qemuImgPath = qemuFindQemuImgBinary(driver))) + 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) { + /* check if destination file exists */ + if (reuse && virFileExists(snapdisk->file)) { + VIR_DEBUG("Skipping snapshot creation: File exists: %s", + snapdisk->file); + continue; + } + + if (!snapdisk->format) + snapdisk->format = VIR_STORAGE_FILE_QCOW2; + + /* probe the disk format */ + if (defdisk->format <= 0) { + defdisk->format = virStorageFileProbeFormat(defdisk->src, + driver->user, + driver->group); + if (defdisk->format < 0) + goto cleanup; + } + + if (virAsprintf(&backingFileArg, "backing_file=%s,backing_fmt=%s", + defdisk->src, + virStorageFileFormatTypeToString(defdisk->format)) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!(cmd = virCommandNewArgList(qemuImgPath, + "create", + "-f", + virStorageFileFormatTypeToString(snapdisk->format), + "-o", + backingFileArg, + snapdisk->file, + NULL))) + goto cleanup; + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + virCommandFree(cmd); + VIR_FREE(backingFileArg); + cmd = NULL; + } + } + + /* 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); + virCommandFree(cmd); + + return ret; +} + /* The domain is expected to be locked and active. */ static int @@ -11462,12 +11565,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; @@ -11540,8 +11637,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