From f1a89a8b6d1a1097e41a171a13b1984b06e8ab3e Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Fri, 17 Apr 2015 16:37:57 -0400 Subject: [PATCH] domain: conf: Don't validate VM ostype/arch at daemon startup 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 8458f5b224..860c9501ca 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 '%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 '%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 e6fa3c9220..30456524bb 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2530,6 +2530,10 @@ typedef enum { /* parse only source half of */ 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 df19449b38..e725a235fe 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 { -- GitLab