]> xenbits.xensource.com Git - libvirt.git/commitdiff
snapshot: affect persistent xml after disk snapshot
authorEric Blake <eblake@redhat.com>
Sat, 17 Sep 2011 03:46:21 +0000 (21:46 -0600)
committerEric Blake <eblake@redhat.com>
Sat, 17 Sep 2011 11:57:23 +0000 (05:57 -0600)
For external snapshots to be useful on persistent domains, we must
alter the persistent definition alongside the running definition.
Thanks to the possibility of disk hotplug as well as of edits that
only affect the persistent xml, we can't assume that vm->def and
vm->newDef have the same disk at the same index, so we can only
update the persistent copy if the device destination matches up.

* src/qemu/qemu_driver.c (qemuDomainSnapshotCreateDiskActive)
(qemuDomainSnapshotCreateSingleDiskActive): Also affect newDef, if
present.

src/qemu/qemu_driver.c

index 32f376ec53d2de48c15a5168e609c8955e23b124..2a1e5eab090d86b433d30d8def80032c94800b8f 100644 (file)
@@ -9107,12 +9107,15 @@ static int
 qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
                                          virDomainObjPtr vm,
                                          virDomainSnapshotDiskDefPtr snap,
-                                         virDomainDiskDefPtr disk)
+                                         virDomainDiskDefPtr disk,
+                                         virDomainDiskDefPtr persistDisk)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *device = NULL;
     char *source = NULL;
     char *driverType = NULL;
+    char *persistSource = NULL;
+    char *persistDriverType = NULL;
     int ret = -1;
     int fd = -1;
     char *origsrc = NULL;
@@ -9128,7 +9131,11 @@ qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
     if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
         !(source = strdup(snap->file)) ||
         (STRNEQ_NULLABLE(disk->driverType, "qcow2") &&
-         !(driverType = strdup("qcow2")))) {
+         !(driverType = strdup("qcow2"))) ||
+        (persistDisk &&
+         (!(persistSource = strdup(source)) ||
+          (STRNEQ_NULLABLE(persistDisk->driverType, "qcow2") &&
+           !(persistDriverType = strdup("qcow2")))))) {
         virReportOOMError();
         goto cleanup;
     }
@@ -9176,9 +9183,16 @@ qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
         disk->driverType = driverType;
         driverType = NULL;
     }
-
-    /* XXX Do we also need to update vm->newDef if there are pending
-     * configuration changes awaiting the next boot?  */
+    if (persistDisk) {
+        VIR_FREE(persistDisk->src);
+        persistDisk->src = persistSource;
+        persistSource = NULL;
+        if (persistDriverType) {
+            VIR_FREE(persistDisk->driverType);
+            persistDisk->driverType = persistDriverType;
+            persistDriverType = NULL;
+        }
+    }
 
 cleanup:
     if (origsrc) {
@@ -9190,6 +9204,8 @@ cleanup:
     VIR_FREE(device);
     VIR_FREE(source);
     VIR_FREE(driverType);
+    VIR_FREE(persistSource);
+    VIR_FREE(persistDriverType);
     return ret;
 }
 
@@ -9205,6 +9221,7 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
     bool resume = false;
     int ret = -1;
     int i;
+    bool persist = false;
 
     if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
         return -1;
@@ -9235,12 +9252,24 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
      * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format.  */
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     for (i = 0; i < snap->def->ndisks; i++) {
+        virDomainDiskDefPtr persistDisk = NULL;
+
         if (snap->def->disks[i].snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO)
             continue;
+        if (vm->newDef) {
+            int indx = virDomainDiskIndexByName(vm->newDef,
+                                                vm->def->disks[i]->dst,
+                                                false);
+            if (indx >= 0) {
+                persistDisk = vm->newDef->disks[indx];
+                persist = true;
+            }
+        }
 
         ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
                                                        &snap->def->disks[i],
-                                                       vm->def->disks[i]);
+                                                       vm->def->disks[i],
+                                                       persistDisk);
         if (ret < 0)
             break;
     }
@@ -9275,7 +9304,9 @@ cleanup:
     }
 
     if (vm) {
-        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0 ||
+            (persist &&
+             virDomainSaveConfig(driver->configDir, vm->newDef) < 0))
             ret = -1;
         if (qemuDomainObjEndJob(driver, vm) == 0) {
             /* Only possible if a transient vm quit while our locks were down,