xenconfig: support bios=ovmf xl.cfg

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>
This commit is contained in:
Jim Fehlig 2016-04-20 15:14:34 -06:00
parent 11567cf66f
commit 53d98ccea7
7 changed files with 202 additions and 29 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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" ]

View File

@ -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>

View File

@ -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");