On Mon, Dec 09, 2019 at 01:21:05PM -0500, Cole Robinson wrote:
On 12/4/19 9:20 AM, Daniel P. Berrangé wrote:
> 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.
>
> Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
> ---
> src/bhyve/bhyve_domain.c | 7 ++++++-
> src/conf/capabilities.c | 17 +++++++++++++++++
> src/conf/capabilities.h | 7 +++++++
> src/conf/domain_conf.c | 19 ++-----------------
> src/libvirt_private.syms | 1 +
> src/libxl/libxl_domain.c | 7 ++++++-
> src/lxc/lxc_domain.c | 5 +++++
> src/openvz/openvz_conf.c | 7 ++++++-
> src/phyp/phyp_driver.c | 9 +++++++--
> src/qemu/qemu_domain.c | 19 +++++++++++++++----
> src/vmware/vmware_driver.c | 9 +++++++--
> src/vmx/vmx.c | 9 +++++++--
> src/vz/vz_driver.c | 7 ++++++-
> 13 files changed, 92 insertions(+), 31 deletions(-)
>
> diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
> index 7d24bb602f..575f141b53 100644
> --- a/src/bhyve/bhyve_domain.c
> +++ b/src/bhyve/bhyve_domain.c
> @@ -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)
> diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
> index ff7d265621..748dd64273 100644
> --- a/src/conf/capabilities.c
> +++ b/src/conf/capabilities.c
> @@ -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)
> diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
> index 8a7137d7eb..c39fe0de08 100644
> --- a/src/conf/capabilities.h
> +++ b/src/conf/capabilities.h
> @@ -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);
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 1c2b8f26ed..6abe15f721 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -19565,14 +19565,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);
> @@ -19633,18 +19630,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;
> }
>
This series is a move in the right direction IMO, there's a couple
issues though.
We drop the VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE protection here, by
moving the equivalent into the PostParse callback and not the Validate
callback. This reintroduces the recurring problem of VMs disappearing on
libvirt restart, if host capabilities change.
There is VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL, which has different
behavior, all these error checks would need to 'return 1', but I think
drivers need specially handling for this so I'm not sure if it's a
simple change like that.
Oh, I was mislead in my reading of qemuDomainDefPostParse, as I
saw that it already returned error when os.machine is NULL, but
I didn't realize we'd never even be calling qemuDomainDefPostParse
in that case, as the virDomainDefParseCaps() willl have caused it
to be skipped.
Another issue: other drivers use the machine= setting too, libxl at
least. This appears to drop filling in a default machine type for them,
at least at XML parse time.
I thought that was the case too, but I couln't find any functional use
of def->os.machine in any of the other drivers:
$ git grep os.machine | grep -v -E '(qemu|conf)/'
libvirt-domain.c: * "os.machine" - the machine hardware name as a string
libxl/libxl_conf.c: def->os.machine);
libxl/xen_common.c: def->os.machine = g_strdup(capsdata->machinetype);
vbox/vbox_common.c: VIR_DEBUG("def->os.machine %s",
def->os.machine);
vz/vz_sdk.c: if (def->os.machine != NULL || def->os.bootmenu != 0 ||
that libxl_conf.c usage is just an error message
The xen_common.c usage is just when parsing XM/XL config files,
so output only.
The vz_sdk.c usage reports error for any non-NULL machine
I guess there is a difference in that if the user does dumpxml for a
libxl guest we've no longer filled in the machine. I can fix that,
but it doesn't look like it'll have a functional effect.
Regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|