[libvirt] [PATCH V3 0/6] libxl: Add support for UEFI using OVMF

This is essentially a V3 of https://www.redhat.com/archives/libvir-list/2016-April/msg01358.html To avoid code duplication in that series, I proposed adding a virFirmware object that could be used by multiple drivers https://www.redhat.com/archives/libvir-list/2016-May/msg01370.html mprivozn ACK'ed that series, but I deferred committing it until 1.3.5 was released since it's not all that useful without accompanying use by another driver. Jim Fehlig (6): driver config: Introduce virFirmware object libxl: add default firmwares to driver config object libxl: introduce libxl_capabilities.{ch} libxl: implement connectGetDomainCapabilities xenconfig: support bios=ovmf xl.cfg libxl: Add support for ovmf firmware po/POTFILES.in | 2 + src/Makefile.am | 12 +- src/libvirt_private.syms | 6 + src/libxl/libxl_capabilities.c | 598 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 57 +++ src/libxl/libxl_conf.c | 460 ++-------------------- src/libxl/libxl_conf.h | 22 +- src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 75 ++++ src/qemu/qemu_capabilities.c | 22 +- src/qemu/qemu_capabilities.h | 5 +- src/qemu/qemu_conf.c | 127 +----- src/qemu/qemu_conf.h | 7 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 6 +- src/util/virfirmware.c | 137 +++++++ src/util/virfirmware.h | 51 +++ src/xenconfig/xen_xl.c | 37 +- tests/Makefile.am | 5 + tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 +++ tests/domaincapstest.c | 64 ++- tests/testutils.c | 16 + tests/testutils.h | 2 + tests/testutilsxen.h | 1 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 ++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 +++ tests/xlconfigtest.c | 90 ++++- 28 files changed, 1415 insertions(+), 600 deletions(-) create mode 100644 src/libxl/libxl_capabilities.c create mode 100644 src/libxl/libxl_capabilities.h create mode 100644 src/util/virfirmware.c create mode 100644 src/util/virfirmware.h create mode 100644 tests/domaincapsschemadata/libxl-xenfv.xml create mode 100644 tests/domaincapsschemadata/libxl-xenpv.xml create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.xml -- 2.1.4

The virQEMUDriverConfig object contains lists of loader:nvram pairs to advertise firmwares supported by by the driver, and qemu_conf.c contains code to populate the lists, all of which is useful for other drivers too. To avoid code duplication, introduce a virFirmware object to encapsulate firmware details and switch the qemu driver to use it. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 6 ++ src/qemu/qemu_capabilities.c | 22 +++---- src/qemu/qemu_capabilities.h | 5 +- src/qemu/qemu_conf.c | 127 ++++++--------------------------------- src/qemu/qemu_conf.h | 7 +-- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 6 +- src/util/virfirmware.c | 137 +++++++++++++++++++++++++++++++++++++++++++ src/util/virfirmware.h | 51 ++++++++++++++++ tests/domaincapstest.c | 3 +- 12 files changed, 237 insertions(+), 131 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 4aa979f..d6e79a8 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -194,6 +194,7 @@ src/util/virerror.h src/util/vireventpoll.c src/util/virfile.c src/util/virfirewall.c +src/util/virfirmware.c src/util/virhash.c src/util/virhook.c src/util/virhostcpu.c diff --git a/src/Makefile.am b/src/Makefile.am index ee4a7bf..d0782f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,6 +114,7 @@ UTIL_SOURCES = \ util/virfile.c util/virfile.h \ util/virfirewall.c util/virfirewall.h \ util/virfirewallpriv.h \ + util/virfirmware.c util/virfirmware.h \ util/virgettext.c util/virgettext.h \ util/virgic.c util/virgic.h \ util/virhash.c util/virhash.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 85b9cd1..234420e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1563,6 +1563,12 @@ virFirewallStartRollback; virFirewallStartTransaction; +# util/virfirmware.h +virFirmwareFreeList; +virFirmwareParse; +virFirmwareParseList; + + # util/virgettext.h virGettextInitialize; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d9f04c8..b9f3fe0 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4071,18 +4071,18 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps) static int virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoaderPtr capsLoader, - char **loader, - size_t nloader) + virFirmwarePtr *firmwares, + size_t nfirmwares) { size_t i; capsLoader->supported = true; - if (VIR_ALLOC_N(capsLoader->values.values, nloader) < 0) + if (VIR_ALLOC_N(capsLoader->values.values, nfirmwares) < 0) return -1; - for (i = 0; i < nloader; i++) { - const char *filename = loader[i]; + for (i = 0; i < nfirmwares; i++) { + const char *filename = firmwares[i]->name; if (!virFileExists(filename)) { VIR_DEBUG("loader filename=%s does not exist", filename); @@ -4111,13 +4111,13 @@ virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoaderPtr capsLoader, static int virQEMUCapsFillDomainOSCaps(virDomainCapsOSPtr os, - char **loader, - size_t nloader) + virFirmwarePtr *firmwares, + size_t nfirmwares) { virDomainCapsLoaderPtr capsLoader = &os->loader; os->supported = true; - if (virQEMUCapsFillDomainLoaderCaps(capsLoader, loader, nloader) < 0) + if (virQEMUCapsFillDomainLoaderCaps(capsLoader, firmwares, nfirmwares) < 0) return -1; return 0; } @@ -4330,8 +4330,8 @@ virQEMUCapsFillDomainFeatureGICCaps(virQEMUCapsPtr qemuCaps, int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, virQEMUCapsPtr qemuCaps, - char **loader, - size_t nloader) + virFirmwarePtr *firmwares, + size_t nfirmwares) { virDomainCapsOSPtr os = &domCaps->os; virDomainCapsDeviceDiskPtr disk = &domCaps->disk; @@ -4342,7 +4342,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, domCaps->maxvcpus = maxvcpus; - if (virQEMUCapsFillDomainOSCaps(os, loader, nloader) < 0 || + if (virQEMUCapsFillDomainOSCaps(os, firmwares, nfirmwares) < 0 || virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, domCaps->machine, disk) < 0 || virQEMUCapsFillDomainDeviceGraphicsCaps(qemuCaps, graphics) < 0 || diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e273f2a..d33ba00 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -29,6 +29,7 @@ # include "vircommand.h" # include "qemu_monitor.h" # include "domain_capabilities.h" +# include "virfirmware.h" /* * Internal flags to keep track of qemu command line capabilities @@ -491,7 +492,7 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps, int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, virQEMUCapsPtr qemuCaps, - char **loader, - size_t nloader); + virFirmwarePtr *firmwares, + size_t nfirmwares); #endif /* __QEMU_CAPABILITIES_H__*/ diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index d4c34c9..6dfa738 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -124,47 +124,6 @@ void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def) } -static int ATTRIBUTE_UNUSED -virQEMUDriverConfigLoaderNVRAMParse(virQEMUDriverConfigPtr cfg, - const char *list) -{ - int ret = -1; - char **token; - size_t i, j; - - if (!(token = virStringSplit(list, ":", 0))) - goto cleanup; - - for (i = 0; token[i]; i += 2) { - if (!token[i] || !token[i + 1] || - STREQ(token[i], "") || STREQ(token[i + 1], "")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid --with-loader-nvram list: %s"), - list); - goto cleanup; - } - } - - if (i) { - if (VIR_ALLOC_N(cfg->loader, i / 2) < 0 || - VIR_ALLOC_N(cfg->nvram, i / 2) < 0) - goto cleanup; - cfg->nloader = i / 2; - - for (j = 0; j < i / 2; j++) { - if (VIR_STRDUP(cfg->loader[j], token[2 * j]) < 0 || - VIR_STRDUP(cfg->nvram[j], token[2 * j + 1]) < 0) - goto cleanup; - } - } - - ret = 0; - cleanup: - virStringFreeList(token); - return ret; -} - - #define VIR_QEMU_OVMF_LOADER_PATH "/usr/share/OVMF/OVMF_CODE.fd" #define VIR_QEMU_OVMF_NVRAM_PATH "/usr/share/OVMF/OVMF_VARS.fd" #define VIR_QEMU_AAVMF_LOADER_PATH "/usr/share/AAVMF/AAVMF_CODE.fd" @@ -327,20 +286,22 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) cfg->stdioLogD = true; #ifdef DEFAULT_LOADER_NVRAM - if (virQEMUDriverConfigLoaderNVRAMParse(cfg, DEFAULT_LOADER_NVRAM) < 0) + if (virFirmwareParseList(DEFAULT_LOADER_NVRAM, + &cfg->firmwares, + &cfg->nfirmwares) < 0) goto error; #else - - if (VIR_ALLOC_N(cfg->loader, 2) < 0 || - VIR_ALLOC_N(cfg->nvram, 2) < 0) + if (VIR_ALLOC_N(cfg->firmwares, 2) < 0) + goto error; + cfg->nfirmwares = 2; + if (VIR_ALLOC(cfg->firmwares[0]) < 0 || VIR_ALLOC(cfg->firmwares[1]) < 0) goto error; - cfg->nloader = 2; - if (VIR_STRDUP(cfg->loader[0], VIR_QEMU_AAVMF_LOADER_PATH) < 0 || - VIR_STRDUP(cfg->nvram[0], VIR_QEMU_AAVMF_NVRAM_PATH) < 0 || - VIR_STRDUP(cfg->loader[1], VIR_QEMU_OVMF_LOADER_PATH) < 0 || - VIR_STRDUP(cfg->nvram[1], VIR_QEMU_OVMF_NVRAM_PATH) < 0) + if (VIR_STRDUP(cfg->firmwares[0]->name, VIR_QEMU_AAVMF_LOADER_PATH) < 0 || + VIR_STRDUP(cfg->firmwares[0]->nvram, VIR_QEMU_AAVMF_NVRAM_PATH) < 0 || + VIR_STRDUP(cfg->firmwares[1]->name, VIR_QEMU_OVMF_LOADER_PATH) < 0 || + VIR_STRDUP(cfg->firmwares[1]->nvram, VIR_QEMU_OVMF_NVRAM_PATH) < 0) goto error; #endif @@ -397,13 +358,7 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->lockManagerName); - while (cfg->nloader) { - VIR_FREE(cfg->loader[cfg->nloader - 1]); - VIR_FREE(cfg->nvram[cfg->nloader - 1]); - cfg->nloader--; - } - VIR_FREE(cfg->loader); - VIR_FREE(cfg->nvram); + virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares); } @@ -427,43 +382,6 @@ virQEMUDriverConfigHugeTLBFSInit(virHugeTLBFSPtr hugetlbfs, } -static int -virQEMUDriverConfigNVRAMParse(const char *str, - char **loader, - char **nvram) -{ - int ret = -1; - char **token; - - if (!(token = virStringSplit(str, ":", 0))) - goto cleanup; - - if (token[0]) { - virSkipSpaces((const char **) &token[0]); - if (token[1]) - virSkipSpaces((const char **) &token[1]); - } - - /* Exactly two tokens are expected */ - if (!token[0] || !token[1] || token[2] || - STREQ(token[0], "") || STREQ(token[1], "")) { - virReportError(VIR_ERR_CONF_SYNTAX, - _("Invalid nvram format: '%s'"), - str); - goto cleanup; - } - - if (VIR_STRDUP(*loader, token[0]) < 0 || - VIR_STRDUP(*nvram, token[1]) < 0) - goto cleanup; - - ret = 0; - cleanup: - virStringFreeList(token); - return ret; -} - - int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename) { @@ -855,14 +773,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, CHECK_TYPE("nvram", VIR_CONF_LIST); - while (cfg->nloader) { - VIR_FREE(cfg->loader[cfg->nloader - 1]); - VIR_FREE(cfg->nvram[cfg->nloader - 1]); - cfg->nloader--; - } - VIR_FREE(cfg->loader); - VIR_FREE(cfg->nvram); - + virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares); /* Calc length and check items */ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { if (pp->type != VIR_CONF_STRING) { @@ -872,16 +783,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, } } - if (len && - (VIR_ALLOC_N(cfg->loader, len) < 0 || - VIR_ALLOC_N(cfg->nvram, len) < 0)) + if (len && VIR_ALLOC_N(cfg->firmwares, len) < 0) goto cleanup; - cfg->nloader = len; + cfg->nfirmwares = len; for (i = 0, pp = p->list; pp; i++, pp = pp->next) { - if (virQEMUDriverConfigNVRAMParse(pp->str, - &cfg->loader[i], - &cfg->nvram[i]) < 0) + if (VIR_ALLOC(cfg->firmwares[i]) < 0) + goto cleanup; + if (virFirmwareParse(pp->str, cfg->firmwares[i]) < 0) goto cleanup; } } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index e830b40..a09c81d 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -48,6 +48,7 @@ # include "virclosecallbacks.h" # include "virhostdev.h" # include "virfile.h" +# include "virfirmware.h" # ifdef CPU_SETSIZE /* Linux */ # define QEMUD_CPUMASK_LEN CPU_SETSIZE @@ -178,10 +179,8 @@ struct _virQEMUDriverConfig { bool logTimestamp; bool stdioLogD; - /* Pairs of loader:nvram paths. The list is @nloader items long */ - char **loader; - char **nvram; - size_t nloader; + virFirmwarePtr *firmwares; + size_t nfirmwares; }; /* Main driver state */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index efb3f85..a45fd55 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18534,7 +18534,7 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn, goto cleanup; if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, - cfg->loader, cfg->nloader) < 0) + cfg->firmwares, cfg->nfirmwares) < 0) goto cleanup; ret = virDomainCapsFormat(domCaps); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 2f3eb96..01d607d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3724,9 +3724,9 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, master_nvram_path = loader->templt; if (!loader->templt) { size_t i; - for (i = 0; i < cfg->nloader; i++) { - if (STREQ(cfg->loader[i], loader->path)) { - master_nvram_path = cfg->nvram[i]; + for (i = 0; i < cfg->nfirmwares; i++) { + if (STREQ(cfg->firmwares[i]->name, loader->path)) { + master_nvram_path = cfg->firmwares[i]->nvram; break; } } diff --git a/src/util/virfirmware.c b/src/util/virfirmware.c new file mode 100644 index 0000000..6b20c06 --- /dev/null +++ b/src/util/virfirmware.c @@ -0,0 +1,137 @@ +/* + * virfirmware.c: Definition of firmware object and supporting functions + * + * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Jim Fehlig <jfehlig@suse.com> + */ + +#include <config.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virfirmware.h" +#include "virlog.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +VIR_LOG_INIT("util.firmware"); + + +static void +virFirmwareFree(virFirmwarePtr firmware) +{ + if (!firmware) + return; + + VIR_FREE(firmware->name); + VIR_FREE(firmware->nvram); + VIR_FREE(firmware); +} + + +void +virFirmwareFreeList(virFirmwarePtr *firmwares, size_t nfirmwares) +{ + size_t i; + + for (i = 0; i < nfirmwares; i++) + virFirmwareFree(firmwares[i]); + + VIR_FREE(firmwares); +} + + +int +virFirmwareParse(const char *str, virFirmwarePtr firmware) +{ + int ret = -1; + char **token; + + if (!(token = virStringSplit(str, ":", 0))) + goto cleanup; + + if (token[0]) { + virSkipSpaces((const char **) &token[0]); + if (token[1]) + virSkipSpaces((const char **) &token[1]); + } + + /* Exactly two tokens are expected */ + if (!token[0] || !token[1] || token[2] || + STREQ(token[0], "") || STREQ(token[1], "")) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("Invalid nvram format: '%s'"), + str); + goto cleanup; + } + + if (VIR_STRDUP(firmware->name, token[0]) < 0 || + VIR_STRDUP(firmware->nvram, token[1]) < 0) + goto cleanup; + + ret = 0; + cleanup: + virStringFreeList(token); + return ret; +} + + +int +virFirmwareParseList(const char *list, + virFirmwarePtr **firmwares, + size_t *nfirmwares) +{ + int ret = -1; + char **token; + size_t i, j; + + if (!(token = virStringSplit(list, ":", 0))) + goto cleanup; + + for (i = 0; token[i]; i += 2) { + if (!token[i] || !token[i + 1] || + STREQ(token[i], "") || STREQ(token[i + 1], "")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid --with-loader-nvram list: %s"), + list); + goto cleanup; + } + } + + if (i) { + if (VIR_ALLOC_N(*firmwares, i / 2) < 0) + goto cleanup; + *nfirmwares = i / 2; + + for (j = 0; j < i / 2; j++) { + virFirmwarePtr *fws = *firmwares; + + if (VIR_ALLOC(fws[j]) < 0) + goto cleanup; + if (VIR_STRDUP(fws[j]->name, token[2 * j]) < 0 || + VIR_STRDUP(fws[j]->nvram, token[2 * j + 1]) < 0) + goto cleanup; + } + } + + ret = 0; + cleanup: + virStringFreeList(token); + return ret; +} diff --git a/src/util/virfirmware.h b/src/util/virfirmware.h new file mode 100644 index 0000000..682a865 --- /dev/null +++ b/src/util/virfirmware.h @@ -0,0 +1,51 @@ +/* + * virfirmware.h: Declaration of firmware object and supporting functions + * + * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Jim Fehlig <jfehlig@suse.com> + */ + +#ifndef __VIR_FIRMWARE_H__ +# define __VIR_FIRMWARE_H__ + +# include "internal.h" + +typedef struct _virFirmware virFirmware; +typedef virFirmware *virFirmwarePtr; + +struct _virFirmware { + char *name; + char *nvram; +}; + + +void +virFirmwareFreeList(virFirmwarePtr *firmwares, size_t nfirmwares); + +int +virFirmwareParse(const char *str, virFirmwarePtr firmware) + ATTRIBUTE_NONNULL(2); + +int +virFirmwareParseList(const char *list, + virFirmwarePtr **firmwares, + size_t *nfirmwares) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + + +#endif /* __VIR_FIRMWARE_H__ */ diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index e1d0671..83ce0e5 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -128,7 +128,8 @@ fillQemuCaps(virDomainCapsPtr domCaps, goto cleanup; if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, - cfg->loader, cfg->nloader) < 0) + cfg->firmwares, + cfg->nfirmwares) < 0) goto cleanup; /* The function above tries to query host's KVM & VFIO capabilities by -- 2.1.4

Prefer firmwares specified via --with-loader-nvram configure option. If none are specified, use the Xen-provided default firmwares found in LIBXL_FIRMWARE_DIR. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V3: - Always include hvmloader in cfg->firmwares src/libxl/libxl_conf.c | 28 ++++++++++++++++++++++++++++ src/libxl/libxl_conf.h | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a64b4c1..c6a23c2 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -104,6 +104,7 @@ libxlDriverConfigDispose(void *obj) VIR_FREE(cfg->saveDir); VIR_FREE(cfg->autoDumpDir); VIR_FREE(cfg->lockManagerName); + virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares); } @@ -1777,6 +1778,33 @@ libxlDriverConfigNew(void) goto error; } +#ifdef DEFAULT_LOADER_NVRAM + if (virFirmwareParseList(DEFAULT_LOADER_NVRAM, + &cfg->firmwares, + &cfg->nfirmwares) < 0) + goto error; + +#else + if (VIR_ALLOC_N(cfg->firmwares, 1) < 0) + goto error; + cfg->nfirmwares = 1; + if (VIR_ALLOC(cfg->firmwares[0]) < 0) + goto error; + if (VIR_STRDUP(cfg->firmwares[0]->name, + LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0) + goto error; +#endif + + /* Always add hvmloader to firmwares */ + if (VIR_REALLOC_N(cfg->firmwares, cfg->nfirmwares + 1) < 0) + goto error; + cfg->nfirmwares++; + if (VIR_ALLOC(cfg->firmwares[cfg->nfirmwares - 1]) < 0) + goto error; + if (VIR_STRDUP(cfg->firmwares[cfg->nfirmwares - 1]->name, + LIBXL_FIRMWARE_DIR "/hvmloader") < 0) + goto error; + return cfg; error: diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index c5b9429..e55717a 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -39,6 +39,7 @@ # include "virchrdev.h" # include "virhostdev.h" # include "locking/lock_manager.h" +# include "virfirmware.h" # define LIBXL_DRIVER_NAME "xenlight" # define LIBXL_VNC_PORT_MIN 5900 @@ -107,6 +108,9 @@ struct _libxlDriverConfig { char *libDir; char *saveDir; char *autoDumpDir; + + virFirmwarePtr *firmwares; + size_t nfirmwares; }; -- 2.1.4

Move capabilities code out of libxl_conf.{ch} and into new libxl_capabilities.{ch} files. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- po/POTFILES.in | 1 + src/Makefile.am | 9 +- src/libxl/libxl_capabilities.c | 458 +++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 50 +++++ src/libxl/libxl_conf.c | 419 ------------------------------------- src/libxl/libxl_conf.h | 18 +- src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 1 + 8 files changed, 517 insertions(+), 440 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index d6e79a8..822cfbc 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -75,6 +75,7 @@ src/libvirt-secret.c src/libvirt-storage.c src/libvirt-stream.c src/libvirt.c +src/libxl/libxl_capabilities.c src/libxl/libxl_conf.c src/libxl/libxl_domain.c src/libxl/libxl_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index d0782f2..7004d14 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -828,10 +828,11 @@ XENAPI_DRIVER_SOURCES = \ xenapi/xenapi_driver_private.h \ xenapi/xenapi_utils.c xenapi/xenapi_utils.h -LIBXL_DRIVER_SOURCES = \ - libxl/libxl_conf.c libxl/libxl_conf.h \ - libxl/libxl_domain.c libxl/libxl_domain.h \ - libxl/libxl_driver.c libxl/libxl_driver.h \ +LIBXL_DRIVER_SOURCES = \ + libxl/libxl_conf.c libxl/libxl_conf.h \ + libxl/libxl_capabilities.c libxl/libxl_capabilities.h \ + libxl/libxl_domain.c libxl/libxl_domain.h \ + libxl/libxl_driver.c libxl/libxl_driver.h \ libxl/libxl_migration.c libxl/libxl_migration.h UML_DRIVER_SOURCES = \ diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c new file mode 100644 index 0000000..aef2c2d --- /dev/null +++ b/src/libxl/libxl_capabilities.c @@ -0,0 +1,458 @@ +/* + * libxl_capabilities.c: libxl capabilities generation + * + * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Jim Fehlig <jfehlig@suse.com> + */ + +#include <config.h> + +#include <libxl.h> +#include <regex.h> + +#include "internal.h" +#include "virlog.h" +#include "virerror.h" +#include "virfile.h" +#include "viralloc.h" +#include "domain_conf.h" +#include "capabilities.h" +#include "vircommand.h" +#include "libxl_capabilities.h" + + +#define VIR_FROM_THIS VIR_FROM_LIBXL + +VIR_LOG_INIT("libxl.libxl_capabilities"); + +/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */ +#define LIBXL_X86_FEATURE_PAE_MASK 0x40 + + +struct guest_arch { + virArch arch; + int bits; + int hvm; + int pae; + int nonpae; + int ia64_be; +}; + +#define XEN_CAP_REGEX "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?" + + +static int +libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps) +{ + libxl_physinfo phy_info; + int host_pae; + + if (libxl_get_physinfo(ctx, &phy_info) != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get node physical info from libxenlight")); + return -1; + } + + /* hw_caps is an array of 32-bit words whose meaning is listed in + * xen-unstable.hg/xen/include/asm-x86/cpufeature.h. Each feature + * is defined in the form X*32+Y, corresponding to the Y'th bit in + * the X'th 32-bit word of hw_cap. + */ + host_pae = phy_info.hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK; + if (host_pae && + virCapabilitiesAddHostFeature(caps, "pae") < 0) + return -1; + + if (virCapabilitiesSetNetPrefix(caps, LIBXL_GENERATED_PREFIX_XEN) < 0) + return -1; + + return 0; +} + +static int +libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps) +{ + libxl_numainfo *numa_info = NULL; + libxl_cputopology *cpu_topo = NULL; + int nr_nodes = 0, nr_cpus = 0; + virCapsHostNUMACellCPUPtr *cpus = NULL; + int *nr_cpus_node = NULL; + size_t i; + int ret = -1; + + /* Let's try to fetch all the topology information */ + numa_info = libxl_get_numainfo(ctx, &nr_nodes); + if (numa_info == NULL || nr_nodes == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("libxl_get_numainfo failed")); + goto cleanup; + } else { + cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus); + if (cpu_topo == NULL || nr_cpus == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("libxl_get_cpu_topology failed")); + goto cleanup; + } + } + + if (VIR_ALLOC_N(cpus, nr_nodes) < 0) + goto cleanup; + + if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0) + goto cleanup; + + /* For each node, prepare a list of CPUs belonging to that node */ + for (i = 0; i < nr_cpus; i++) { + int node = cpu_topo[i].node; + + if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) + continue; + + nr_cpus_node[node]++; + + if (nr_cpus_node[node] == 1) { + if (VIR_ALLOC(cpus[node]) < 0) + goto cleanup; + } else { + if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0) + goto cleanup; + } + + /* Mapping between what libxl tells and what libvirt wants */ + cpus[node][nr_cpus_node[node]-1].id = i; + cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket; + cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core; + /* Allocate the siblings maps. We will be filling them later */ + cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus); + if (!cpus[node][nr_cpus_node[node]-1].siblings) { + virReportOOMError(); + goto cleanup; + } + } + + /* Let's now populate the siblings bitmaps */ + for (i = 0; i < nr_cpus; i++) { + int node = cpu_topo[i].node; + size_t j; + + if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) + continue; + + for (j = 0; j < nr_cpus_node[node]; j++) { + if (cpus[node][j].socket_id == cpu_topo[i].socket && + cpus[node][j].core_id == cpu_topo[i].core) + ignore_value(virBitmapSetBit(cpus[node][j].siblings, i)); + } + } + + for (i = 0; i < nr_nodes; i++) { + if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY) + continue; + + if (virCapabilitiesAddHostNUMACell(caps, i, + numa_info[i].size / 1024, + nr_cpus_node[i], cpus[i], + 0, NULL, + 0, NULL) < 0) { + virCapabilitiesClearHostNUMACellCPUTopology(cpus[i], + nr_cpus_node[i]); + goto cleanup; + } + + /* This is safe, as the CPU list is now stored in the NUMA cell */ + cpus[i] = NULL; + } + + ret = 0; + + cleanup: + if (ret != 0) { + for (i = 0; cpus && i < nr_nodes; i++) + VIR_FREE(cpus[i]); + virCapabilitiesFreeNUMAInfo(caps); + } + + VIR_FREE(cpus); + VIR_FREE(nr_cpus_node); + libxl_cputopology_list_free(cpu_topo, nr_cpus); + libxl_numainfo_list_free(numa_info, nr_nodes); + + return ret; +} + +static int +libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) +{ + const libxl_version_info *ver_info; + int err; + regex_t regex; + char *str, *token; + regmatch_t subs[4]; + char *saveptr = NULL; + size_t i; + + struct guest_arch guest_archs[32]; + int nr_guest_archs = 0; + + memset(guest_archs, 0, sizeof(guest_archs)); + + if ((ver_info = libxl_get_version_info(ctx)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get version info from libxenlight")); + return -1; + } + + if (!ver_info->capabilities) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to get capabilities from libxenlight")); + return -1; + } + + err = regcomp(®ex, XEN_CAP_REGEX, REG_EXTENDED); + if (err != 0) { + char error[100]; + regerror(err, ®ex, error, sizeof(error)); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to compile regex %s"), error); + return -1; + } + + /* Format of capabilities string is documented in the code in + * xen-unstable.hg/xen/arch/.../setup.c. + * + * It is a space-separated list of supported guest architectures. + * + * For x86: + * TYP-VER-ARCH[p] + * ^ ^ ^ ^ + * | | | +-- PAE supported + * | | +------- x86_32 or x86_64 + * | +----------- the version of Xen, eg. "3.0" + * +--------------- "xen" or "hvm" for para or full virt respectively + * + * For IA64: + * TYP-VER-ARCH[be] + * ^ ^ ^ ^ + * | | | +-- Big-endian supported + * | | +------- always "ia64" + * | +----------- the version of Xen, eg. "3.0" + * +--------------- "xen" or "hvm" for para or full virt respectively + */ + + /* Split capabilities string into tokens. strtok_r is OK here because + * we "own" the buffer. Parse out the features from each token. + */ + for (str = ver_info->capabilities, nr_guest_archs = 0; + nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0]) + && (token = strtok_r(str, " ", &saveptr)) != NULL; + str = NULL) { + if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]), + subs, 0) == 0) { + int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); + virArch arch; + int pae = 0, nonpae = 0, ia64_be = 0; + + if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { + arch = VIR_ARCH_I686; + if (subs[3].rm_so != -1 && + STRPREFIX(&token[subs[3].rm_so], "p")) + pae = 1; + else + nonpae = 1; + } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { + arch = VIR_ARCH_X86_64; + } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { + arch = VIR_ARCH_ITANIUM; + if (subs[3].rm_so != -1 && + STRPREFIX(&token[subs[3].rm_so], "be")) + ia64_be = 1; + } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { + arch = VIR_ARCH_PPC64; + } else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) { + arch = VIR_ARCH_ARMV7L; + } else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) { + arch = VIR_ARCH_AARCH64; + } else { + continue; + } + + /* Search for existing matching (model,hvm) tuple */ + for (i = 0; i < nr_guest_archs; i++) { + if ((guest_archs[i].arch == arch) && + guest_archs[i].hvm == hvm) + break; + } + + /* Too many arch flavours - highly unlikely ! */ + if (i >= ARRAY_CARDINALITY(guest_archs)) + continue; + /* Didn't find a match, so create a new one */ + if (i == nr_guest_archs) + nr_guest_archs++; + + guest_archs[i].arch = arch; + guest_archs[i].hvm = hvm; + + /* Careful not to overwrite a previous positive + setting with a negative one here - some archs + can do both pae & non-pae, but Xen reports + separately capabilities so we're merging archs */ + if (pae) + guest_archs[i].pae = pae; + if (nonpae) + guest_archs[i].nonpae = nonpae; + if (ia64_be) + guest_archs[i].ia64_be = ia64_be; + } + } + regfree(®ex); + + for (i = 0; i < nr_guest_archs; ++i) { + virCapsGuestPtr guest; + char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; + virCapsGuestMachinePtr *machines; + + if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL) + return -1; + + if ((guest = virCapabilitiesAddGuest(caps, + guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM : VIR_DOMAIN_OSTYPE_XEN, + guest_archs[i].arch, + LIBXL_EXECBIN_DIR "/qemu-system-i386", + (guest_archs[i].hvm ? + LIBXL_FIRMWARE_DIR "/hvmloader" : + NULL), + 1, + machines)) == NULL) { + virCapabilitiesFreeMachines(machines, 1); + return -1; + } + machines = NULL; + + if (virCapabilitiesAddGuestDomain(guest, + VIR_DOMAIN_VIRT_XEN, + NULL, + NULL, + 0, + NULL) == NULL) + return -1; + + if (guest_archs[i].pae && + virCapabilitiesAddGuestFeature(guest, + "pae", + 1, + 0) == NULL) + return -1; + + if (guest_archs[i].nonpae && + virCapabilitiesAddGuestFeature(guest, + "nonpae", + 1, + 0) == NULL) + return -1; + + if (guest_archs[i].ia64_be && + virCapabilitiesAddGuestFeature(guest, + "ia64_be", + 1, + 0) == NULL) + return -1; + + if (guest_archs[i].hvm) { + if (virCapabilitiesAddGuestFeature(guest, + "acpi", + 1, + 1) == NULL) + return -1; + + if (virCapabilitiesAddGuestFeature(guest, "apic", + 1, + 0) == NULL) + return -1; + + if (virCapabilitiesAddGuestFeature(guest, + "hap", + 1, + 1) == NULL) + return -1; + } + } + + return 0; +} + +virCapsPtr +libxlMakeCapabilities(libxl_ctx *ctx) +{ + virCapsPtr caps; + +#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME + if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) +#else + if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL) +#endif + return NULL; + + if (libxlCapsInitHost(ctx, caps) < 0) + goto error; + + if (libxlCapsInitNuma(ctx, caps) < 0) + goto error; + + if (libxlCapsInitGuests(ctx, caps) < 0) + goto error; + + return caps; + + error: + virObjectUnref(caps); + return NULL; +} + +#define LIBXL_QEMU_DM_STR "Options specific to the Xen version:" + +int +libxlDomainGetEmulatorType(const virDomainDef *def) +{ + int ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; + virCommandPtr cmd = NULL; + char *output = NULL; + + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (def->emulator) { + if (!virFileExists(def->emulator)) + goto cleanup; + + cmd = virCommandNew(def->emulator); + + virCommandAddArgList(cmd, "-help", NULL); + virCommandSetOutputBuffer(cmd, &output); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + if (strstr(output, LIBXL_QEMU_DM_STR)) + ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; + } + } + + cleanup: + VIR_FREE(output); + virCommandFree(cmd); + return ret; +} diff --git a/src/libxl/libxl_capabilities.h b/src/libxl/libxl_capabilities.h new file mode 100644 index 0000000..df1c327 --- /dev/null +++ b/src/libxl/libxl_capabilities.h @@ -0,0 +1,50 @@ +/* + * libxl_capabilities.h: libxl capabilities generation + * + * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Jim Fehlig <jfehlig@suse.com> + */ + +#ifndef LIBXL_CAPABILITIES_H +# define LIBXL_CAPABILITIES_H + +# include <libxl.h> + +# include "virobject.h" +# include "capabilities.h" + + +# ifndef LIBXL_FIRMWARE_DIR +# define LIBXL_FIRMWARE_DIR "/usr/lib/xen/boot" +# endif +# ifndef LIBXL_EXECBIN_DIR +# define LIBXL_EXECBIN_DIR "/usr/lib/xen/bin" +# endif + +/* Used for prefix of ifname of any network name generated dynamically + * by libvirt for Xen, and cannot be used for a persistent network name. */ +# define LIBXL_GENERATED_PREFIX_XEN "vif" + + +virCapsPtr +libxlMakeCapabilities(libxl_ctx *ctx); + +int +libxlDomainGetEmulatorType(const virDomainDef *def); + +#endif /* LIBXL_CAPABILITIES_H */ diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index c6a23c2..96f9635 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -40,7 +40,6 @@ #include "virstring.h" #include "viralloc.h" #include "viruuid.h" -#include "capabilities.h" #include "vircommand.h" #include "libxl_domain.h" #include "libxl_conf.h" @@ -53,21 +52,6 @@ VIR_LOG_INIT("libxl.libxl_conf"); -/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */ -#define LIBXL_X86_FEATURE_PAE_MASK 0x40 - - -struct guest_arch { - virArch arch; - int bits; - int hvm; - int pae; - int nonpae; - int ia64_be; -}; - -#define XEN_CAP_REGEX "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?" - static virClassPtr libxlDriverConfigClass; static void libxlDriverConfigDispose(void *obj); @@ -164,346 +148,6 @@ libxlActionFromVirLifecycleCrash(virDomainLifecycleCrashAction action) static int -libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps) -{ - libxl_physinfo phy_info; - int host_pae; - - if (libxl_get_physinfo(ctx, &phy_info) != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Failed to get node physical info from libxenlight")); - return -1; - } - - /* hw_caps is an array of 32-bit words whose meaning is listed in - * xen-unstable.hg/xen/include/asm-x86/cpufeature.h. Each feature - * is defined in the form X*32+Y, corresponding to the Y'th bit in - * the X'th 32-bit word of hw_cap. - */ - host_pae = phy_info.hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK; - if (host_pae && - virCapabilitiesAddHostFeature(caps, "pae") < 0) - return -1; - - if (virCapabilitiesSetNetPrefix(caps, LIBXL_GENERATED_PREFIX_XEN) < 0) - return -1; - - return 0; -} - -static int -libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps) -{ - libxl_numainfo *numa_info = NULL; - libxl_cputopology *cpu_topo = NULL; - int nr_nodes = 0, nr_cpus = 0; - virCapsHostNUMACellCPUPtr *cpus = NULL; - int *nr_cpus_node = NULL; - size_t i; - int ret = -1; - - /* Let's try to fetch all the topology information */ - numa_info = libxl_get_numainfo(ctx, &nr_nodes); - if (numa_info == NULL || nr_nodes == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("libxl_get_numainfo failed")); - goto cleanup; - } else { - cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus); - if (cpu_topo == NULL || nr_cpus == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("libxl_get_cpu_topology failed")); - goto cleanup; - } - } - - if (VIR_ALLOC_N(cpus, nr_nodes) < 0) - goto cleanup; - - if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0) - goto cleanup; - - /* For each node, prepare a list of CPUs belonging to that node */ - for (i = 0; i < nr_cpus; i++) { - int node = cpu_topo[i].node; - - if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) - continue; - - nr_cpus_node[node]++; - - if (nr_cpus_node[node] == 1) { - if (VIR_ALLOC(cpus[node]) < 0) - goto cleanup; - } else { - if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0) - goto cleanup; - } - - /* Mapping between what libxl tells and what libvirt wants */ - cpus[node][nr_cpus_node[node]-1].id = i; - cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket; - cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core; - /* Allocate the siblings maps. We will be filling them later */ - cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus); - if (!cpus[node][nr_cpus_node[node]-1].siblings) { - virReportOOMError(); - goto cleanup; - } - } - - /* Let's now populate the siblings bitmaps */ - for (i = 0; i < nr_cpus; i++) { - int node = cpu_topo[i].node; - size_t j; - - if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) - continue; - - for (j = 0; j < nr_cpus_node[node]; j++) { - if (cpus[node][j].socket_id == cpu_topo[i].socket && - cpus[node][j].core_id == cpu_topo[i].core) - ignore_value(virBitmapSetBit(cpus[node][j].siblings, i)); - } - } - - for (i = 0; i < nr_nodes; i++) { - if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY) - continue; - - if (virCapabilitiesAddHostNUMACell(caps, i, - numa_info[i].size / 1024, - nr_cpus_node[i], cpus[i], - 0, NULL, - 0, NULL) < 0) { - virCapabilitiesClearHostNUMACellCPUTopology(cpus[i], - nr_cpus_node[i]); - goto cleanup; - } - - /* This is safe, as the CPU list is now stored in the NUMA cell */ - cpus[i] = NULL; - } - - ret = 0; - - cleanup: - if (ret != 0) { - for (i = 0; cpus && i < nr_nodes; i++) - VIR_FREE(cpus[i]); - virCapabilitiesFreeNUMAInfo(caps); - } - - VIR_FREE(cpus); - VIR_FREE(nr_cpus_node); - libxl_cputopology_list_free(cpu_topo, nr_cpus); - libxl_numainfo_list_free(numa_info, nr_nodes); - - return ret; -} - -static int -libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) -{ - const libxl_version_info *ver_info; - int err; - regex_t regex; - char *str, *token; - regmatch_t subs[4]; - char *saveptr = NULL; - size_t i; - - struct guest_arch guest_archs[32]; - int nr_guest_archs = 0; - - memset(guest_archs, 0, sizeof(guest_archs)); - - if ((ver_info = libxl_get_version_info(ctx)) == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Failed to get version info from libxenlight")); - return -1; - } - - if (!ver_info->capabilities) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Failed to get capabilities from libxenlight")); - return -1; - } - - err = regcomp(®ex, XEN_CAP_REGEX, REG_EXTENDED); - if (err != 0) { - char error[100]; - regerror(err, ®ex, error, sizeof(error)); - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to compile regex %s"), error); - return -1; - } - - /* Format of capabilities string is documented in the code in - * xen-unstable.hg/xen/arch/.../setup.c. - * - * It is a space-separated list of supported guest architectures. - * - * For x86: - * TYP-VER-ARCH[p] - * ^ ^ ^ ^ - * | | | +-- PAE supported - * | | +------- x86_32 or x86_64 - * | +----------- the version of Xen, eg. "3.0" - * +--------------- "xen" or "hvm" for para or full virt respectively - * - * For IA64: - * TYP-VER-ARCH[be] - * ^ ^ ^ ^ - * | | | +-- Big-endian supported - * | | +------- always "ia64" - * | +----------- the version of Xen, eg. "3.0" - * +--------------- "xen" or "hvm" for para or full virt respectively - */ - - /* Split capabilities string into tokens. strtok_r is OK here because - * we "own" the buffer. Parse out the features from each token. - */ - for (str = ver_info->capabilities, nr_guest_archs = 0; - nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0]) - && (token = strtok_r(str, " ", &saveptr)) != NULL; - str = NULL) { - if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]), - subs, 0) == 0) { - int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); - virArch arch; - int pae = 0, nonpae = 0, ia64_be = 0; - - if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { - arch = VIR_ARCH_I686; - if (subs[3].rm_so != -1 && - STRPREFIX(&token[subs[3].rm_so], "p")) - pae = 1; - else - nonpae = 1; - } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { - arch = VIR_ARCH_X86_64; - } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { - arch = VIR_ARCH_ITANIUM; - if (subs[3].rm_so != -1 && - STRPREFIX(&token[subs[3].rm_so], "be")) - ia64_be = 1; - } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { - arch = VIR_ARCH_PPC64; - } else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) { - arch = VIR_ARCH_ARMV7L; - } else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) { - arch = VIR_ARCH_AARCH64; - } else { - continue; - } - - /* Search for existing matching (model,hvm) tuple */ - for (i = 0; i < nr_guest_archs; i++) { - if ((guest_archs[i].arch == arch) && - guest_archs[i].hvm == hvm) - break; - } - - /* Too many arch flavours - highly unlikely ! */ - if (i >= ARRAY_CARDINALITY(guest_archs)) - continue; - /* Didn't find a match, so create a new one */ - if (i == nr_guest_archs) - nr_guest_archs++; - - guest_archs[i].arch = arch; - guest_archs[i].hvm = hvm; - - /* Careful not to overwrite a previous positive - setting with a negative one here - some archs - can do both pae & non-pae, but Xen reports - separately capabilities so we're merging archs */ - if (pae) - guest_archs[i].pae = pae; - if (nonpae) - guest_archs[i].nonpae = nonpae; - if (ia64_be) - guest_archs[i].ia64_be = ia64_be; - } - } - regfree(®ex); - - for (i = 0; i < nr_guest_archs; ++i) { - virCapsGuestPtr guest; - char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; - virCapsGuestMachinePtr *machines; - - if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL) - return -1; - - if ((guest = virCapabilitiesAddGuest(caps, - guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM : VIR_DOMAIN_OSTYPE_XEN, - guest_archs[i].arch, - LIBXL_EXECBIN_DIR "/qemu-system-i386", - (guest_archs[i].hvm ? - LIBXL_FIRMWARE_DIR "/hvmloader" : - NULL), - 1, - machines)) == NULL) { - virCapabilitiesFreeMachines(machines, 1); - return -1; - } - machines = NULL; - - if (virCapabilitiesAddGuestDomain(guest, - VIR_DOMAIN_VIRT_XEN, - NULL, - NULL, - 0, - NULL) == NULL) - return -1; - - if (guest_archs[i].pae && - virCapabilitiesAddGuestFeature(guest, - "pae", - 1, - 0) == NULL) - return -1; - - if (guest_archs[i].nonpae && - virCapabilitiesAddGuestFeature(guest, - "nonpae", - 1, - 0) == NULL) - return -1; - - if (guest_archs[i].ia64_be && - virCapabilitiesAddGuestFeature(guest, - "ia64_be", - 1, - 0) == NULL) - return -1; - - if (guest_archs[i].hvm) { - if (virCapabilitiesAddGuestFeature(guest, - "acpi", - 1, - 1) == NULL) - return -1; - - if (virCapabilitiesAddGuestFeature(guest, "apic", - 1, - 0) == NULL) - return -1; - - if (virCapabilitiesAddGuestFeature(guest, - "hap", - 1, - 1) == NULL) - return -1; - } - } - - return 0; -} - -static int libxlMakeDomCreateInfo(libxl_ctx *ctx, virDomainDefPtr def, libxl_domain_create_info *c_info) @@ -905,41 +549,6 @@ libxlDiskSetDiscard(libxl_device_disk *x_disk, int discard) #endif } - -#define LIBXL_QEMU_DM_STR "Options specific to the Xen version:" - -int -libxlDomainGetEmulatorType(const virDomainDef *def) -{ - int ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; - virCommandPtr cmd = NULL; - char *output = NULL; - - if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { - if (def->emulator) { - if (!virFileExists(def->emulator)) - goto cleanup; - - cmd = virCommandNew(def->emulator); - - virCommandAddArgList(cmd, "-help", NULL); - virCommandSetOutputBuffer(cmd, &output); - - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; - - if (strstr(output, LIBXL_QEMU_DM_STR)) - ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; - } - } - - cleanup: - VIR_FREE(output); - virCommandFree(cmd); - return ret; -} - - static char * libxlMakeNetworkDiskSrcStr(virStorageSourcePtr src, const char *username, @@ -2066,34 +1675,6 @@ libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) return ret; } -virCapsPtr -libxlMakeCapabilities(libxl_ctx *ctx) -{ - virCapsPtr caps; - -#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME - if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) -#else - if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL) -#endif - return NULL; - - if (libxlCapsInitHost(ctx, caps) < 0) - goto error; - - if (libxlCapsInitNuma(ctx, caps) < 0) - goto error; - - if (libxlCapsInitGuests(ctx, caps) < 0) - goto error; - - return caps; - - error: - virObjectUnref(caps); - return NULL; -} - int libxlBuildDomainConfig(virPortAllocatorPtr graphicsports, virDomainDefPtr def, diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index e55717a..6547056 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -40,6 +40,7 @@ # include "virhostdev.h" # include "locking/lock_manager.h" # include "virfirmware.h" +# include "libxl_capabilities.h" # define LIBXL_DRIVER_NAME "xenlight" # define LIBXL_VNC_PORT_MIN 5900 @@ -48,10 +49,6 @@ # define LIBXL_MIGRATION_PORT_MIN 49152 # define LIBXL_MIGRATION_PORT_MAX 49216 -/* Used for prefix of ifname of any network name generated dynamically - * by libvirt for Xen, and cannot be used for a persistent network name. */ -# define LIBXL_GENERATED_PREFIX_XEN "vif" - # define LIBXL_CONFIG_BASE_DIR SYSCONFDIR "/libvirt" # define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl" # define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart" @@ -62,13 +59,6 @@ # define LIBXL_DUMP_DIR LIBXL_LIB_DIR "/dump" # define LIBXL_BOOTLOADER_PATH "pygrub" -# ifndef LIBXL_FIRMWARE_DIR -# define LIBXL_FIRMWARE_DIR "/usr/lib/xen/boot" -# endif -# ifndef LIBXL_EXECBIN_DIR -# define LIBXL_EXECBIN_DIR "/usr/lib/xen/bin" -# endif - typedef struct _libxlDriverPrivate libxlDriverPrivate; typedef libxlDriverPrivate *libxlDriverPrivatePtr; @@ -181,12 +171,6 @@ libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, int libxlDriverConfigLoadFile(libxlDriverConfigPtr cfg, const char *filename); -virCapsPtr -libxlMakeCapabilities(libxl_ctx *ctx); - -int -libxlDomainGetEmulatorType(const virDomainDef *def); - int libxlMakeDisk(virDomainDiskDefPtr l_dev, libxl_device_disk *x_dev); int diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 4a21f68..223862a 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -26,6 +26,7 @@ #include <fcntl.h> #include "libxl_domain.h" +#include "libxl_capabilities.h" #include "viralloc.h" #include "viratomic.h" diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 2ab08ac..afc5ac3 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -45,6 +45,7 @@ #include "libxl_domain.h" #include "libxl_driver.h" #include "libxl_conf.h" +#include "libxl_capabilities.h" #include "libxl_migration.h" #include "xen_xm.h" #include "xen_sxpr.h" -- 2.1.4

Add domain capabilities for PV and HVM domains. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V3: - Change introduction of connectGetDomainCapabilities to 1.3.6 src/libxl/libxl_capabilities.c | 140 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 7 ++ src/libxl/libxl_driver.c | 74 +++++++++++++++ tests/Makefile.am | 5 ++ tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++++++++++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 ++++++++++++ tests/domaincapstest.c | 61 +++++++++++++ tests/testutilsxen.h | 1 + 8 files changed, 414 insertions(+) diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index aef2c2d..45f0988 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -30,8 +30,10 @@ #include "virerror.h" #include "virfile.h" #include "viralloc.h" +#include "virstring.h" #include "domain_conf.h" #include "capabilities.h" +#include "domain_capabilities.h" #include "vircommand.h" #include "libxl_capabilities.h" @@ -396,6 +398,109 @@ libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) return 0; } +static int +libxlMakeDomainOSCaps(const char *machine, + virDomainCapsOSPtr os, + virFirmwarePtr *firmwares, + size_t nfirmwares) +{ + virDomainCapsLoaderPtr capsLoader = &os->loader; + size_t i; + + os->supported = true; + + if (STREQ(machine, "xenpv")) + return 0; + + capsLoader->supported = true; + if (VIR_ALLOC_N(capsLoader->values.values, nfirmwares) < 0) + return -1; + + for (i = 0; i < nfirmwares; i++) { + if (VIR_STRDUP(capsLoader->values.values[capsLoader->values.nvalues], + firmwares[i]->name) < 0) + return -1; + capsLoader->values.nvalues++; + } + + VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->type, + VIR_DOMAIN_LOADER_TYPE_ROM, + VIR_DOMAIN_LOADER_TYPE_PFLASH); + VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->readonly, + VIR_TRISTATE_BOOL_YES); + + return 0; +} + +static int +libxlMakeDomainDeviceDiskCaps(virDomainCapsDeviceDiskPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->diskDevice, + VIR_DOMAIN_DISK_DEVICE_DISK, + VIR_DOMAIN_DISK_DEVICE_CDROM); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->bus, + VIR_DOMAIN_DISK_BUS_IDE, + VIR_DOMAIN_DISK_BUS_SCSI, + VIR_DOMAIN_DISK_BUS_XEN); + + return 0; +} + +static int +libxlMakeDomainDeviceGraphicsCaps(virDomainCapsDeviceGraphicsPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->type, + VIR_DOMAIN_GRAPHICS_TYPE_SDL, + VIR_DOMAIN_GRAPHICS_TYPE_VNC, + VIR_DOMAIN_GRAPHICS_TYPE_SPICE); + + return 0; +} + +static int +libxlMakeDomainDeviceVideoCaps(virDomainCapsDeviceVideoPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->modelType, + VIR_DOMAIN_VIDEO_TYPE_VGA, + VIR_DOMAIN_VIDEO_TYPE_CIRRUS, + VIR_DOMAIN_VIDEO_TYPE_XEN); + + return 0; +} + +static int +libxlMakeDomainDeviceHostdevCaps(virDomainCapsDeviceHostdevPtr dev) +{ + dev->supported = true; + /* VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES is for containers only */ + VIR_DOMAIN_CAPS_ENUM_SET(dev->mode, + VIR_DOMAIN_HOSTDEV_MODE_SUBSYS); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->startupPolicy, + VIR_DOMAIN_STARTUP_POLICY_DEFAULT, + VIR_DOMAIN_STARTUP_POLICY_MANDATORY, + VIR_DOMAIN_STARTUP_POLICY_REQUISITE, + VIR_DOMAIN_STARTUP_POLICY_OPTIONAL); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->subsysType, + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI); + + /* No virDomainHostdevCapsType for libxl */ + virDomainCapsEnumClear(&dev->capsType); + + virDomainCapsEnumClear(&dev->pciBackend); + VIR_DOMAIN_CAPS_ENUM_SET(dev->pciBackend, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN); + return 0; +} + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { @@ -424,6 +529,41 @@ libxlMakeCapabilities(libxl_ctx *ctx) return NULL; } +/* + * Currently Xen has no interface to report maxvcpus supported + * for the various domain types (PV, HVM, PVH). HVM_MAX_VCPUS + * is defined in $xensrc/xen/include/public/hvm/hvm_info_table.h + * PV has no equivalent and is relunctantly set here until Xen + * can report such capabilities. + */ +#define HVM_MAX_VCPUS 128 +#define PV_MAX_VCPUS 512 + +int +libxlMakeDomainCapabilities(virDomainCapsPtr domCaps, + virFirmwarePtr *firmwares, + size_t nfirmwares) +{ + virDomainCapsOSPtr os = &domCaps->os; + virDomainCapsDeviceDiskPtr disk = &domCaps->disk; + virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics; + virDomainCapsDeviceVideoPtr video = &domCaps->video; + virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; + + if (STREQ(domCaps->machine, "xenfv")) + domCaps->maxvcpus = HVM_MAX_VCPUS; + else + domCaps->maxvcpus = PV_MAX_VCPUS; + + if (libxlMakeDomainOSCaps(domCaps->machine, os, firmwares, nfirmwares) < 0 || + libxlMakeDomainDeviceDiskCaps(disk) < 0 || + libxlMakeDomainDeviceGraphicsCaps(graphics) < 0 || + libxlMakeDomainDeviceVideoCaps(video) < 0 || + libxlMakeDomainDeviceHostdevCaps(hostdev) < 0) + return -1; + return 0; +} + #define LIBXL_QEMU_DM_STR "Options specific to the Xen version:" int diff --git a/src/libxl/libxl_capabilities.h b/src/libxl/libxl_capabilities.h index df1c327..992b780 100644 --- a/src/libxl/libxl_capabilities.h +++ b/src/libxl/libxl_capabilities.h @@ -27,6 +27,8 @@ # include "virobject.h" # include "capabilities.h" +# include "domain_capabilities.h" +# include "virfirmware.h" # ifndef LIBXL_FIRMWARE_DIR @@ -45,6 +47,11 @@ virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx); int +libxlMakeDomainCapabilities(virDomainCapsPtr domCaps, + virFirmwarePtr *firmwares, + size_t nfirmwares); + +int libxlDomainGetEmulatorType(const virDomainDef *def); #endif /* LIBXL_CAPABILITIES_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index afc5ac3..c12c1cf 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -5562,6 +5562,79 @@ libxlDomainInterfaceAddresses(virDomainPtr dom, } +static char * +libxlConnectGetDomainCapabilities(virConnectPtr conn, + const char *emulatorbin, + const char *arch_str, + const char *machine, + const char *virttype_str, + unsigned int flags) +{ + libxlDriverPrivatePtr driver = conn->privateData; + libxlDriverConfigPtr cfg; + char *ret = NULL; + int virttype = VIR_DOMAIN_VIRT_XEN; + virDomainCapsPtr domCaps = NULL; + int arch = virArchFromHost(); /* virArch */ + + virCheckFlags(0, ret); + + if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0) + return ret; + + cfg = libxlDriverConfigGet(driver); + + if (virttype_str && + (virttype = virDomainVirtTypeFromString(virttype_str)) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown virttype: %s"), + virttype_str); + goto cleanup; + } + + if (virttype != VIR_DOMAIN_VIRT_XEN) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown virttype: %s"), + virttype_str); + goto cleanup; + } + + if (arch_str && (arch = virArchFromString(arch_str)) == VIR_ARCH_NONE) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown architecture: %s"), + arch_str); + goto cleanup; + } + + if (emulatorbin == NULL) + emulatorbin = "/usr/bin/qemu-system-x86_64"; + + if (machine) { + if (STRNEQ(machine, "xenpv") && STRNEQ(machine, "xenfv")) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Xen only supports 'xenpv' and 'xenfv' machines")); + goto cleanup; + } + } else { + machine = "xenpv"; + } + + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype))) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, cfg->firmwares, + cfg->nfirmwares) < 0) + goto cleanup; + + ret = virDomainCapsFormat(domCaps); + + cleanup: + virObjectUnref(domCaps); + virObjectUnref(cfg); + return ret; +} + + static virHypervisorDriver libxlHypervisorDriver = { .name = LIBXL_DRIVER_NAME, .connectOpen = libxlConnectOpen, /* 0.9.0 */ @@ -5663,6 +5736,7 @@ static virHypervisorDriver libxlHypervisorDriver = { .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */ .nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */ .domainInterfaceAddresses = libxlDomainInterfaceAddresses, /* 1.3.5 */ + .connectGetDomainCapabilities = libxlConnectGetDomainCapabilities, /* 1.3.6 */ }; static virConnectDriver libxlConnectDriver = { diff --git a/tests/Makefile.am b/tests/Makefile.am index 18ffab6..4a1e0f3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -930,6 +930,11 @@ domaincapstest_SOURCES += testutilsqemu.c testutilsqemu.h domaincapstest_LDADD += $(qemu_LDADDS) $(GNULIB_LIBS) endif WITH_QEMU +if WITH_LIBXL +domaincapstest_SOURCES += testutilsxen.c testutilsxen.h +domaincapstest_LDADD += ../src/libvirt_driver_libxl_impl.la +endif WITH_LIBXL + if WITH_LIBVIRTD libvirtdconftest_SOURCES = \ libvirtdconftest.c testutils.h testutils.c \ diff --git a/tests/domaincapsschemadata/libxl-xenfv.xml b/tests/domaincapsschemadata/libxl-xenfv.xml new file mode 100644 index 0000000..9436ef8 --- /dev/null +++ b/tests/domaincapsschemadata/libxl-xenfv.xml @@ -0,0 +1,68 @@ +<domainCapabilities> + <path>/usr/bin/qemu-system-x86_64</path> + <domain>xen</domain> + <machine>xenfv</machine> + <arch>x86_64</arch> + <vcpu max='128'/> + <os supported='yes'> + <loader supported='yes'> + <value>/usr/lib/xen/boot/hvmloader</value> + <value>/usr/lib/xen/boot/ovmf.bin</value> + <enum name='type'> + <value>rom</value> + <value>pflash</value> + </enum> + <enum name='readonly'> + <value>yes</value> + </enum> + </loader> + </os> + <devices> + <disk supported='yes'> + <enum name='diskDevice'> + <value>disk</value> + <value>cdrom</value> + </enum> + <enum name='bus'> + <value>ide</value> + <value>scsi</value> + <value>xen</value> + </enum> + </disk> + <graphics supported='yes'> + <enum name='type'> + <value>sdl</value> + <value>vnc</value> + <value>spice</value> + </enum> + </graphics> + <video supported='yes'> + <enum name='modelType'> + <value>vga</value> + <value>cirrus</value> + <value>xen</value> + </enum> + </video> + <hostdev supported='yes'> + <enum name='mode'> + <value>subsystem</value> + </enum> + <enum name='startupPolicy'> + <value>default</value> + <value>mandatory</value> + <value>requisite</value> + <value>optional</value> + </enum> + <enum name='subsysType'> + <value>pci</value> + </enum> + <enum name='capsType'/> + <enum name='pciBackend'> + <value>xen</value> + </enum> + </hostdev> + </devices> + <features> + <gic supported='no'/> + </features> +</domainCapabilities> diff --git a/tests/domaincapsschemadata/libxl-xenpv.xml b/tests/domaincapsschemadata/libxl-xenpv.xml new file mode 100644 index 0000000..ab00a28 --- /dev/null +++ b/tests/domaincapsschemadata/libxl-xenpv.xml @@ -0,0 +1,58 @@ +<domainCapabilities> + <path>/usr/bin/qemu-system-x86_64</path> + <domain>xen</domain> + <machine>xenpv</machine> + <arch>x86_64</arch> + <vcpu max='512'/> + <os supported='yes'> + <loader supported='no'/> + </os> + <devices> + <disk supported='yes'> + <enum name='diskDevice'> + <value>disk</value> + <value>cdrom</value> + </enum> + <enum name='bus'> + <value>ide</value> + <value>scsi</value> + <value>xen</value> + </enum> + </disk> + <graphics supported='yes'> + <enum name='type'> + <value>sdl</value> + <value>vnc</value> + <value>spice</value> + </enum> + </graphics> + <video supported='yes'> + <enum name='modelType'> + <value>vga</value> + <value>cirrus</value> + <value>xen</value> + </enum> + </video> + <hostdev supported='yes'> + <enum name='mode'> + <value>subsystem</value> + </enum> + <enum name='startupPolicy'> + <value>default</value> + <value>mandatory</value> + <value>requisite</value> + <value>optional</value> + </enum> + <enum name='subsysType'> + <value>pci</value> + </enum> + <enum name='capsType'/> + <enum name='pciBackend'> + <value>xen</value> + </enum> + </hostdev> + </devices> + <features> + <gic supported='no'/> + </features> +</domainCapabilities> diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 83ce0e5..9fb2c97 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -162,10 +162,41 @@ fillQemuCaps(virDomainCapsPtr domCaps, #endif /* WITH_QEMU */ +#ifdef WITH_LIBXL +# include "testutilsxen.h" + +static int +fillXenCaps(virDomainCapsPtr domCaps) +{ + virFirmwarePtr *firmwares; + int ret = -1; + + if (VIR_ALLOC_N(firmwares, 2) < 0) + return ret; + + if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0) + goto cleanup; + if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 || + VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virFirmwareFreeList(firmwares, 2); + return ret; +} +#endif /* WITH_LIBXL */ + + enum testCapsType { CAPS_NONE, CAPS_ALL, CAPS_QEMU, + CAPS_LIBXL, }; struct testData { @@ -213,6 +244,13 @@ test_virDomainCapsFormat(const void *opaque) goto cleanup; #endif break; + + case CAPS_LIBXL: +#if WITH_LIBXL + if (fillXenCaps(domCaps) < 0) + goto cleanup; +#endif + break; } if (!(domCapsXML = virDomainCapsFormat(domCaps))) @@ -280,6 +318,20 @@ mymain(void) VIR_FREE(name); \ } while (0) +#define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type) \ + do { \ + struct testData data = { \ + .name = Name, \ + .emulator = Emulator, \ + .machine = Machine, \ + .arch = Arch, \ + .type = Type, \ + .capsType = CAPS_LIBXL, \ + }; \ + if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ + ret = -1; \ + } while (0) + DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE); DO_TEST("full", "/bin/emulatorbin", "my-machine-type", @@ -313,6 +365,15 @@ mymain(void) #endif /* WITH_QEMU */ +#if WITH_LIBXL + + DO_TEST_LIBXL("libxl-xenpv", "/usr/bin/qemu-system-x86_64", + "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN); + DO_TEST_LIBXL("libxl-xenfv", "/usr/bin/qemu-system-x86_64", + "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN); + +#endif /* WITH_LIBXL */ + return ret; } diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index c78350d..8b997c3 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -2,6 +2,7 @@ # define _TESTUTILSXEN_H_ # include "capabilities.h" +# include "libxl/libxl_capabilities.h" virCapsPtr testXenCapsInit(void); -- 2.1.4

Jim Fehlig wrote:
Add domain capabilities for PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V3: - Change introduction of connectGetDomainCapabilities to 1.3.6
src/libxl/libxl_capabilities.c | 140 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 7 ++ src/libxl/libxl_driver.c | 74 +++++++++++++++ tests/Makefile.am | 5 ++ tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++++++++++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 ++++++++++++ tests/domaincapstest.c | 61 +++++++++++++ tests/testutilsxen.h | 1 + 8 files changed, 414 insertions(+)
...
--- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -162,10 +162,41 @@ fillQemuCaps(virDomainCapsPtr domCaps, #endif /* WITH_QEMU */
+#ifdef WITH_LIBXL +# include "testutilsxen.h" + +static int +fillXenCaps(virDomainCapsPtr domCaps) +{ + virFirmwarePtr *firmwares; + int ret = -1; + + if (VIR_ALLOC_N(firmwares, 2) < 0) + return ret; + + if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0) + goto cleanup; + if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 || + VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virFirmwareFreeList(firmwares, 2); + return ret; +} +#endif /* WITH_LIBXL */ + + enum testCapsType { CAPS_NONE, CAPS_ALL, CAPS_QEMU, + CAPS_LIBXL, };
struct testData { @@ -213,6 +244,13 @@ test_virDomainCapsFormat(const void *opaque) goto cleanup; #endif break; + + case CAPS_LIBXL: +#if WITH_LIBXL + if (fillXenCaps(domCaps) < 0) + goto cleanup; +#endif + break; }
if (!(domCapsXML = virDomainCapsFormat(domCaps))) @@ -280,6 +318,20 @@ mymain(void) VIR_FREE(name); \ } while (0)
+#define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type) \ + do { \ + struct testData data = { \ + .name = Name, \ + .emulator = Emulator, \ + .machine = Machine, \ + .arch = Arch, \ + .type = Type, \ + .capsType = CAPS_LIBXL, \ + }; \ + if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ + ret = -1; \ + } while (0) + DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE); DO_TEST("full", "/bin/emulatorbin", "my-machine-type", @@ -313,6 +365,15 @@ mymain(void)
#endif /* WITH_QEMU */
+#if WITH_LIBXL + + DO_TEST_LIBXL("libxl-xenpv", "/usr/bin/qemu-system-x86_64", + "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN); + DO_TEST_LIBXL("libxl-xenfv", "/usr/bin/qemu-system-x86_64", + "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN); + +#endif /* WITH_LIBXL */ + return ret; }
diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index c78350d..8b997c3 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -2,6 +2,7 @@ # define _TESTUTILSXEN_H_
# include "capabilities.h" +# include "libxl/libxl_capabilities.h"
virCapsPtr testXenCapsInit(void);
This breaks build without xl: gmake[2]: Entering directory '/usr/home/novel/code/libvirt/tests' CC vircapstest.o In file included from vircapstest.c:25: In file included from ./testutilsxen.h:5: ../src/libxl/libxl_capabilities.h:26:11: fatal error: 'libxl.h' file not found # include <libxl.h> ^ 1 error generated. Makefile:4935: recipe for target 'vircapstest.o' failed Probably it would be easier to just include "libxl/libxl_capabilities.h" in tests/domaincapstest.c directly? Something like this: diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 9fb2c97..b3ab662 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -163,7 +163,7 @@ fillQemuCaps(virDomainCapsPtr domCaps, #ifdef WITH_LIBXL -# include "testutilsxen.h" +# include "libxl/libxl_capabilities.h" static int fillXenCaps(virDomainCapsPtr domCaps) diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index 8b997c3..c78350d 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -2,7 +2,6 @@ # define _TESTUTILSXEN_H_ # include "capabilities.h" -# include "libxl/libxl_capabilities.h" virCapsPtr testXenCapsInit(void); Roman Bogorodskiy

Roman Bogorodskiy wrote:
Jim Fehlig wrote:
Add domain capabilities for PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V3: - Change introduction of connectGetDomainCapabilities to 1.3.6
src/libxl/libxl_capabilities.c | 140 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 7 ++ src/libxl/libxl_driver.c | 74 +++++++++++++++ tests/Makefile.am | 5 ++ tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++++++++++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 ++++++++++++ tests/domaincapstest.c | 61 +++++++++++++ tests/testutilsxen.h | 1 + 8 files changed, 414 insertions(+)
...
--- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -162,10 +162,41 @@ fillQemuCaps(virDomainCapsPtr domCaps, #endif /* WITH_QEMU */
+#ifdef WITH_LIBXL +# include "testutilsxen.h" + +static int +fillXenCaps(virDomainCapsPtr domCaps) +{ + virFirmwarePtr *firmwares; + int ret = -1; + + if (VIR_ALLOC_N(firmwares, 2) < 0) + return ret; + + if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0) + goto cleanup; + if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 || + VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virFirmwareFreeList(firmwares, 2); + return ret; +} +#endif /* WITH_LIBXL */ + + enum testCapsType { CAPS_NONE, CAPS_ALL, CAPS_QEMU, + CAPS_LIBXL, };
struct testData { @@ -213,6 +244,13 @@ test_virDomainCapsFormat(const void *opaque) goto cleanup; #endif break; + + case CAPS_LIBXL: +#if WITH_LIBXL + if (fillXenCaps(domCaps) < 0) + goto cleanup; +#endif + break; }
if (!(domCapsXML = virDomainCapsFormat(domCaps))) @@ -280,6 +318,20 @@ mymain(void) VIR_FREE(name); \ } while (0)
+#define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type) \ + do { \ + struct testData data = { \ + .name = Name, \ + .emulator = Emulator, \ + .machine = Machine, \ + .arch = Arch, \ + .type = Type, \ + .capsType = CAPS_LIBXL, \ + }; \ + if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ + ret = -1; \ + } while (0) + DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE); DO_TEST("full", "/bin/emulatorbin", "my-machine-type", @@ -313,6 +365,15 @@ mymain(void)
#endif /* WITH_QEMU */
+#if WITH_LIBXL + + DO_TEST_LIBXL("libxl-xenpv", "/usr/bin/qemu-system-x86_64", + "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN); + DO_TEST_LIBXL("libxl-xenfv", "/usr/bin/qemu-system-x86_64", + "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN); + +#endif /* WITH_LIBXL */ + return ret; }
diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index c78350d..8b997c3 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -2,6 +2,7 @@ # define _TESTUTILSXEN_H_
# include "capabilities.h" +# include "libxl/libxl_capabilities.h"
virCapsPtr testXenCapsInit(void);
This breaks build without xl:
gmake[2]: Entering directory '/usr/home/novel/code/libvirt/tests' CC vircapstest.o In file included from vircapstest.c:25: In file included from ./testutilsxen.h:5: ../src/libxl/libxl_capabilities.h:26:11: fatal error: 'libxl.h' file not found # include <libxl.h> ^ 1 error generated. Makefile:4935: recipe for target 'vircapstest.o' failed
Sorry. My pre-commit checklist needs to grow to include testing broader changes like this using '--without-xen --without-libxl'. Anyhow, it looks like Martin already pushed a fix for this (thanks Martin!). Regards, Jim

On Tue, Jun 14, 2016 at 09:06:51AM -0600, Jim Fehlig wrote:
Jim Fehlig wrote: Sorry. My pre-commit checklist needs to grow to include testing broader changes
Roman Bogorodskiy wrote: like this using '--without-xen --without-libxl'. Anyhow, it looks like Martin already pushed a fix for this (thanks Martin!).
You're welcome =) No problem, worry, we can't all check for everything. And this is not a surgery, we can (almost) always fix things. I would would speak differently if half of your patches wouldn't build but it's nowhere near that case ;) Have a nice day, Martin

Add support to xenconfig for conversion of xl.cfg(5) bios config to/from libvirt domXml <loader> config. SeaBIOS is the default for HVM guests using upstream QEMU. ROMBIOS is the default when using the old qemu-dm. This patch allows specifying OVMF as an alternate firmware. Example xl.cfg: bios = "ovmf" Example domXML: <os> ... <loader readonly='yes' type='pflash'>/usr/lib/xen/boot/ovmf.bin</loader> </os> Note that currently Xen does not support a separate nvram for non-volatile variables. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V3: - Rework test code to account for discovery of LIBXL_FIRMWARE_DIR at build time - Drop code that relies on Xen patches that are not yet committed to xen.git master src/Makefile.am | 2 +- src/xenconfig/xen_xl.c | 37 ++++++++++--- tests/testutils.c | 16 ++++++ tests/testutils.h | 2 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 +++++++++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 ++++++++++++++++++++ tests/xlconfigtest.c | 90 +++++++++++++++++++++++-------- 7 files changed, 202 insertions(+), 29 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7004d14..1aff57d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1151,7 +1151,7 @@ noinst_LTLIBRARIES += libvirt_xenconfig.la libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la libvirt_xenconfig_la_LIBADD = $(LIBXL_LIBS) libvirt_xenconfig_la_CFLAGS = \ - -I$(srcdir)/conf $(AM_CFLAGS) + -I$(srcdir)/conf -I$(srcdir)/libxl $(AM_CFLAGS) libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES) endif WITH_XENCONFIG diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 9b8306f..dc54a73 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -33,6 +33,7 @@ #include "virstring.h" #include "virstoragefile.h" #include "xen_xl.h" +#include "libxl_capabilities.h" #define VIR_FROM_THIS VIR_FROM_XENXL @@ -103,15 +104,31 @@ xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps) size_t i; if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + const char *bios; const char *boot; - for (i = 0; i < caps->nguests; i++) { - if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && - caps->guests[i]->arch.id == def->os.arch) { - if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, - caps->guests[i]->arch.defaultInfo.loader) < 0) - return -1; + if (xenConfigGetString(conf, "bios", &bios, NULL) < 0) + return -1; + + if (bios && STREQ(bios, "ovmf")) { + if (VIR_ALLOC(def->os.loader) < 0) + return -1; + + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH; + def->os.loader->readonly = VIR_TRISTATE_BOOL_YES; + + if (VIR_STRDUP(def->os.loader->path, + LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0) + return -1; + } else { + for (i = 0; i < caps->nguests; i++) { + if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && + caps->guests[i]->arch.id == def->os.arch) { + if (VIR_ALLOC(def->os.loader) < 0 || + VIR_STRDUP(def->os.loader->path, + caps->guests[i]->arch.defaultInfo.loader) < 0) + return -1; + } } } @@ -535,6 +552,12 @@ xenFormatXLOS(virConfPtr conf, virDomainDefPtr def) if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1; + if (def->os.loader && + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) { + if (xenConfigSetString(conf, "bios", "ovmf") < 0) + return -1; + } + #ifdef LIBXL_HAVE_BUILDINFO_KERNEL if (def->os.kernel && xenConfigSetString(conf, "kernel", def->os.kernel) < 0) diff --git a/tests/testutils.c b/tests/testutils.c index e2dd2fe..54adab2 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -718,6 +718,22 @@ virTestCompareToFile(const char *strcontent, return ret; } +/* + * @param strcontent: String input content + * @param strsrc: String source to compare strcontent against + */ +int +virTestCompareToString(const char *strcontent, + const char *strsrc) +{ + if (STRNEQ_NULLABLE(strcontent, strsrc)) { + virTestDifference(stderr, strcontent, strsrc); + return -1; + } + + return 0; +} + static void virTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED, virErrorPtr err ATTRIBUTE_UNUSED) diff --git a/tests/testutils.h b/tests/testutils.h index e3881e8..c7c641c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -75,6 +75,8 @@ int virTestDifferenceBin(FILE *stream, size_t length); int virTestCompareToFile(const char *strcontent, const char *filename); +int virTestCompareToString(const char *strcontent, + const char *strsrc); unsigned int virTestGetDebug(void); unsigned int virTestGetVerbose(void); diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.cfg b/tests/xlconfigdata/test-fullvirt-ovmf.cfg new file mode 100644 index 0000000..b08e7fd --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +builder = "hvm" +bios = "ovmf" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.xml b/tests/xlconfigdata/test-fullvirt-ovmf.xml new file mode 100644 index 0000000..ca902e6 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.xml @@ -0,0 +1,58 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader readonly='yes' type='pflash'>/LIBXL_FIRMWARE_DIR/ovmf.bin</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 62bb144..55c756c 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -43,12 +43,33 @@ static virCapsPtr caps; static virDomainXMLOptionPtr xmlopt; + +/* + * This function provides a mechanism to replace variables in test + * data files whose values are discovered at built time. + */ +static char * +testReplaceVarsXML(const char *xml) +{ + char *xmlcfgData; + char *replacedXML; + + if (virTestLoadFile(xml, &xmlcfgData) < 0) + return NULL; + + replacedXML = virStringReplace(xmlcfgData, "/LIBXL_FIRMWARE_DIR", + LIBXL_FIRMWARE_DIR); + + VIR_FREE(xmlcfgData); + return replacedXML; +} + /* * Parses domXML to virDomainDef object, which is then converted to xl.cfg(5) * config and compared with expected config. */ static int -testCompareParseXML(const char *xlcfg, const char *xml) +testCompareParseXML(const char *xlcfg, const char *xml, bool replaceVars) { char *gotxlcfgData = NULL; virConfPtr conf = NULL; @@ -56,6 +77,7 @@ testCompareParseXML(const char *xlcfg, const char *xml) int wrote = 4096; int ret = -1; virDomainDefPtr def = NULL; + char *replacedXML = NULL; if (VIR_ALLOC_N(gotxlcfgData, wrote) < 0) goto fail; @@ -63,9 +85,17 @@ testCompareParseXML(const char *xlcfg, const char *xml) conn = virGetConnect(); if (!conn) goto fail; - if (!(def = virDomainDefParseFile(xml, caps, xmlopt, - VIR_DOMAIN_XML_INACTIVE))) - goto fail; + if (replaceVars) { + if (!(replacedXML = testReplaceVarsXML(xml))) + goto fail; + if (!(def = virDomainDefParseString(replacedXML, caps, xmlopt, + VIR_DOMAIN_XML_INACTIVE))) + goto fail; + } else { + if (!(def = virDomainDefParseFile(xml, caps, xmlopt, + VIR_DOMAIN_XML_INACTIVE))) + goto fail; + } if (!virDomainDefCheckABIStability(def, def)) { fprintf(stderr, "ABI stability check failed on %s", xml); @@ -85,6 +115,7 @@ testCompareParseXML(const char *xlcfg, const char *xml) ret = 0; fail: + VIR_FREE(replacedXML); VIR_FREE(gotxlcfgData); if (conf) virConfFree(conf); @@ -99,7 +130,7 @@ testCompareParseXML(const char *xlcfg, const char *xml) * domXML and compared to expected XML. */ static int -testCompareFormatXML(const char *xlcfg, const char *xml) +testCompareFormatXML(const char *xlcfg, const char *xml, bool replaceVars) { char *xlcfgData = NULL; char *gotxml = NULL; @@ -107,6 +138,7 @@ testCompareFormatXML(const char *xlcfg, const char *xml) int ret = -1; virConnectPtr conn; virDomainDefPtr def = NULL; + char *replacedXML = NULL; conn = virGetConnect(); if (!conn) goto fail; @@ -124,14 +156,22 @@ testCompareFormatXML(const char *xlcfg, const char *xml) VIR_DOMAIN_XML_SECURE))) goto fail; - if (virTestCompareToFile(gotxml, xml) < 0) - goto fail; + if (replaceVars) { + if (!(replacedXML = testReplaceVarsXML(xml))) + goto fail; + if (virTestCompareToString(gotxml, replacedXML) < 0) + goto fail; + } else { + if (virTestCompareToFile(gotxml, xml) < 0) + goto fail; + } ret = 0; fail: if (conf) virConfFree(conf); + VIR_FREE(replacedXML); VIR_FREE(xlcfgData); VIR_FREE(gotxml); virDomainDefFree(def); @@ -144,6 +184,7 @@ testCompareFormatXML(const char *xlcfg, const char *xml) struct testInfo { const char *name; int mode; + bool replaceVars; }; static int @@ -161,9 +202,9 @@ testCompareHelper(const void *data) goto cleanup; if (info->mode == 0) - result = testCompareParseXML(cfg, xml); + result = testCompareParseXML(cfg, xml, info->replaceVars); else - result = testCompareFormatXML(cfg, xml); + result = testCompareFormatXML(cfg, xml, info->replaceVars); cleanup: VIR_FREE(xml); @@ -184,17 +225,17 @@ mymain(void) if (!(xmlopt = libxlCreateXMLConf())) return EXIT_FAILURE; -#define DO_TEST_PARSE(name) \ +#define DO_TEST_PARSE(name, replace) \ do { \ - struct testInfo info0 = { name, 0 }; \ + struct testInfo info0 = { name, 0, replace }; \ if (virTestRun("Xen XL-2-XML Parse " name, \ testCompareHelper, &info0) < 0) \ ret = -1; \ } while (0) -#define DO_TEST_FORMAT(name) \ +#define DO_TEST_FORMAT(name, replace) \ do { \ - struct testInfo info1 = { name, 1 }; \ + struct testInfo info1 = { name, 1, replace }; \ if (virTestRun("Xen XL-2-XML Format " name, \ testCompareHelper, &info1) < 0) \ ret = -1; \ @@ -202,22 +243,29 @@ mymain(void) #define DO_TEST(name) \ do { \ - DO_TEST_PARSE(name); \ - DO_TEST_FORMAT(name); \ + DO_TEST_PARSE(name, false); \ + DO_TEST_FORMAT(name, false); \ } while (0) +#define DO_TEST_REPLACE_VARS(name) \ + do { \ + DO_TEST_PARSE(name, true); \ + DO_TEST_FORMAT(name, true); \ + } while (0) + + DO_TEST_REPLACE_VARS("fullvirt-ovmf"); DO_TEST("paravirt-maxvcpus"); DO_TEST("new-disk"); - DO_TEST_FORMAT("disk-positional-parms-full"); - DO_TEST_FORMAT("disk-positional-parms-partial"); + DO_TEST_FORMAT("disk-positional-parms-full", false); + DO_TEST_FORMAT("disk-positional-parms-partial", false); DO_TEST("spice"); DO_TEST("spice-features"); DO_TEST("vif-rate"); DO_TEST("fullvirt-nohap"); DO_TEST("paravirt-cmdline"); - DO_TEST_FORMAT("paravirt-cmdline-extra-root"); - DO_TEST_FORMAT("paravirt-cmdline-bogus-extra-root"); + DO_TEST_FORMAT("paravirt-cmdline-extra-root", false); + DO_TEST_FORMAT("paravirt-cmdline-bogus-extra-root", false); DO_TEST("rbd-multihost-noauth"); #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST @@ -225,8 +273,8 @@ mymain(void) #endif #ifdef LIBXL_HAVE_BUILDINFO_KERNEL DO_TEST("fullvirt-direct-kernel-boot"); - DO_TEST_FORMAT("fullvirt-direct-kernel-boot-extra"); - DO_TEST_FORMAT("fullvirt-direct-kernel-boot-bogus-extra"); + DO_TEST_FORMAT("fullvirt-direct-kernel-boot-extra", false); + DO_TEST_FORMAT("fullvirt-direct-kernel-boot-bogus-extra", false); #endif DO_TEST("vif-typename"); -- 2.1.4

On 11.06.2016 00:34, Jim Fehlig wrote:
Add support to xenconfig for conversion of xl.cfg(5) bios config to/from libvirt domXml <loader> config. SeaBIOS is the default for HVM guests using upstream QEMU. ROMBIOS is the default when using the old qemu-dm. This patch allows specifying OVMF as an alternate firmware.
Example xl.cfg: bios = "ovmf"
Example domXML: <os> ... <loader readonly='yes' type='pflash'>/usr/lib/xen/boot/ovmf.bin</loader> </os>
Note that currently Xen does not support a separate nvram for non-volatile variables.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V3: - Rework test code to account for discovery of LIBXL_FIRMWARE_DIR at build time - Drop code that relies on Xen patches that are not yet committed to xen.git master
src/Makefile.am | 2 +- src/xenconfig/xen_xl.c | 37 ++++++++++--- tests/testutils.c | 16 ++++++ tests/testutils.h | 2 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 +++++++++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 ++++++++++++++++++++ tests/xlconfigtest.c | 90 +++++++++++++++++++++++-------- 7 files changed, 202 insertions(+), 29 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index 7004d14..1aff57d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1151,7 +1151,7 @@ noinst_LTLIBRARIES += libvirt_xenconfig.la libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la libvirt_xenconfig_la_LIBADD = $(LIBXL_LIBS) libvirt_xenconfig_la_CFLAGS = \ - -I$(srcdir)/conf $(AM_CFLAGS) + -I$(srcdir)/conf -I$(srcdir)/libxl $(AM_CFLAGS) libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES) endif WITH_XENCONFIG
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 9b8306f..dc54a73 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -33,6 +33,7 @@ #include "virstring.h" #include "virstoragefile.h" #include "xen_xl.h" +#include "libxl_capabilities.h"
#define VIR_FROM_THIS VIR_FROM_XENXL
@@ -103,15 +104,31 @@ xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps) size_t i;
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + const char *bios; const char *boot;
- for (i = 0; i < caps->nguests; i++) { - if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && - caps->guests[i]->arch.id == def->os.arch) { - if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, - caps->guests[i]->arch.defaultInfo.loader) < 0) - return -1; + if (xenConfigGetString(conf, "bios", &bios, NULL) < 0) + return -1; + + if (bios && STREQ(bios, "ovmf")) { + if (VIR_ALLOC(def->os.loader) < 0) + return -1; + + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH; + def->os.loader->readonly = VIR_TRISTATE_BOOL_YES; + + if (VIR_STRDUP(def->os.loader->path, + LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0) + return -1; + } else { + for (i = 0; i < caps->nguests; i++) { + if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && + caps->guests[i]->arch.id == def->os.arch) { + if (VIR_ALLOC(def->os.loader) < 0 || + VIR_STRDUP(def->os.loader->path, + caps->guests[i]->arch.defaultInfo.loader) < 0) + return -1; + } } }
@@ -535,6 +552,12 @@ xenFormatXLOS(virConfPtr conf, virDomainDefPtr def) if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1;
+ if (def->os.loader && + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) { + if (xenConfigSetString(conf, "bios", "ovmf") < 0) + return -1; + } + #ifdef LIBXL_HAVE_BUILDINFO_KERNEL if (def->os.kernel && xenConfigSetString(conf, "kernel", def->os.kernel) < 0) diff --git a/tests/testutils.c b/tests/testutils.c index e2dd2fe..54adab2 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -718,6 +718,22 @@ virTestCompareToFile(const char *strcontent, return ret; }
+/* + * @param strcontent: String input content + * @param strsrc: String source to compare strcontent against + */ +int +virTestCompareToString(const char *strcontent, + const char *strsrc) +{ + if (STRNEQ_NULLABLE(strcontent, strsrc)) { + virTestDifference(stderr, strcontent, strsrc); + return -1; + } + + return 0; +} + static void virTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED, virErrorPtr err ATTRIBUTE_UNUSED) diff --git a/tests/testutils.h b/tests/testutils.h index e3881e8..c7c641c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -75,6 +75,8 @@ int virTestDifferenceBin(FILE *stream, size_t length); int virTestCompareToFile(const char *strcontent, const char *filename); +int virTestCompareToString(const char *strcontent, + const char *strsrc);
unsigned int virTestGetDebug(void); unsigned int virTestGetVerbose(void); diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.cfg b/tests/xlconfigdata/test-fullvirt-ovmf.cfg new file mode 100644 index 0000000..b08e7fd --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +builder = "hvm" +bios = "ovmf" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.xml b/tests/xlconfigdata/test-fullvirt-ovmf.xml new file mode 100644 index 0000000..ca902e6 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.xml @@ -0,0 +1,58 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader readonly='yes' type='pflash'>/LIBXL_FIRMWARE_DIR/ovmf.bin</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 62bb144..55c756c 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -43,12 +43,33 @@ static virCapsPtr caps; static virDomainXMLOptionPtr xmlopt;
+ +/* + * This function provides a mechanism to replace variables in test + * data files whose values are discovered at built time. + */ +static char * +testReplaceVarsXML(const char *xml) +{ + char *xmlcfgData; + char *replacedXML; + + if (virTestLoadFile(xml, &xmlcfgData) < 0) + return NULL; + + replacedXML = virStringReplace(xmlcfgData, "/LIBXL_FIRMWARE_DIR", + LIBXL_FIRMWARE_DIR);
I think we want to replace just LIBXL_FW_DIR without the leading slash. That's what would have been done if we had .in files anyway.
+ + VIR_FREE(xmlcfgData); + return replacedXML; +}
Michal

On 06/13/2016 03:33 AM, Michal Privoznik wrote:
On 11.06.2016 00:34, Jim Fehlig wrote:
Add support to xenconfig for conversion of xl.cfg(5) bios config to/from libvirt domXml <loader> config. SeaBIOS is the default for HVM guests using upstream QEMU. ROMBIOS is the default when using the old qemu-dm. This patch allows specifying OVMF as an alternate firmware.
Example xl.cfg: bios = "ovmf"
Example domXML: <os> ... <loader readonly='yes' type='pflash'>/usr/lib/xen/boot/ovmf.bin</loader> </os>
Note that currently Xen does not support a separate nvram for non-volatile variables.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V3: - Rework test code to account for discovery of LIBXL_FIRMWARE_DIR at build time - Drop code that relies on Xen patches that are not yet committed to xen.git master
src/Makefile.am | 2 +- src/xenconfig/xen_xl.c | 37 ++++++++++--- tests/testutils.c | 16 ++++++ tests/testutils.h | 2 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 +++++++++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 ++++++++++++++++++++ tests/xlconfigtest.c | 90 +++++++++++++++++++++++-------- 7 files changed, 202 insertions(+), 29 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index 7004d14..1aff57d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1151,7 +1151,7 @@ noinst_LTLIBRARIES += libvirt_xenconfig.la libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la libvirt_xenconfig_la_LIBADD = $(LIBXL_LIBS) libvirt_xenconfig_la_CFLAGS = \ - -I$(srcdir)/conf $(AM_CFLAGS) + -I$(srcdir)/conf -I$(srcdir)/libxl $(AM_CFLAGS) libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES) endif WITH_XENCONFIG
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 9b8306f..dc54a73 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -33,6 +33,7 @@ #include "virstring.h" #include "virstoragefile.h" #include "xen_xl.h" +#include "libxl_capabilities.h"
#define VIR_FROM_THIS VIR_FROM_XENXL
@@ -103,15 +104,31 @@ xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps) size_t i;
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + const char *bios; const char *boot;
- for (i = 0; i < caps->nguests; i++) { - if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && - caps->guests[i]->arch.id == def->os.arch) { - if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, - caps->guests[i]->arch.defaultInfo.loader) < 0) - return -1; + if (xenConfigGetString(conf, "bios", &bios, NULL) < 0) + return -1; + + if (bios && STREQ(bios, "ovmf")) { + if (VIR_ALLOC(def->os.loader) < 0) + return -1; + + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH; + def->os.loader->readonly = VIR_TRISTATE_BOOL_YES; + + if (VIR_STRDUP(def->os.loader->path, + LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0) + return -1; + } else { + for (i = 0; i < caps->nguests; i++) { + if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && + caps->guests[i]->arch.id == def->os.arch) { + if (VIR_ALLOC(def->os.loader) < 0 || + VIR_STRDUP(def->os.loader->path, + caps->guests[i]->arch.defaultInfo.loader) < 0) + return -1; + } } }
@@ -535,6 +552,12 @@ xenFormatXLOS(virConfPtr conf, virDomainDefPtr def) if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1;
+ if (def->os.loader && + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) { + if (xenConfigSetString(conf, "bios", "ovmf") < 0) + return -1; + } + #ifdef LIBXL_HAVE_BUILDINFO_KERNEL if (def->os.kernel && xenConfigSetString(conf, "kernel", def->os.kernel) < 0) diff --git a/tests/testutils.c b/tests/testutils.c index e2dd2fe..54adab2 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -718,6 +718,22 @@ virTestCompareToFile(const char *strcontent, return ret; }
+/* + * @param strcontent: String input content + * @param strsrc: String source to compare strcontent against + */ +int +virTestCompareToString(const char *strcontent, + const char *strsrc) +{ + if (STRNEQ_NULLABLE(strcontent, strsrc)) { + virTestDifference(stderr, strcontent, strsrc); + return -1; + } + + return 0; +} + static void virTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED, virErrorPtr err ATTRIBUTE_UNUSED) diff --git a/tests/testutils.h b/tests/testutils.h index e3881e8..c7c641c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -75,6 +75,8 @@ int virTestDifferenceBin(FILE *stream, size_t length); int virTestCompareToFile(const char *strcontent, const char *filename); +int virTestCompareToString(const char *strcontent, + const char *strsrc);
unsigned int virTestGetDebug(void); unsigned int virTestGetVerbose(void); diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.cfg b/tests/xlconfigdata/test-fullvirt-ovmf.cfg new file mode 100644 index 0000000..b08e7fd --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +builder = "hvm" +bios = "ovmf" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.xml b/tests/xlconfigdata/test-fullvirt-ovmf.xml new file mode 100644 index 0000000..ca902e6 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.xml @@ -0,0 +1,58 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader readonly='yes' type='pflash'>/LIBXL_FIRMWARE_DIR/ovmf.bin</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 62bb144..55c756c 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -43,12 +43,33 @@ static virCapsPtr caps; static virDomainXMLOptionPtr xmlopt;
+ +/* + * This function provides a mechanism to replace variables in test + * data files whose values are discovered at built time. + */ +static char * +testReplaceVarsXML(const char *xml) +{ + char *xmlcfgData; + char *replacedXML; + + if (virTestLoadFile(xml, &xmlcfgData) < 0) + return NULL; + + replacedXML = virStringReplace(xmlcfgData, "/LIBXL_FIRMWARE_DIR", + LIBXL_FIRMWARE_DIR); I think we want to replace just LIBXL_FW_DIR without the leading slash. That's what would have been done if we had .in files anyway.
If only LIBXL_FIRMWARE_DIR is replaced, the test fails since there are two leading slashes instead of the expected one. If I remove the leading slash from the test data fail, then virschematest fails on the test data file with XML document failed to validate against schema: Unable to validate doc against /home/jfehlig/virt/upstream/libvirt/docs/schemas/domain.rng Extra element os in interleave This lame approach fixed both problems :-). Regards, Jim

On 13.06.2016 16:21, Jim Fehlig wrote:
On 06/13/2016 03:33 AM, Michal Privoznik wrote:
On 11.06.2016 00:34, Jim Fehlig wrote:
Add support to xenconfig for conversion of xl.cfg(5) bios config to/from libvirt domXml <loader> config. SeaBIOS is the default for HVM guests using upstream QEMU. ROMBIOS is the default when using the old qemu-dm. This patch allows specifying OVMF as an alternate firmware.
Example xl.cfg: bios = "ovmf"
Example domXML: <os> ... <loader readonly='yes' type='pflash'>/usr/lib/xen/boot/ovmf.bin</loader> </os>
Note that currently Xen does not support a separate nvram for non-volatile variables.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V3: - Rework test code to account for discovery of LIBXL_FIRMWARE_DIR at build time - Drop code that relies on Xen patches that are not yet committed to xen.git master
src/Makefile.am | 2 +- src/xenconfig/xen_xl.c | 37 ++++++++++--- tests/testutils.c | 16 ++++++ tests/testutils.h | 2 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 +++++++++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 ++++++++++++++++++++ tests/xlconfigtest.c | 90 +++++++++++++++++++++++-------- 7 files changed, 202 insertions(+), 29 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index 7004d14..1aff57d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1151,7 +1151,7 @@ noinst_LTLIBRARIES += libvirt_xenconfig.la libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la libvirt_xenconfig_la_LIBADD = $(LIBXL_LIBS) libvirt_xenconfig_la_CFLAGS = \ - -I$(srcdir)/conf $(AM_CFLAGS) + -I$(srcdir)/conf -I$(srcdir)/libxl $(AM_CFLAGS) libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES) endif WITH_XENCONFIG
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c index 9b8306f..dc54a73 100644 --- a/src/xenconfig/xen_xl.c +++ b/src/xenconfig/xen_xl.c @@ -33,6 +33,7 @@ #include "virstring.h" #include "virstoragefile.h" #include "xen_xl.h" +#include "libxl_capabilities.h"
#define VIR_FROM_THIS VIR_FROM_XENXL
@@ -103,15 +104,31 @@ xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps) size_t i;
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + const char *bios; const char *boot;
- for (i = 0; i < caps->nguests; i++) { - if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && - caps->guests[i]->arch.id == def->os.arch) { - if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, - caps->guests[i]->arch.defaultInfo.loader) < 0) - return -1; + if (xenConfigGetString(conf, "bios", &bios, NULL) < 0) + return -1; + + if (bios && STREQ(bios, "ovmf")) { + if (VIR_ALLOC(def->os.loader) < 0) + return -1; + + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH; + def->os.loader->readonly = VIR_TRISTATE_BOOL_YES; + + if (VIR_STRDUP(def->os.loader->path, + LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0) + return -1; + } else { + for (i = 0; i < caps->nguests; i++) { + if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM && + caps->guests[i]->arch.id == def->os.arch) { + if (VIR_ALLOC(def->os.loader) < 0 || + VIR_STRDUP(def->os.loader->path, + caps->guests[i]->arch.defaultInfo.loader) < 0) + return -1; + } } }
@@ -535,6 +552,12 @@ xenFormatXLOS(virConfPtr conf, virDomainDefPtr def) if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1;
+ if (def->os.loader && + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) { + if (xenConfigSetString(conf, "bios", "ovmf") < 0) + return -1; + } + #ifdef LIBXL_HAVE_BUILDINFO_KERNEL if (def->os.kernel && xenConfigSetString(conf, "kernel", def->os.kernel) < 0) diff --git a/tests/testutils.c b/tests/testutils.c index e2dd2fe..54adab2 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -718,6 +718,22 @@ virTestCompareToFile(const char *strcontent, return ret; }
+/* + * @param strcontent: String input content + * @param strsrc: String source to compare strcontent against + */ +int +virTestCompareToString(const char *strcontent, + const char *strsrc) +{ + if (STRNEQ_NULLABLE(strcontent, strsrc)) { + virTestDifference(stderr, strcontent, strsrc); + return -1; + } + + return 0; +} + static void virTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED, virErrorPtr err ATTRIBUTE_UNUSED) diff --git a/tests/testutils.h b/tests/testutils.h index e3881e8..c7c641c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -75,6 +75,8 @@ int virTestDifferenceBin(FILE *stream, size_t length); int virTestCompareToFile(const char *strcontent, const char *filename); +int virTestCompareToString(const char *strcontent, + const char *strsrc);
unsigned int virTestGetDebug(void); unsigned int virTestGetVerbose(void); diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.cfg b/tests/xlconfigdata/test-fullvirt-ovmf.cfg new file mode 100644 index 0000000..b08e7fd --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +viridian = 0 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +builder = "hvm" +bios = "ovmf" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-ovmf.xml b/tests/xlconfigdata/test-fullvirt-ovmf.xml new file mode 100644 index 0000000..ca902e6 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-ovmf.xml @@ -0,0 +1,58 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader readonly='yes' type='pflash'>/LIBXL_FIRMWARE_DIR/ovmf.bin</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 62bb144..55c756c 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -43,12 +43,33 @@ static virCapsPtr caps; static virDomainXMLOptionPtr xmlopt;
+ +/* + * This function provides a mechanism to replace variables in test + * data files whose values are discovered at built time. + */ +static char * +testReplaceVarsXML(const char *xml) +{ + char *xmlcfgData; + char *replacedXML; + + if (virTestLoadFile(xml, &xmlcfgData) < 0) + return NULL; + + replacedXML = virStringReplace(xmlcfgData, "/LIBXL_FIRMWARE_DIR", + LIBXL_FIRMWARE_DIR); I think we want to replace just LIBXL_FW_DIR without the leading slash. That's what would have been done if we had .in files anyway.
If only LIBXL_FIRMWARE_DIR is replaced, the test fails since there are two leading slashes instead of the expected one. If I remove the leading slash from the test data fail, then virschematest fails on the test data file with
XML document failed to validate against schema: Unable to validate doc against /home/jfehlig/virt/upstream/libvirt/docs/schemas/domain.rng Extra element os in interleave
Ah. Okay then. It's a bit unfortunate but I can live with that. Michal

Populate libxl_domain_build_info struct with bios and firmware info from virDomainLoaderDef. Note: Currently libxl only allows specifying the type of BIOS. For type LIBXL_BIOS_TYPE_OVMF, the firmware path is configured when building Xen using '--with-system-ovmf='. If not specified, LIBXL_FIRMWARE_DIR/ovmf.bin is used. In the future, Xen will support a user-specified firmware path. See http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01628.html Once that work is merged into xen.git, the libvirt libxl driver will be able to honor a user-specified path. In the meantime use the implicit path, which is tolerable since it is advertised in domcapabilities. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 96f9635..acb6594 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -395,6 +395,19 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, return -1; #endif + /* + * Currently libxl only allows specifying the type of BIOS. + * If the type is PFLASH, we assume OVMF and set libxl_bios_type + * to LIBXL_BIOS_TYPE_OVMF. The path to the OVMF firmware is + * configured when building Xen using '--with-system-ovmf='. If + * not specified, LIBXL_FIRMWARE_DIR/ovmf.bin is used. In the + * future, Xen will support a user-specified firmware path. See + * http://lists.xenproject.org/archives/html/xen-devel/2016-03/msg01628.html + */ + if (def->os.loader && + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) + b_info->u.hvm.bios = LIBXL_BIOS_TYPE_OVMF; + if (def->emulator) { if (!virFileExists(def->emulator)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 2.1.4

On 11.06.2016 00:34, Jim Fehlig wrote:
This is essentially a V3 of
https://www.redhat.com/archives/libvir-list/2016-April/msg01358.html
To avoid code duplication in that series, I proposed adding a virFirmware object that could be used by multiple drivers
https://www.redhat.com/archives/libvir-list/2016-May/msg01370.html
mprivozn ACK'ed that series, but I deferred committing it until 1.3.5 was released since it's not all that useful without accompanying use by another driver.
Jim Fehlig (6): driver config: Introduce virFirmware object libxl: add default firmwares to driver config object libxl: introduce libxl_capabilities.{ch} libxl: implement connectGetDomainCapabilities xenconfig: support bios=ovmf xl.cfg libxl: Add support for ovmf firmware
po/POTFILES.in | 2 + src/Makefile.am | 12 +- src/libvirt_private.syms | 6 + src/libxl/libxl_capabilities.c | 598 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 57 +++ src/libxl/libxl_conf.c | 460 ++-------------------- src/libxl/libxl_conf.h | 22 +- src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 75 ++++ src/qemu/qemu_capabilities.c | 22 +- src/qemu/qemu_capabilities.h | 5 +- src/qemu/qemu_conf.c | 127 +----- src/qemu/qemu_conf.h | 7 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 6 +- src/util/virfirmware.c | 137 +++++++ src/util/virfirmware.h | 51 +++ src/xenconfig/xen_xl.c | 37 +- tests/Makefile.am | 5 + tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 +++ tests/domaincapstest.c | 64 ++- tests/testutils.c | 16 + tests/testutils.h | 2 + tests/testutilsxen.h | 1 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 ++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 +++ tests/xlconfigtest.c | 90 ++++- 28 files changed, 1415 insertions(+), 600 deletions(-) create mode 100644 src/libxl/libxl_capabilities.c create mode 100644 src/libxl/libxl_capabilities.h create mode 100644 src/util/virfirmware.c create mode 100644 src/util/virfirmware.h create mode 100644 tests/domaincapsschemadata/libxl-xenfv.xml create mode 100644 tests/domaincapsschemadata/libxl-xenpv.xml create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.xml
ACK series Michal

On 06/13/2016 03:29 AM, Michal Privoznik wrote:
On 11.06.2016 00:34, Jim Fehlig wrote:
This is essentially a V3 of
https://www.redhat.com/archives/libvir-list/2016-April/msg01358.html
To avoid code duplication in that series, I proposed adding a virFirmware object that could be used by multiple drivers
https://www.redhat.com/archives/libvir-list/2016-May/msg01370.html
mprivozn ACK'ed that series, but I deferred committing it until 1.3.5 was released since it's not all that useful without accompanying use by another driver.
Jim Fehlig (6): driver config: Introduce virFirmware object libxl: add default firmwares to driver config object libxl: introduce libxl_capabilities.{ch} libxl: implement connectGetDomainCapabilities xenconfig: support bios=ovmf xl.cfg libxl: Add support for ovmf firmware
po/POTFILES.in | 2 + src/Makefile.am | 12 +- src/libvirt_private.syms | 6 + src/libxl/libxl_capabilities.c | 598 +++++++++++++++++++++++++++++ src/libxl/libxl_capabilities.h | 57 +++ src/libxl/libxl_conf.c | 460 ++-------------------- src/libxl/libxl_conf.h | 22 +- src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 75 ++++ src/qemu/qemu_capabilities.c | 22 +- src/qemu/qemu_capabilities.h | 5 +- src/qemu/qemu_conf.c | 127 +----- src/qemu/qemu_conf.h | 7 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 6 +- src/util/virfirmware.c | 137 +++++++ src/util/virfirmware.h | 51 +++ src/xenconfig/xen_xl.c | 37 +- tests/Makefile.am | 5 + tests/domaincapsschemadata/libxl-xenfv.xml | 68 ++++ tests/domaincapsschemadata/libxl-xenpv.xml | 58 +++ tests/domaincapstest.c | 64 ++- tests/testutils.c | 16 + tests/testutils.h | 2 + tests/testutilsxen.h | 1 + tests/xlconfigdata/test-fullvirt-ovmf.cfg | 26 ++ tests/xlconfigdata/test-fullvirt-ovmf.xml | 58 +++ tests/xlconfigtest.c | 90 ++++- 28 files changed, 1415 insertions(+), 600 deletions(-) create mode 100644 src/libxl/libxl_capabilities.c create mode 100644 src/libxl/libxl_capabilities.h create mode 100644 src/util/virfirmware.c create mode 100644 src/util/virfirmware.h create mode 100644 tests/domaincapsschemadata/libxl-xenfv.xml create mode 100644 tests/domaincapsschemadata/libxl-xenpv.xml create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-ovmf.xml
ACK series
Thanks! I've pushed this now without making any changes to 5/6, but can certainly send follow-ups to rework anything we deem needs reworking. Regards, Jim
participants (4)
-
Jim Fehlig
-
Martin Kletzander
-
Michal Privoznik
-
Roman Bogorodskiy