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

Cole Robinson crobinso at redhat.com
Mon Aug 13 14:30:40 UTC 2012


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




More information about the libvir-list mailing list