[libvirt] [PATCH] domaincaps: Expose UEFI capability

As of 542899168c38 we learned libvirt to use UEFI for domains. However, management applications may firstly query if libvirt supports it. And this is where virConnectGetDomainCapabilities() API comes handy. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomaincaps.html.in | 40 ++++++++++++++++++++++ docs/schemas/domaincaps.rng | 21 ++++++++++++ src/conf/domain_capabilities.c | 28 +++++++++++++++ src/conf/domain_capabilities.h | 16 +++++++++ src/qemu/qemu_capabilities.c | 38 ++++++++++++++++++++ tests/domaincapsschemadata/domaincaps-basic.xml | 1 + tests/domaincapsschemadata/domaincaps-full.xml | 13 +++++++ .../domaincaps-qemu_1.6.50-1.xml | 12 +++++++ tests/domaincapstest.c | 8 +++++ 9 files changed, 177 insertions(+) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index 66b6017..34d746d 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -93,6 +93,46 @@ <dd>The maximum number of supported virtual CPUs</dd> </dl> + <h3><a name="elementsOSBIOS">BIOS bootloader</a></h3> + + <p>Sometimes users might want to tweak some BIOS knobs or use + UEFI. For cases like that, <a + href="formatdomain.html#elementsOSBIOS"><code>os</code></a> + element exposes what values can be passed to its children.</p> + +<pre> +<domainCapabilities> + ... + <os supported='yes'> + <loader supported='yes'> + <enum name='type'> + <value>rom</value> + <value>pflash</value> + </enum> + <enum name='readonly'> + <value>yes</value> + <value>no</value> + </enum> + </loader> + </os> + ... +<domainCapabilities> +</pre> + + <p>For the <code>loader</code> element, the following can occur:</p> + + <dl> + <dt>type</dt> + <dd>Whether loader is a typical BIOS (<code>rom</code>) or + an UEFI binary (<code>pflash</code>). This refers to + <code>type</code> attribute of the <loader/> + element.</dd> + + <dt>readonly</dt> + <dd>Options for the <code>readonly</code> attribute of the + <loader/> element.</dd> + </dl> + <h3><a name="elementsDevices">Devices</a></h3> <p> diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 627b699..ad8d966 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -26,6 +26,9 @@ <ref name='vcpu'/> </optional> <optional> + <ref name='os'/> + </optional> + <optional> <ref name='devices'/> </optional> </interleave> @@ -41,6 +44,24 @@ </element> </define> + <define name='loader'> + <element name='loader'> + <ref name='supported'/> + <ref name='enum'/> + </element> + </define> + + <define name='os'> + <element name='os'> + <interleave> + <ref name='supported'/> + <optional> + <ref name='loader'/> + </optional> + </interleave> + </element> + </define> + <define name='devices'> <element name='devices'> <interleave> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index df190eb..5a3c8e7 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -178,6 +178,32 @@ virDomainCapsEnumFormat(virBufferPtr buf, #capsEnum, valToStr); \ } while (0) + +static void +virDomainCapsLoaderFormat(virBufferPtr buf, + virDomainCapsLoaderPtr loader) +{ + FORMAT_PROLOGUE(loader); + + ENUM_PROCESS(loader, type, virDomainLoaderTypeToString); + ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString); + + FORMAT_EPILOGUE(loader); +} + +static void +virDomainCapsOSFormat(virBufferPtr buf, + virDomainCapsOSPtr os) +{ + virDomainCapsLoaderPtr loader = &os->loader; + + FORMAT_PROLOGUE(os); + + virDomainCapsLoaderFormat(buf, loader); + + FORMAT_EPILOGUE(os); +} + static void virDomainCapsDeviceDiskFormat(virBufferPtr buf, virDomainCapsDeviceDiskPtr const disk) @@ -225,6 +251,8 @@ virDomainCapsFormatInternal(virBufferPtr buf, if (caps->maxvcpus) virBufferAsprintf(buf, "<vcpu max='%d'/>\n", caps->maxvcpus); + virDomainCapsOSFormat(buf, &caps->os); + virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 731e66f..768646b 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -43,6 +43,21 @@ struct _virDomainCapsDevice { bool supported; /* true if <devtype> is supported by hypervisor */ }; +typedef struct _virDomainCapsLoader virDomainCapsLoader; +typedef virDomainCapsLoader *virDomainCapsLoaderPtr; +struct _virDomainCapsLoader { + virDomainCapsDevice device; + virDomainCapsEnum type; /* Info about virDomainLoader */ + virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */ +}; + +typedef struct _virDomainCapsOS virDomainCapsOS; +typedef virDomainCapsOS *virDomainCapsOSPtr; +struct _virDomainCapsOS { + virDomainCapsDevice device; + virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ +}; + typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk; typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; struct _virDomainCapsDeviceDisk { @@ -75,6 +90,7 @@ struct _virDomainCaps { /* Some machine specific info */ int maxvcpus; + virDomainCapsOS os; virDomainCapsDeviceDisk disk; virDomainCapsDeviceHostdev hostdev; /* add new domain devices here */ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 81ada48..9f8868d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3609,6 +3609,42 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps) static void +virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsLoaderPtr loader, + virArch arch) +{ + loader->device.supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(loader->type, + VIR_DOMAIN_LOADER_TYPE_ROM); + + if (arch == VIR_ARCH_X86_64 && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) + VIR_DOMAIN_CAPS_ENUM_SET(loader->type, + VIR_DOMAIN_LOADER_TYPE_PFLASH); + + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) + VIR_DOMAIN_CAPS_ENUM_SET(loader->readonly, + VIR_TRISTATE_BOOL_YES, + VIR_TRISTATE_BOOL_NO); +} + + +static void +virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsOSPtr os, + virArch arch) +{ + virDomainCapsLoaderPtr loader = &os->loader; + + os->device.supported = true; + virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch); +} + + +static void virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, virDomainCapsDeviceDiskPtr disk) { @@ -3686,12 +3722,14 @@ void virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, virQEMUCapsPtr qemuCaps) { + virDomainCapsOSPtr os = &domCaps->os; virDomainCapsDeviceDiskPtr disk = &domCaps->disk; virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; int maxvcpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, domCaps->machine); domCaps->maxvcpus = maxvcpus; + virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch); virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk); virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev); } diff --git a/tests/domaincapsschemadata/domaincaps-basic.xml b/tests/domaincapsschemadata/domaincaps-basic.xml index 9963519..6171393 100644 --- a/tests/domaincapsschemadata/domaincaps-basic.xml +++ b/tests/domaincapsschemadata/domaincaps-basic.xml @@ -3,6 +3,7 @@ <domain>uml</domain> <machine>my-machine-type</machine> <arch>x86_64</arch> + <os supported='no'/> <devices> <disk supported='no'/> <hostdev supported='no'/> diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml index 58dd4cb..9722772 100644 --- a/tests/domaincapsschemadata/domaincaps-full.xml +++ b/tests/domaincapsschemadata/domaincaps-full.xml @@ -4,6 +4,19 @@ <machine>my-machine-type</machine> <arch>x86_64</arch> <vcpu max='255'/> + <os supported='yes'> + <loader supported='yes'> + <enum name='type'> + <value>rom</value> + <value>pflash</value> + </enum> + <enum name='readonly'> + <value>default</value> + <value>yes</value> + <value>no</value> + </enum> + </loader> + </os> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml index 8b63993..568cecb 100644 --- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml @@ -3,6 +3,18 @@ <domain>kvm</domain> <machine>pc-1.2</machine> <arch>x86_64</arch> + <os supported='yes'> + <loader supported='yes'> + <enum name='type'> + <value>rom</value> + <value>pflash</value> + </enum> + <enum name='readonly'> + <value>yes</value> + <value>no</value> + </enum> + </loader> + </os> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 78197e2..f240643 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -38,10 +38,18 @@ static void fillAll(virDomainCapsPtr domCaps, void *opaque ATTRIBUTE_UNUSED) { + virDomainCapsOSPtr os = &domCaps->os; + virDomainCapsLoaderPtr loader = &os->loader; virDomainCapsDeviceDiskPtr disk = &domCaps->disk; virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; domCaps->maxvcpus = 255; + os->device.supported = true; + + loader->device.supported = true; + SET_ALL_BITS(loader->type); + SET_ALL_BITS(loader->readonly); + disk->device.supported = true; SET_ALL_BITS(disk->diskDevice); SET_ALL_BITS(disk->bus); -- 1.8.5.5

On 09/16/2014 09:44 AM, Michal Privoznik wrote:
As of 542899168c38 we learned libvirt to use UEFI for domains. However, management applications may firstly query if libvirt supports it. And this is where virConnectGetDomainCapabilities() API comes handy.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Tested-by: Cole Robinson <crobinso@redhat.com> Acked-by: Cole Robinson <crobinso@redhat.com> So this exposes that qemu + libvirt have the required support to use OVMF. The other bit virt-manager would like is to know the paths to the OVMF binaries. Preferably with some way to tell if they actually exist on disk, which might just be hiding them from the XML if they aren't found, or an extra XML property. As you mentioned in the virt-tools-list email, you probably don't need to expose the vars template file path, and just the OVMF binary path. Thoughts on what the XML might look like? Doesn't seem like there's any existing precedence in domcapabilities schema Thanks, Cole

On 16.09.2014 17:11, Cole Robinson wrote:
On 09/16/2014 09:44 AM, Michal Privoznik wrote:
As of 542899168c38 we learned libvirt to use UEFI for domains. However, management applications may firstly query if libvirt supports it. And this is where virConnectGetDomainCapabilities() API comes handy.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Tested-by: Cole Robinson <crobinso@redhat.com> Acked-by: Cole Robinson <crobinso@redhat.com>
Thanks. I'll push this one shortly.
So this exposes that qemu + libvirt have the required support to use OVMF.
The other bit virt-manager would like is to know the paths to the OVMF binaries. Preferably with some way to tell if they actually exist on disk, which might just be hiding them from the XML if they aren't found, or an extra XML property.
As you mentioned in the virt-tools-list email, you probably don't need to expose the vars template file path, and just the OVMF binary path.
Thoughts on what the XML might look like? Doesn't seem like there's any existing precedence in domcapabilities schema
Correct. domcapabilities is not very mature atm. With this patch, its output should look like this: <domainCapabilities> <snip/> <os supported='yes'> <loader supported='yes'> <enum name='type'> <value>rom</value> <value>pflash</value> </enum> <enum name='readonly'> <value>yes</value> <value>no</value> </enum> </loader> </os> <devices/> </domainCapabilities> How about introducing <nvram/> under the <os/> (like it is in the domain XML)? Something like the following: <os supported='yes'> <loader supported='yes'> <enum name='type'> <value>rom</value> <value>pflash</value> </enum> <enum name='readonly'> <value>yes</value> <value>no</value> </enum> </loader> <nvram supported='yes'> <value>/usr/share/OVMF/OVMF_VARS.fd</value> <value>/other/files/from/libvirtd.config</value> ... </nvram> </os> As you've probably guessed, the <nvram/>'s <value/> would repeat itself for every VARS file known to libvirt. Or should we enclose these into an <enum/> and make it child of the <nvram/>? What should the enum be called then? Or even better - shall the <nvram/> be turned into <enum name='nvram'/>? Michal

On 09/16/2014 11:35 AM, Michal Privoznik wrote:
On 16.09.2014 17:11, Cole Robinson wrote:
On 09/16/2014 09:44 AM, Michal Privoznik wrote:
As of 542899168c38 we learned libvirt to use UEFI for domains. However, management applications may firstly query if libvirt supports it. And this is where virConnectGetDomainCapabilities() API comes handy.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Tested-by: Cole Robinson <crobinso@redhat.com> Acked-by: Cole Robinson <crobinso@redhat.com>
Thanks. I'll push this one shortly.
So this exposes that qemu + libvirt have the required support to use OVMF.
The other bit virt-manager would like is to know the paths to the OVMF binaries. Preferably with some way to tell if they actually exist on disk, which might just be hiding them from the XML if they aren't found, or an extra XML property.
As you mentioned in the virt-tools-list email, you probably don't need to expose the vars template file path, and just the OVMF binary path.
Thoughts on what the XML might look like? Doesn't seem like there's any existing precedence in domcapabilities schema
Correct. domcapabilities is not very mature atm. With this patch, its output should look like this:
<domainCapabilities> <snip/> <os supported='yes'> <loader supported='yes'> <enum name='type'> <value>rom</value> <value>pflash</value> </enum> <enum name='readonly'> <value>yes</value> <value>no</value> </enum> </loader> </os> <devices/> </domainCapabilities>
How about introducing <nvram/> under the <os/> (like it is in the domain XML)? Something like the following:
<os supported='yes'> <loader supported='yes'> <enum name='type'> <value>rom</value> <value>pflash</value> </enum> <enum name='readonly'> <value>yes</value> <value>no</value> </enum> </loader> <nvram supported='yes'> <value>/usr/share/OVMF/OVMF_VARS.fd</value> <value>/other/files/from/libvirtd.config</value> ... </nvram> </os>
As you've probably guessed, the <nvram/>'s <value/> would repeat itself for every VARS file known to libvirt. Or should we enclose these into an <enum/> and make it child of the <nvram/>? What should the enum be called then? Or even better - shall the <nvram/> be turned into <enum name='nvram'/>?
Yeah that format looks fine, but I'd expect we'd list <loader> values and not nvram. Theoretically you could have multiple OVMF binaries map to the same nvram template, but not the other way around. Also template is the uninteresting bit from the tool's perspective, since libvirt will fill it in for us. - Cole
participants (2)
-
Cole Robinson
-
Michal Privoznik