[libvirt] [PATCHv2 16/16] save: support qemu modifying xml on domain save/restore

Eric Blake eblake at redhat.com
Wed Jul 20 04:20:39 UTC 2011


With this, it is possible to update the path to a disk backing
image on either the save or restore action, without having to
binary edit the XML embedded in the state file.

* src/qemu/qemu_driver.c (qemuDomainSaveInternal)
(qemuDomainSaveImageOpen): Add parameter.
(qemuDomainSaveFlags, qemuDomainManagedSave)
(qemuDomainRestoreFlags, qemuDomainObjRestore): Update callers.
---

v2: new patch

Tested via:

virsh start dom
virsh dumpxml dom > dom.xml
ln /path/to/disk /path/to/disk2
ln /path/to/disk /path/to/disk3
edit dom.xml to change /path/to/disk to /path/to/disk2
virsh save dom dom.save --xml dom.xml
check that xml embedded in binary dom.save did change
cp dom.xml dom.xml2
edit dom.xml to change /path/to/disk2 to /path/to/disk3
edit dom.xml2 to break abi, such as removing entire cdrom <disk> element
virsh restore dom.save --xml dom.xml2 => properly failed
virsh restore dom.save --xml dom.xml
virsh dumpxml dom - validate that /path/to/disk3 is in use

Which means it is now possible to do:

virsh dumpxml dom > dom.xml
virsh save dom dom.save
use qemu-img to create new qcow2 files with backing file of the original images
alter dom.xml to reflect the new file names
virsh restore dom.save --xml dom.xml

to externally manage disk snapshots causing changed file names.

Not quite where I wanted to be with snapshot support, but certainly
a step in the right direction!

 src/qemu/qemu_driver.c |   56 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 73d2938..d1fa06f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2113,7 +2113,7 @@ qemuCompressProgramName(int compress)
 static int
 qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
                        virDomainObjPtr vm, const char *path,
-                       int compressed, bool bypass_cache)
+                       int compressed, bool bypass_cache, const char *xmlin)
 {
     char *xml = NULL;
     struct qemud_save_header header;
@@ -2160,7 +2160,22 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
     }

     /* Get XML for the domain */
-    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+    if (xmlin) {
+        virDomainDefPtr def = NULL;
+
+        if (!(def = virDomainDefParseString(driver->caps, xmlin,
+                                            QEMU_EXPECTED_VIRT_TYPES,
+                                            VIR_DOMAIN_XML_INACTIVE))) {
+            goto endjob;
+        }
+        if (!virDomainDefCheckABIStability(vm->def, def)) {
+            virDomainDefFree(def);
+            goto endjob;
+        }
+        xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
+    } else {
+        xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+    }
     if (!xml) {
         qemuReportError(VIR_ERR_OPERATION_FAILED,
                         "%s", _("failed to get domain xml"));
@@ -2381,11 +2396,6 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
     virDomainObjPtr vm = NULL;

     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE, -1);
-    if (dxml) {
-        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
-                        _("xml modification unsupported"));
-        return -1;
-    }

     qemuDriverLock(driver);

@@ -2423,7 +2433,8 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
     }

     ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
-                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0);
+                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
+                                 dxml);
     vm = NULL;

 cleanup:
@@ -2487,7 +2498,8 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)

     compressed = QEMUD_SAVE_FORMAT_RAW;
     ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
-                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0);
+                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
+                                 NULL);
     vm = NULL;

 cleanup:
@@ -3616,7 +3628,8 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
                         const char *path,
                         virDomainDefPtr *ret_def,
                         struct qemud_save_header *ret_header,
-                        bool bypass_cache, virFileDirectFdPtr *directFd)
+                        bool bypass_cache, virFileDirectFdPtr *directFd,
+                        const char *xmlin)
 {
     int fd;
     struct qemud_save_header header;
@@ -3700,6 +3713,20 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
                                         QEMU_EXPECTED_VIRT_TYPES,
                                         VIR_DOMAIN_XML_INACTIVE)))
         goto error;
+    if (xmlin) {
+        virDomainDefPtr def2 = NULL;
+
+        if (!(def2 = virDomainDefParseString(driver->caps, xmlin,
+                                             QEMU_EXPECTED_VIRT_TYPES,
+                                             VIR_DOMAIN_XML_INACTIVE)))
+            goto error;
+        if (!virDomainDefCheckABIStability(def, def2)) {
+            virDomainDefFree(def2);
+            goto error;
+        }
+        virDomainDefFree(def);
+        def = def2;
+    }

     VIR_FREE(xml);

@@ -3834,17 +3861,12 @@ qemuDomainRestoreFlags(virConnectPtr conn,
     virFileDirectFdPtr directFd = NULL;

     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE, -1);
-    if (dxml) {
-        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
-                        _("xml modification unsupported"));
-        return -1;
-    }

     qemuDriverLock(driver);

     fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
                                  (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
-                                 &directFd);
+                                 &directFd, dxml);
     if (fd < 0)
         goto cleanup;

@@ -3904,7 +3926,7 @@ qemuDomainObjRestore(virConnectPtr conn,
     virFileDirectFdPtr directFd = NULL;

     fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
-                                 bypass_cache, &directFd);
+                                 bypass_cache, &directFd, NULL);
     if (fd < 0)
         goto cleanup;

-- 
1.7.4.4




More information about the libvir-list mailing list