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

[libvirt] [PATCH] qemu: snapshot: Wire up revert for disk only snapshots



This just uses the existing plumping to update the guest XML to point
at the chosen snapshot disk images. It requires the VM to be inactive.
---

Reverting to a snapshot with children and then running the guest is
probably unsafe, since the backing image will change state on the child
snapshots. How do internal snapshots work around this?

 src/qemu/qemu_driver.c | 72 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9bf89bb..53f5340 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11205,6 +11205,65 @@ qemuDomainSnapshotRevertInactive(struct qemud_driver *driver,
     return ret > 0 ? -1 : ret;
 }
 
+/* The domain is expected to be locked */
+static int qemuDomainRevertToSnapshotDisk(virDomainSnapshotObjPtr snap,
+                                          virDomainObjPtr vm,
+                                          virDomainDefPtr config,
+                                          unsigned int flags)
+{
+    int ret = -1;
+    int i;
+
+    if (virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("domain must be stopped to revert to a "
+                         "disk only snapshot"));
+        goto cleanup;
+    }
+
+    if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
+                 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("domain can only be shutoff after reverting to a"
+                         "disk only snapshot"));
+        goto cleanup;
+    }
+
+    if (!config) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                    _("domain XML must be present in the snapshot metadata"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < snap->def->ndisks; i++) {
+        virDomainDiskDefPtr vmdisk = config->disks[i];
+        virDomainSnapshotDiskDefPtr snapdisk = &(snap->def->disks[i]);
+        char *src = NULL;
+        char *type = NULL;
+
+        if (snapdisk->snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO)
+            continue;
+
+        if (!(src = strdup(snapdisk->file)) ||
+            !(type = strdup(snapdisk->driverType))) {
+            virReportOOMError();
+            VIR_FREE(src);
+            VIR_FREE(type);
+            goto cleanup;
+        }
+
+        VIR_FREE(vmdisk->src);
+        vmdisk->src = src;
+        VIR_FREE(vmdisk->driverType);
+        vmdisk->driverType = type;
+    }
+
+    virDomainObjAssignDef(vm, config, false);
+    ret = 0;
+cleanup:
+    return ret;
+}
+
 static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                                       unsigned int flags)
 {
@@ -11265,12 +11324,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                          "to revert to inactive snapshot"));
         goto cleanup;
     }
-    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("revert to external disk snapshot not supported "
-                         "yet"));
-        goto cleanup;
-    }
     if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
         if (!snap->def->dom) {
             virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
@@ -11289,7 +11342,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
         }
     }
 
-
     if (vm->current_snapshot) {
         vm->current_snapshot->def->current = false;
         if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
@@ -11325,6 +11377,11 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
         goto cleanup;
 
+    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) {
+        ret = qemuDomainRevertToSnapshotDisk(snap, vm, config, flags);
+        goto endjob;
+    }
+
     if (snap->def->state == VIR_DOMAIN_RUNNING
         || snap->def->state == VIR_DOMAIN_PAUSED) {
         /* Transitions 2, 3, 5, 6, 8, 9 */
@@ -11522,7 +11579,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     }
 
     ret = 0;
-
 endjob:
     if (vm && qemuDomainObjEndJob(driver, vm) == 0)
         vm = NULL;
-- 
1.7.11.2


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