]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
domain: conf: Don't validate VM ostype/arch at daemon startup
authorCole Robinson <crobinso@redhat.com>
Fri, 17 Apr 2015 20:37:57 +0000 (16:37 -0400)
committerCole Robinson <crobinso@redhat.com>
Tue, 28 Apr 2015 00:23:35 +0000 (20:23 -0400)
When parsing XML, we validate the passed ostype + arch combo against
the detected hypervisor capabilities. This has led to the following
problem:

- Define x86 qemu guest
- qemu is inadvertently removed from the host
- libvirtd is restarted. fails to parse VM config since arch is removed
- 'virsh list --all' is now empty, user is wondering where their VMs went

Add a new internal flag VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS. Use
it when loading VM and snapshot configs from disk.

https://bugzilla.redhat.com/show_bug.cgi?id=1043572
(cherry picked from commit f1a89a8b6d1a1097e41a171a13b1984b06e8ab3e)

src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/snapshot_conf.c

index d9435233f8364c4c8e2a3673a7ad4d586a4f7d9a..32809c0600b15aed3b31cc1b123899895ac60b14 100644 (file)
@@ -13968,61 +13968,64 @@ virDomainDefParseXML(xmlDocPtr xml,
             goto error;
     }
 
-    if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
+    tmp = virXPathString("string(./os/type[1]/@arch)", ctxt);
+    if (tmp && !(def->os.arch = virArchFromString(tmp))) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("no support found for os <type> '%s'"),
-                       def->os.type);
+                       _("Unknown architecture %s"),
+                       tmp);
         goto error;
     }
+    VIR_FREE(tmp);
 
-    tmp = virXPathString("string(./os/type[1]/@arch)", ctxt);
-    if (tmp) {
-        def->os.arch = virArchFromString(tmp);
-        if (!def->os.arch) {
+    def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt);
+
+    if (!(flags & VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)) {
+        if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Unknown architecture %s"),
-                           tmp);
+                           _("no support found for os <type> '%s'"),
+                           def->os.type);
             goto error;
         }
-        VIR_FREE(tmp);
 
-        if (!virCapabilitiesSupportsGuestArch(caps, def->os.arch)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("No guest options available for arch '%s'"),
-                           virArchToString(def->os.arch));
-            goto error;
-        }
+        if (def->os.arch) {
+            if (!virCapabilitiesSupportsGuestArch(caps, def->os.arch)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("No guest options available for arch '%s'"),
+                               virArchToString(def->os.arch));
+                goto error;
+            }
 
-        if (!virCapabilitiesSupportsGuestOSTypeArch(caps,
-                                                    def->os.type,
-                                                    def->os.arch)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("No os type '%s' available for arch '%s'"),
-                           def->os.type, virArchToString(def->os.arch));
-            goto error;
+            if (!virCapabilitiesSupportsGuestOSTypeArch(caps,
+                                                        def->os.type,
+                                                        def->os.arch)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("No os type '%s' available for arch '%s'"),
+                               def->os.type, virArchToString(def->os.arch));
+                goto error;
+            }
+        } else {
+            def->os.arch =
+                virCapabilitiesDefaultGuestArch(caps,
+                                                def->os.type,
+                                                virDomainVirtTypeToString(def->virtType));
+            if (!def->os.arch) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("no supported architecture for os type '%s'"),
+                               def->os.type);
+                goto error;
+            }
         }
-    } else {
-        def->os.arch =
-            virCapabilitiesDefaultGuestArch(caps,
-                                            def->os.type,
-                                            virDomainVirtTypeToString(def->virtType));
-        if (!def->os.arch) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("no supported architecture for os type '%s'"),
-                           def->os.type);
-            goto error;
+
+        if (!def->os.machine) {
+            const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
+                                                                            def->os.type,
+                                                                            def->os.arch,
+                                                                            virDomainVirtTypeToString(def->virtType));
+            if (VIR_STRDUP(def->os.machine, defaultMachine) < 0)
+                goto error;
         }
     }
 
-    def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt);
-    if (!def->os.machine) {
-        const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
-                                                                        def->os.type,
-                                                                        def->os.arch,
-                                                                        virDomainVirtTypeToString(def->virtType));
-        if (VIR_STRDUP(def->os.machine, defaultMachine) < 0)
-            goto error;
-    }
 
     /*
      * Booting options for different OS types....
@@ -20719,7 +20722,8 @@ virDomainObjListLoadConfig(virDomainObjListPtr doms,
         goto error;
     if (!(def = virDomainDefParseFile(configFile, caps, xmlopt,
                                       expectedVirtTypes,
-                                      VIR_DOMAIN_DEF_PARSE_INACTIVE)))
+                                      VIR_DOMAIN_DEF_PARSE_INACTIVE |
+                                      VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)))
         goto error;
 
     if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
@@ -20769,7 +20773,8 @@ virDomainObjListLoadStatus(virDomainObjListPtr doms,
                                       VIR_DOMAIN_DEF_PARSE_STATUS |
                                       VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
                                       VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
-                                      VIR_DOMAIN_DEF_PARSE_CLOCK_ADJUST)))
+                                      VIR_DOMAIN_DEF_PARSE_CLOCK_ADJUST |
+                                      VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)))
         goto error;
 
     virUUIDFormat(obj->def->uuid, uuidstr);
index 02ddd93a4d2234b826f65cbd2c605cfff3fdee98..b6c0a52d324876cdf7bbb6a04dd5b129e4d15697 100644 (file)
@@ -2477,6 +2477,10 @@ typedef enum {
     /* parse only source half of <disk> */
     VIR_DOMAIN_DEF_PARSE_DISK_SOURCE     = 1 << 7,
     VIR_DOMAIN_DEF_PARSE_VALIDATE        = 1 << 8,
+    /* don't validate os.type and arch against capabilities. Prevents
+     * VMs from disappearing when qemu is removed and libvirtd is restarted
+     */
+    VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS = 1 << 9,
 } virDomainDefParseFlags;
 
 typedef enum {
index a0667c2824be3191eb9442e1cc195be5ca50d99a..4e504bf14214d6716e00372db6cd21df0130b3bd 100644 (file)
@@ -276,6 +276,9 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
          * clients will have to decide between best effort
          * initialization or outright failure.  */
         if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
+            int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
+            if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL)
+                domainflags |= VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS;
             xmlNodePtr domainNode = virXPathNode("./domain", ctxt);
 
             VIR_FREE(tmp);
@@ -286,8 +289,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
             }
             def->dom = virDomainDefParseNode(ctxt->node->doc, domainNode,
                                              caps, xmlopt,
-                                             expectedVirtTypes,
-                                             VIR_DOMAIN_DEF_PARSE_INACTIVE);
+                                             expectedVirtTypes, domainflags);
             if (!def->dom)
                 goto cleanup;
         } else {