提交 2578d74a 编写于 作者: D Daniel P. Berrangé

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: NMichal Privoznik <mprivozn@redhat.com>
Signed-off-by: NDaniel P. Berrangé <berrange@redhat.com>
上级 6430c005
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册