[libvirt] [PATCH 14/20] snapshot: qemu: Add support for external inactive snapshots

Peter Krempa pkrempa at redhat.com
Tue Oct 23 15:12:36 UTC 2012


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




More information about the libvir-list mailing list