mirror of https://gitee.com/openkylin/libvirt.git
conf: move virt type / os type / arch validation to post-parse
The XML parser currently calls virCapabilitiesDomainDataLookup during parsing to find the domain capabilities matching the triple (virt type, os type, arch) This is, however, bogus with the QEMU driver as it assumes that there is an emulator known to the default driver capabilities that matches this triple. It is entirely possible for the driver to be parsing an XML file with a custom emulator path specified pointing to a binary that doesn't exist in the default driver capabilities. This will, for example be the case on a RHEL host which only installs the host native emulator to /usr/bin. The user can have built a custom QEMU for non-native arches into $HOME and wish to use that. Aside from validation, this call is also used to fill in a machine type for the guest if not otherwise specified. Again, this data may be incorrect for the QEMU driver because it is not taking account of the emulator binary that is referenced. To start fixing this, move the validation to the post-parse callbacks where more intelligent driver specific logic can be applied. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
6430c00552
commit
2578d74aee
|
@ -74,11 +74,16 @@ bhyveDomainDefNeedsISAController(virDomainDefPtr def)
|
|||
|
||||
static int
|
||||
bhyveDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
/* Add an implicit PCI root controller */
|
||||
if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
|
||||
|
|
|
@ -816,6 +816,23 @@ virCapabilitiesDomainDataLookup(virCapsPtr caps,
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
virCapabilitiesDomainSupported(virCapsPtr caps,
|
||||
int ostype,
|
||||
virArch arch,
|
||||
int virttype)
|
||||
{
|
||||
g_autofree virCapsDomainDataPtr capsdata = NULL;
|
||||
|
||||
capsdata = virCapabilitiesDomainDataLookup(caps, ostype,
|
||||
arch,
|
||||
virttype,
|
||||
NULL, NULL);
|
||||
|
||||
return capsdata != NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virCapabilitiesAddStoragePool(virCapsPtr caps,
|
||||
int poolType)
|
||||
|
|
|
@ -309,6 +309,13 @@ virCapabilitiesDomainDataLookup(virCapsPtr caps,
|
|||
const char *emulator,
|
||||
const char *machinetype);
|
||||
|
||||
bool
|
||||
virCapabilitiesDomainSupported(virCapsPtr caps,
|
||||
int ostype,
|
||||
virArch arch,
|
||||
int domaintype);
|
||||
|
||||
|
||||
void
|
||||
virCapabilitiesClearHostNUMACellCPUTopology(virCapsHostNUMACellCPUPtr cpu,
|
||||
size_t ncpus);
|
||||
|
|
|
@ -19613,14 +19613,11 @@ virDomainCachetuneDefParse(virDomainDefPtr def,
|
|||
static int
|
||||
virDomainDefParseCaps(virDomainDefPtr def,
|
||||
xmlXPathContextPtr ctxt,
|
||||
virDomainXMLOptionPtr xmlopt,
|
||||
virCapsPtr caps,
|
||||
unsigned int flags)
|
||||
virDomainXMLOptionPtr xmlopt)
|
||||
{
|
||||
g_autofree char *virttype = NULL;
|
||||
g_autofree char *arch = NULL;
|
||||
g_autofree char *ostype = NULL;
|
||||
g_autofree virCapsDomainDataPtr capsdata = NULL;
|
||||
|
||||
virttype = virXPathString("string(./@type)", ctxt);
|
||||
ostype = virXPathString("string(./os/type[1])", ctxt);
|
||||
|
@ -19681,18 +19678,6 @@ virDomainDefParseCaps(virDomainDefPtr def,
|
|||
def->os.arch = virArchFromHost();
|
||||
}
|
||||
|
||||
if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType,
|
||||
NULL, NULL))) {
|
||||
if (!(flags & VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))
|
||||
return -1;
|
||||
virResetLastError();
|
||||
} else {
|
||||
if (!def->os.machine)
|
||||
def->os.machine = g_strdup(capsdata->machinetype);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19846,7 +19831,7 @@ virDomainDefParseXML(xmlDocPtr xml,
|
|||
id = -1;
|
||||
def->id = (int)id;
|
||||
|
||||
if (virDomainDefParseCaps(def, ctxt, xmlopt, caps, flags) < 0)
|
||||
if (virDomainDefParseCaps(def, ctxt, xmlopt) < 0)
|
||||
goto error;
|
||||
|
||||
/* Extract domain name */
|
||||
|
|
|
@ -54,6 +54,7 @@ virCapabilitiesAddStoragePool;
|
|||
virCapabilitiesAllocMachines;
|
||||
virCapabilitiesClearHostNUMACellCPUTopology;
|
||||
virCapabilitiesDomainDataLookup;
|
||||
virCapabilitiesDomainSupported;
|
||||
virCapabilitiesFormatXML;
|
||||
virCapabilitiesFreeGuest;
|
||||
virCapabilitiesFreeMachines;
|
||||
|
|
|
@ -367,11 +367,16 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
|
|||
|
||||
static int
|
||||
libxlDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
/* Xen PV domains always have a PV console, so add one to the domain config
|
||||
* via post-parse callback if not explicitly specified in the XML. */
|
||||
if (def->os.type != VIR_DOMAIN_OSTYPE_HVM && def->nconsoles == 0) {
|
||||
|
|
|
@ -356,6 +356,11 @@ virLXCDomainDefPostParse(virDomainDefPtr def,
|
|||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
/* check for emulator and create a default one if needed */
|
||||
if (!def->emulator &&
|
||||
!(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))
|
||||
|
|
|
@ -1082,11 +1082,16 @@ int openvzGetVEID(const char *name)
|
|||
|
||||
static int
|
||||
openvzDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
/* fill the init path */
|
||||
if (def->os.type == VIR_DOMAIN_OSTYPE_EXE && !def->os.init)
|
||||
def->os.init = g_strdup("/sbin/init");
|
||||
|
|
|
@ -1061,12 +1061,17 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
|
|||
|
||||
|
||||
static int
|
||||
phypDomainDefPostParse(virDomainDefPtr def G_GNUC_UNUSED,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
phypDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -4691,7 +4691,7 @@ qemuDomainDefPostParseBasic(virDomainDefPtr def,
|
|||
|
||||
static int
|
||||
qemuDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags,
|
||||
void *opaque,
|
||||
void *parseOpaque)
|
||||
|
@ -4703,6 +4703,11 @@ qemuDomainDefPostParse(virDomainDefPtr def,
|
|||
* with the capabilities populated. */
|
||||
virQEMUCapsPtr qemuCaps = parseOpaque;
|
||||
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
if (def->os.bootloader || def->os.bootloaderArgs) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("bootloader is not supported by QEMU"));
|
||||
|
@ -4710,9 +4715,15 @@ qemuDomainDefPostParse(virDomainDefPtr def,
|
|||
}
|
||||
|
||||
if (!def->os.machine) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("missing machine type"));
|
||||
return -1;
|
||||
g_autofree virCapsDomainDataPtr capsdata = NULL;
|
||||
|
||||
if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType,
|
||||
NULL, NULL))) {
|
||||
return -1;
|
||||
}
|
||||
def->os.machine = g_strdup(capsdata->machinetype);
|
||||
}
|
||||
|
||||
qemuDomainNVRAMPathGenerate(cfg, def);
|
||||
|
|
|
@ -116,12 +116,17 @@ vmwareDataFreeFunc(void *data)
|
|||
}
|
||||
|
||||
static int
|
||||
vmwareDomainDefPostParse(virDomainDefPtr def G_GNUC_UNUSED,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
vmwareDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -529,12 +529,17 @@ VIR_ENUM_IMPL(virVMXControllerModelSCSI,
|
|||
*/
|
||||
|
||||
static int
|
||||
virVMXDomainDefPostParse(virDomainDefPtr def G_GNUC_UNUSED,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virVMXDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,11 +241,16 @@ vzDomainDefAddDefaultInputDevices(virDomainDefPtr def)
|
|||
|
||||
static int
|
||||
vzDomainDefPostParse(virDomainDefPtr def,
|
||||
virCapsPtr caps G_GNUC_UNUSED,
|
||||
virCapsPtr caps,
|
||||
unsigned int parseFlags G_GNUC_UNUSED,
|
||||
void *opaque G_GNUC_UNUSED,
|
||||
void *parseOpaque G_GNUC_UNUSED)
|
||||
{
|
||||
if (!virCapabilitiesDomainSupported(caps, def->os.type,
|
||||
def->os.arch,
|
||||
def->virtType))
|
||||
return -1;
|
||||
|
||||
if (vzDomainDefAddDefaultInputDevices(def) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue