[libvirt] [PATCH 02/11] domain: conf: Don't validate VM ostype/arch at daemon startup

Cole Robinson crobinso at redhat.com
Sat Apr 18 01:45:12 UTC 2015


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
---
 src/conf/domain_conf.c   | 93 +++++++++++++++++++++++++-----------------------
 src/conf/domain_conf.h   |  4 +++
 src/conf/snapshot_conf.c |  6 ++--
 3 files changed, 57 insertions(+), 46 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8458f5b..860c950 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14655,61 +14655,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....
@@ -21591,7 +21594,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)
@@ -21641,7 +21645,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);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e6fa3c9..3045652 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2530,6 +2530,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 {
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index df19449..e725a23 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -270,6 +270,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);
@@ -280,8 +283,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 {
-- 
2.3.5




More information about the libvir-list mailing list