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