]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Emit compatible XML when migrating a domain
authorJiri Denemark <jdenemar@redhat.com>
Fri, 4 May 2012 19:23:17 +0000 (21:23 +0200)
committerCole Robinson <crobinso@redhat.com>
Thu, 14 Jun 2012 15:19:18 +0000 (11:19 -0400)
When we added the default USB controller into domain XML, we efficiently
broke migration to older versions of libvirt that didn't support USB
controllers at all (0.9.4 and earlier) even for domains that don't use
anything that the older libvirt can't provide. We still want to present
the default USB controller in any XML seen by a user/app but we can
safely remove it from the domain XML used during migration. If we are
migrating to a new enough libvirt, it will add the controller XML back,
while older libvirt won't be confused with it although it will still
tell qemu to create the controller.

Similar approach can be used in the future whenever we find out we
always enabled some kind of device without properly advertising it in
domain XML.
(cherry picked from commit 409b5f549530e7b3a33f4505f2cad2e26896107c)

src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_process.c

index a80567168ef42bef66317fa02fd5207015a755f8..1926c210b910c74acb9c991384719c07c7a838e7 100644 (file)
@@ -1153,11 +1153,14 @@ int
 qemuDomainDefFormatBuf(struct qemud_driver *driver,
                        virDomainDefPtr def,
                        unsigned int flags,
+                       bool compatible,
                        virBuffer *buf)
 {
     int ret = -1;
     virCPUDefPtr cpu = NULL;
     virCPUDefPtr def_cpu = def->cpu;
+    virDomainControllerDefPtr *controllers = NULL;
+    int ncontrollers = 0;
 
     /* Update guest CPU requirements according to host CPU */
     if ((flags & VIR_DOMAIN_XML_UPDATE_CPU) &&
@@ -1175,21 +1178,64 @@ qemuDomainDefFormatBuf(struct qemud_driver *driver,
         def->cpu = cpu;
     }
 
+    if (compatible) {
+        int i;
+        virDomainControllerDefPtr usb = NULL;
+
+        /* If only the default USB controller is present, we can remove it
+         * and make the XML compatible with older versions of libvirt which
+         * didn't support USB controllers in the XML but always added the
+         * default one to qemu anyway.
+         */
+        for (i = 0; i < def->ncontrollers; i++) {
+            if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
+                if (usb) {
+                    usb = NULL;
+                    break;
+                }
+                usb = def->controllers[i];
+            }
+        }
+        if (usb && usb->idx == 0 && usb->model == -1) {
+            VIR_DEBUG("Removing default USB controller from domain '%s'"
+                      " for migration compatibility", def->name);
+            controllers = def->controllers;
+            ncontrollers = def->ncontrollers;
+            if (VIR_ALLOC_N(def->controllers, ncontrollers - 1) < 0) {
+                controllers = NULL;
+                virReportOOMError();
+                goto cleanup;
+            }
+
+            def->ncontrollers = 0;
+            for (i = 0; i < ncontrollers; i++) {
+                if (controllers[i] != usb)
+                    def->controllers[def->ncontrollers++] = controllers[i];
+            }
+        }
+    }
+
     ret = virDomainDefFormatInternal(def, flags, buf);
 
 cleanup:
     def->cpu = def_cpu;
     virCPUDefFree(cpu);
+    if (controllers) {
+        VIR_FREE(def->controllers);
+        def->controllers = controllers;
+        def->ncontrollers = ncontrollers;
+    }
     return ret;
 }
 
 char *qemuDomainDefFormatXML(struct qemud_driver *driver,
                              virDomainDefPtr def,
-                             unsigned int flags)
+                             unsigned int flags,
+                             bool compatible)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
 
-    if (qemuDomainDefFormatBuf(driver, def, flags, &buf) < 0) {
+    if (qemuDomainDefFormatBuf(driver, def, flags, compatible, &buf) < 0) {
         virBufferFreeAndReset(&buf);
         return NULL;
     }
@@ -1205,7 +1251,8 @@ char *qemuDomainDefFormatXML(struct qemud_driver *driver,
 
 char *qemuDomainFormatXML(struct qemud_driver *driver,
                           virDomainObjPtr vm,
-                          unsigned int flags)
+                          unsigned int flags,
+                          bool compatible)
 {
     virDomainDefPtr def;
 
@@ -1214,20 +1261,21 @@ char *qemuDomainFormatXML(struct qemud_driver *driver,
     else
         def = vm->def;
 
-    return qemuDomainDefFormatXML(driver, def, flags);
+    return qemuDomainDefFormatXML(driver, def, flags, compatible);
 }
 
 char *
 qemuDomainDefFormatLive(struct qemud_driver *driver,
                         virDomainDefPtr def,
-                        bool inactive)
+                        bool inactive,
+                        bool compatible)
 {
     unsigned int flags = QEMU_DOMAIN_FORMAT_LIVE_FLAGS;
 
     if (inactive)
         flags |= VIR_DOMAIN_XML_INACTIVE;
 
-    return qemuDomainDefFormatXML(driver, def, flags);
+    return qemuDomainDefFormatXML(driver, def, flags, compatible);
 }
 
 
index f582dd75badbb461e899ba281c5be47fa2981171..9ff516594d060bedb8d64db2852caf7cfa265b5e 100644 (file)
@@ -243,19 +243,23 @@ void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver,
 int qemuDomainDefFormatBuf(struct qemud_driver *driver,
                            virDomainDefPtr vm,
                            unsigned int flags,
+                           bool compatible,
                            virBuffer *buf);
 
 char *qemuDomainDefFormatXML(struct qemud_driver *driver,
                              virDomainDefPtr vm,
-                             unsigned int flags);
+                             unsigned int flags,
+                             bool compatible);
 
 char *qemuDomainFormatXML(struct qemud_driver *driver,
                           virDomainObjPtr vm,
-                          unsigned int flags);
+                          unsigned int flags,
+                          bool compatible);
 
 char *qemuDomainDefFormatLive(struct qemud_driver *driver,
                               virDomainDefPtr def,
-                              bool inactive);
+                              bool inactive,
+                              bool compatible);
 
 void qemuDomainObjTaint(struct qemud_driver *driver,
                         virDomainObjPtr obj,
index 77d3c7b4264896a61f337dc1d33dfb2d8d6be599..057a84ce993c8f1984ebd5d74c4e2dc4460ac79f 100644 (file)
@@ -2622,9 +2622,9 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
             virDomainDefFree(def);
             goto endjob;
         }
-        xml = qemuDomainDefFormatLive(driver, def, true);
+        xml = qemuDomainDefFormatLive(driver, def, true, true);
     } else {
-        xml = qemuDomainDefFormatLive(driver, vm->def, true);
+        xml = qemuDomainDefFormatLive(driver, vm->def, true, true);
     }
     if (!xml) {
         qemuReportError(VIR_ERR_OPERATION_FAILED,
@@ -4313,7 +4313,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
     if (fd < 0)
         goto cleanup;
 
-    ret = qemuDomainDefFormatXML(driver, def, flags);
+    ret = qemuDomainDefFormatXML(driver, def, flags, false);
 
 cleanup:
     virDomainDefFree(def);
@@ -4355,8 +4355,10 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
         goto cleanup;
     }
 
-    xml = qemuDomainDefFormatXML(driver, def, (VIR_DOMAIN_XML_INACTIVE |
-                                               VIR_DOMAIN_XML_SECURE));
+    xml = qemuDomainDefFormatXML(driver, def,
+                                 VIR_DOMAIN_XML_INACTIVE |
+                                 VIR_DOMAIN_XML_SECURE,
+                                 true);
     if (!xml)
         goto cleanup;
     len = strlen(xml) + 1;
@@ -4503,7 +4505,7 @@ endjob:
         }
     }
 
-    ret = qemuDomainFormatXML(driver, vm, flags);
+    ret = qemuDomainFormatXML(driver, vm, flags, false);
 
 cleanup:
     if (vm)
@@ -4543,7 +4545,7 @@ static char *qemuDomainXMLFromNative(virConnectPtr conn,
         goto cleanup;
     }
 
-    xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE);
+    xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE, false);
 
 cleanup:
     virDomainDefFree(def);
@@ -10388,7 +10390,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
     } else {
         /* Easiest way to clone inactive portion of vm->def is via
          * conversion in and back out of xml.  */
-        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true)) ||
+        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, false)) ||
             !(def->dom = virDomainDefParseString(driver->caps, xml,
                                                  QEMU_EXPECTED_VIRT_TYPES,
                                                  VIR_DOMAIN_XML_INACTIVE)))
@@ -10957,7 +10959,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
         if (!(xml = qemuDomainDefFormatXML(driver,
                                            snap->def->dom,
                                            VIR_DOMAIN_XML_INACTIVE |
-                                           VIR_DOMAIN_XML_SECURE)))
+                                           VIR_DOMAIN_XML_SECURE,
+                                           false)))
             goto cleanup;
         config = virDomainDefParseString(driver->caps, xml,
                                          QEMU_EXPECTED_VIRT_TYPES,
index bdb1d5ac14bb2d83eabaf83849a42dac84e26897..4ebebcf073c7c5b7eb775b0f6a09f8cbd97bacb8 100644 (file)
@@ -433,6 +433,7 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
                                    mig->persistent,
                                    VIR_DOMAIN_XML_INACTIVE |
                                    VIR_DOMAIN_XML_SECURE,
+                                   true,
                                    buf) < 0)
             return -1;
         virBufferAdjustIndent(buf, -2);
@@ -1158,9 +1159,9 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
         if (!virDomainDefCheckABIStability(vm->def, def))
             goto cleanup;
 
-        rv = qemuDomainDefFormatLive(driver, def, false);
+        rv = qemuDomainDefFormatLive(driver, def, false, true);
     } else {
-        rv = qemuDomainDefFormatLive(driver, vm->def, false);
+        rv = qemuDomainDefFormatLive(driver, vm->def, false, true);
     }
 
 cleanup:
@@ -1239,7 +1240,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
         int hookret;
 
         if (!(xml = qemuDomainDefFormatXML(driver, def,
-                                           VIR_DOMAIN_XML_SECURE)))
+                                           VIR_DOMAIN_XML_SECURE, false)))
             goto cleanup;
 
         hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
@@ -2186,7 +2187,8 @@ static int doPeer2PeerMigrate2(struct qemud_driver *driver,
      */
     if (!(dom_xml = qemuDomainFormatXML(driver, vm,
                                         VIR_DOMAIN_XML_SECURE |
-                                        VIR_DOMAIN_XML_UPDATE_CPU)))
+                                        VIR_DOMAIN_XML_UPDATE_CPU,
+                                        true)))
         return -1;
 
     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
index 3a21a39b456bb9c8e0b0124f699f73339a944395..27fefbaab164c7b26c33d20ff4779e0319d899a0 100644 (file)
@@ -3320,7 +3320,7 @@ int qemuProcessStart(virConnectPtr conn,
 
     /* Run an early hook to set-up missing devices */
     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
-        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
+        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
         int hookret;
 
         hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,
@@ -3513,7 +3513,7 @@ int qemuProcessStart(virConnectPtr conn,
 
     /* now that we know it is about to start call the hook if present */
     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
-        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
+        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
         int hookret;
 
         hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,
@@ -3953,7 +3953,7 @@ void qemuProcessStop(struct qemud_driver *driver,
 
     /* now that we know it's stopped call the hook if present */
     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
-        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
+        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
 
         /* we can't stop the operation even if the script raised an error */
         virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,
@@ -4046,7 +4046,7 @@ retry:
 
     /* The "release" hook cleans up additional resources */
     if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
-        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
+        char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
 
         /* we can't stop the operation even if the script raised an error */
         virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,