mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
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
This commit is contained in:
parent
3700c065cd
commit
f1a89a8b6d
@ -14655,61 +14655,64 @@ virDomainDefParseXML(xmlDocPtr xml,
|
|||||||
goto error;
|
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,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
_("no support found for os <type> '%s'"),
|
_("Unknown architecture %s"),
|
||||||
def->os.type);
|
tmp);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
|
||||||
tmp = virXPathString("string(./os/type[1]/@arch)", ctxt);
|
def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt);
|
||||||
if (tmp) {
|
|
||||||
def->os.arch = virArchFromString(tmp);
|
if (!(flags & VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)) {
|
||||||
if (!def->os.arch) {
|
if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
_("Unknown architecture %s"),
|
_("no support found for os <type> '%s'"),
|
||||||
tmp);
|
|
||||||
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 (!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);
|
def->os.type);
|
||||||
goto error;
|
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;
|
||||||
|
}
|
||||||
|
} 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....
|
* Booting options for different OS types....
|
||||||
@ -21591,7 +21594,8 @@ virDomainObjListLoadConfig(virDomainObjListPtr doms,
|
|||||||
goto error;
|
goto error;
|
||||||
if (!(def = virDomainDefParseFile(configFile, caps, xmlopt,
|
if (!(def = virDomainDefParseFile(configFile, caps, xmlopt,
|
||||||
expectedVirtTypes,
|
expectedVirtTypes,
|
||||||
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
||||||
|
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
|
if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
|
||||||
@ -21641,7 +21645,8 @@ virDomainObjListLoadStatus(virDomainObjListPtr doms,
|
|||||||
VIR_DOMAIN_DEF_PARSE_STATUS |
|
VIR_DOMAIN_DEF_PARSE_STATUS |
|
||||||
VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
|
VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
|
||||||
VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
|
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;
|
goto error;
|
||||||
|
|
||||||
virUUIDFormat(obj->def->uuid, uuidstr);
|
virUUIDFormat(obj->def->uuid, uuidstr);
|
||||||
|
@ -2530,6 +2530,10 @@ typedef enum {
|
|||||||
/* parse only source half of <disk> */
|
/* parse only source half of <disk> */
|
||||||
VIR_DOMAIN_DEF_PARSE_DISK_SOURCE = 1 << 7,
|
VIR_DOMAIN_DEF_PARSE_DISK_SOURCE = 1 << 7,
|
||||||
VIR_DOMAIN_DEF_PARSE_VALIDATE = 1 << 8,
|
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;
|
} virDomainDefParseFlags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -270,6 +270,9 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
|
|||||||
* clients will have to decide between best effort
|
* clients will have to decide between best effort
|
||||||
* initialization or outright failure. */
|
* initialization or outright failure. */
|
||||||
if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
|
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);
|
xmlNodePtr domainNode = virXPathNode("./domain", ctxt);
|
||||||
|
|
||||||
VIR_FREE(tmp);
|
VIR_FREE(tmp);
|
||||||
@ -280,8 +283,7 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
|
|||||||
}
|
}
|
||||||
def->dom = virDomainDefParseNode(ctxt->node->doc, domainNode,
|
def->dom = virDomainDefParseNode(ctxt->node->doc, domainNode,
|
||||||
caps, xmlopt,
|
caps, xmlopt,
|
||||||
expectedVirtTypes,
|
expectedVirtTypes, domainflags);
|
||||||
VIR_DOMAIN_DEF_PARSE_INACTIVE);
|
|
||||||
if (!def->dom)
|
if (!def->dom)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user