[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv2 15/20] snapshot: qemu: Add support for external inactive snapshots



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]