Don't mess up labelling of /dev/net/tun (bz #1141879)

pflash/nvram support for UEFI/OVMF
This commit is contained in:
Cole Robinson 2014-09-18 15:36:06 -04:00
parent 622cf0d642
commit 3ec523d168
15 changed files with 3510 additions and 22 deletions

View File

@ -1,6 +1,6 @@
From 28b27787c5bb545df3c178fef682151c45b66784 Mon Sep 17 00:00:00 2001
From b2735463b886ac88027cec0ff1a4dbaa4f8be739 Mon Sep 17 00:00:00 2001
From: Martin Kletzander <mkletzan@redhat.com>
Date: Mon, 8 Sep 2014 07:46:39 +0200
Date: Sun, 7 Sep 2014 20:41:11 +0200
Subject: [PATCH] rpc: make daemon spawning a bit more intelligent
This way it behaves more like the daemon itself does (acquiring a
@ -10,12 +10,13 @@ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=927369
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1138604
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit bd9ad91a4036649645fffb1598213339263478de)
---
src/rpc/virnetsocket.c | 57 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 51 insertions(+), 6 deletions(-)
src/rpc/virnetsocket.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 59 insertions(+), 8 deletions(-)
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 306c9ea..fa9ba99 100644
index 306c9ea..5feccf6 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -51,9 +51,11 @@
@ -41,7 +42,7 @@ index 306c9ea..fa9ba99 100644
virSocketAddr localAddr;
virSocketAddr remoteAddr;
@@ -583,16 +588,45 @@ int virNetSocketNewConnectUNIX(const char *path,
@@ -583,16 +588,46 @@ int virNetSocketNewConnectUNIX(const char *path,
goto error;
}
@ -55,7 +56,8 @@ index 306c9ea..fa9ba99 100644
+ if (virPidFileConstructPath(false, NULL, binname, &pidpath) < 0)
+ goto error;
+
+ if ((pidfd = virPidFileAcquirePath(pidpath, false, getpid())) < 0) {
+ pidfd = virPidFileAcquirePath(pidpath, false, getpid());
+ if (pidfd < 0) {
+ /*
+ * This can happen in a very rare case of two clients spawning two
+ * daemons at the same time, and the error in the logs that gets
@ -76,7 +78,7 @@ index 306c9ea..fa9ba99 100644
- * per-process, chmod() is racy and fchmod() has undefined
- * behaviour on sockets according to POSIX, so it doesn't
- * work outside Linux.
+ * We already even acquired the pidfile, so noone else should be using
+ * We already even acquired the pidfile, so no one else should be using
+ * @path right now. So we're OK to unlink it and paying attention to
+ * the return value makes no real sense here. Only if it's not an
+ * abstract socket, of course.
@ -91,19 +93,28 @@ index 306c9ea..fa9ba99 100644
*/
if ((pid = virFork()) < 0)
goto error;
@@ -612,8 +646,9 @@ int virNetSocketNewConnectUNIX(const char *path,
@@ -610,12 +645,16 @@ int virNetSocketNewConnectUNIX(const char *path,
if (status != EXIT_SUCCESS) {
/*
* OK, so the subprocces failed to bind() the socket. This may mean
* that another daemon was starting at the same time and succeeded
- * OK, so the subprocces failed to bind() the socket. This may mean
- * that another daemon was starting at the same time and succeeded
- * with its bind(). So we'll try connecting again, but this time
- * without spawning the daemon.
+ * with its bind() (even though it should not happen because we
+ * using a pidfile for the race). So we'll try connecting again,
+ * but this time without spawning the daemon.
+ * OK, so the child failed to bind() the socket. This may mean that
+ * another daemon was starting at the same time and succeeded with
+ * its bind() (even though it should not happen because we using a
+ * pidfile for the race). So we'll try connecting again, but this
+ * time without spawning the daemon.
*/
spawnDaemon = false;
+ virPidFileDeletePath(pidpath);
+ VIR_FORCE_CLOSE(pidfd);
+ VIR_FORCE_CLOSE(passfd);
goto retry;
@@ -632,6 +667,12 @@ int virNetSocketNewConnectUNIX(const char *path,
}
@@ -632,6 +671,12 @@ int virNetSocketNewConnectUNIX(const char *path,
goto error;
}
@ -116,11 +127,16 @@ index 306c9ea..fa9ba99 100644
if (virNetSocketForkDaemon(binary, passfd) < 0)
goto error;
}
@@ -648,8 +689,12 @@ int virNetSocketNewConnectUNIX(const char *path,
@@ -645,11 +690,17 @@ int virNetSocketNewConnectUNIX(const char *path,
if (!(*retsock = virNetSocketNew(&localAddr, &remoteAddr, true, fd, -1, 0)))
goto error;
+ VIR_FREE(pidpath);
+
return 0;
error:
+ if (pidfd > 0)
+ if (pidfd >= 0)
+ virPidFileDeletePath(pidpath);
+ VIR_FREE(pidpath);
VIR_FORCE_CLOSE(fd);

View File

@ -1,4 +1,4 @@
From 2950887a9e7800e0421dadb0b9c348adb087deca Mon Sep 17 00:00:00 2001
From d437ccd8fef17c2bb119e98a034bdc56ff9425b2 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Mon, 15 Sep 2014 14:49:35 -0400
Subject: [PATCH] spec: Don't build wireshark on f21 (non upstream)

View File

@ -1,4 +1,4 @@
From 09f0ff32b8925131c058de768751d3368f47a722 Mon Sep 17 00:00:00 2001
From abb9c206877a937c2a509ec534c190b27c0b0e55 Mon Sep 17 00:00:00 2001
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 3 Sep 2014 10:51:14 +0200
Subject: [PATCH] spec: Fix preun script for daemon

View File

@ -0,0 +1,98 @@
From c414cb524bdbc3555a5332fe75b40f8cf3ded0f4 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 18 Sep 2014 15:17:29 +0200
Subject: [PATCH] virSecuritySELinuxSetTapFDLabel: Temporarily revert to old
behavior
https://bugzilla.redhat.com/show_bug.cgi?id=1141879
A long time ago I've implemented support for so called multiqueue
net. The idea was to let guest network traffic be processed by
multiple host CPUs and thus increasing performance. However, this
behavior is enabled by QEMU via special ioctl() iterated over the
all tap FDs passed in by libvirt. Unfortunately, SELinux comes in
and disallows the ioctl() call because the /dev/net/tun has label
system_u:object_r:tun_tap_device_t:s0 and 'attach_queue' ioctl()
is not allowed on tun_tap_device_t type. So after discussion with
a SELinux developer we've decided that the FDs passed to the QEMU
should be labelled with svirt_t type and SELinux policy will
allow the ioctl(). Therefore I've made a patch
(cf976d9dcf4e592261b14f03572) that does exactly this. The patch
was fixed then by a4431931393aeb1ac5893f121151fa3df4fde612 and
b635b7a1af0e64754016d758376f382470bc11e7. However, things are not
that easy - even though the API to label FD is called
(fsetfilecon_raw) the underlying file is labelled too! So
effectively we are mangling /dev/net/tun label. Yes, that broke
dozen of other application from openvpn, or boxes, to qemu
running other domains.
The best solution would be if SELinux provides a way to label an
FD only, which could be then labeled when passed to the qemu.
However that's a long path to go and we should fix this
regression AQAP. So I went to talk to the SELinux developer again
and we agreed on temporary solution that:
1) All the three patches are reverted
2) SELinux temporarily allows 'attach_queue' on the
tun_tap_device_t
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ba7468dbb13f552a9177d01ea8bad155f9877bc3)
---
src/security/security_selinux.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index e8c13db..c078cab 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2330,17 +2330,47 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
}
static int
-virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd)
{
+ struct stat buf;
+ security_context_t fcon = NULL;
virSecurityLabelDefPtr secdef;
+ char *str = NULL;
+ int rc = -1;
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
if (!secdef || !secdef->label)
return 0;
- return virSecuritySELinuxFSetFilecon(fd, secdef->imagelabel);
+ if (fstat(fd, &buf) < 0) {
+ virReportSystemError(errno, _("cannot stat tap fd %d"), fd);
+ goto cleanup;
+ }
+
+ if ((buf.st_mode & S_IFMT) != S_IFCHR) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("tap fd %d is not character device"), fd);
+ goto cleanup;
+ }
+
+ if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot lookup default selinux label for tap fd %d"), fd);
+ goto cleanup;
+ }
+
+ if (!(str = virSecuritySELinuxContextAddRange(secdef->label, fcon))) {
+ goto cleanup;
+ } else {
+ rc = virSecuritySELinuxFSetFilecon(fd, str);
+ }
+
+ cleanup:
+ freecon(fcon);
+ VIR_FREE(str);
+ return rc;
}
static char *

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
From ac0859aae7162255848effdc560368266845dfce Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 7 Aug 2014 13:50:00 +0200
Subject: [PATCH] qemu: Implement extended loader and nvram
QEMU now supports UEFI with the following command line:
-drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \
-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
where the first line reflects <loader> and the second one <nvram>.
Moreover, these two lines obsolete the -bios argument.
Note that UEFI is unusable without ACPI. This is handled properly now.
Among with this extension, the variable file is expected to be
writable and hence we need security drivers to label it.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 542899168c382610dbad9a597d27ef3d7c699f68)
---
src/qemu/qemu_command.c | 94 +++++++++++++++++++++-
src/security/security_dac.c | 8 ++
src/security/security_selinux.c | 8 ++
.../qemuxml2argvdata/qemuxml2argv-bios-nvram.args | 10 +++
tests/qemuxml2argvtest.c | 2 +
5 files changed, 118 insertions(+), 4 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3cb2e0b..718533b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7370,6 +7370,94 @@ qemuBuildChrDeviceCommandLine(virCommandPtr cmd,
return 0;
}
+static int
+qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
+ virDomainDefPtr def,
+ virQEMUCapsPtr qemuCaps)
+{
+ int ret = -1;
+ virDomainLoaderDefPtr loader = def->os.loader;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ int unit = 0;
+
+ if (!loader)
+ return 0;
+
+ switch ((virDomainLoader) loader->type) {
+ case VIR_DOMAIN_LOADER_TYPE_ROM:
+ virCommandAddArg(cmd, "-bios");
+ virCommandAddArg(cmd, loader->path);
+ break;
+
+ case VIR_DOMAIN_LOADER_TYPE_PFLASH:
+ /* UEFI is supported only for x86_64 currently */
+ if (def->os.arch != VIR_ARCH_X86_64) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("pflash is not supported for %s guest architecture"),
+ virArchToString(def->os.arch));
+ goto cleanup;
+ }
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary doesn't support -drive"));
+ goto cleanup;
+ }
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary doesn't support passing "
+ "drive format"));
+ goto cleanup;
+ }
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI) &&
+ def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("ACPI must be enabled in order to use UEFI"));
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buf,
+ "file=%s,if=pflash,format=raw,unit=%d",
+ loader->path, unit);
+ unit++;
+
+ if (loader->readonly) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this qemu doesn't support passing "
+ "readonly attribute"));
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buf, ",readonly=%s",
+ virTristateSwitchTypeToString(loader->readonly));
+ }
+
+ virCommandAddArg(cmd, "-drive");
+ virCommandAddArgBuffer(cmd, &buf);
+
+ if (loader->nvram) {
+ virBufferFreeAndReset(&buf);
+ virBufferAsprintf(&buf,
+ "file=%s,if=pflash,format=raw,unit=%d",
+ loader->nvram, unit);
+
+ virCommandAddArg(cmd, "-drive");
+ virCommandAddArgBuffer(cmd, &buf);
+ }
+ break;
+
+ case VIR_DOMAIN_LOADER_TYPE_LAST:
+ /* nada */
+ break;
+ }
+
+ ret = 0;
+ cleanup:
+ virBufferFreeAndReset(&buf);
+ return ret;
+}
+
qemuBuildCommandLineCallbacks buildCommandLineCallbacks = {
.qemuGetSCSIDeviceSgName = virSCSIDeviceGetSgName,
};
@@ -7525,10 +7613,8 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, "-enable-nesting");
}
- if (def->os.loader) {
- virCommandAddArg(cmd, "-bios");
- virCommandAddArg(cmd, def->os.loader->path);
- }
+ if (qemuBuildDomainLoaderCommandLine(cmd, def, qemuCaps) < 0)
+ goto error;
/* Set '-m MB' based on maxmem, because the lower 'memory' limit
* is set post-startup using the balloon driver. If balloon driver
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index e62828e..e398d2c 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -960,6 +960,10 @@ virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
rc = -1;
}
+ if (def->os.loader && def->os.loader->nvram &&
+ virSecurityDACRestoreSecurityFileLabel(def->os.loader->nvram) < 0)
+ rc = -1;
+
if (def->os.kernel &&
virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0)
rc = -1;
@@ -1036,6 +1040,10 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
return -1;
+ if (def->os.loader && def->os.loader->nvram &&
+ virSecurityDACSetOwnership(def->os.loader->nvram, user, group) < 0)
+ return -1;
+
if (def->os.kernel &&
virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
return -1;
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index c078cab..a409c19 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1911,6 +1911,10 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
mgr) < 0)
rc = -1;
+ if (def->os.loader && def->os.loader->nvram &&
+ virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.loader->nvram) < 0)
+ rc = -1;
+
if (def->os.kernel &&
virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.kernel) < 0)
rc = -1;
@@ -2294,6 +2298,10 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
mgr) < 0)
return -1;
+ if (def->os.loader && def->os.loader->nvram &&
+ virSecuritySELinuxSetFilecon(def->os.loader->nvram, data->content_context) < 0)
+ return -1;
+
if (def->os.kernel &&
virSecuritySELinuxSetFilecon(def->os.kernel, data->content_context) < 0)
return -1;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
new file mode 100644
index 0000000..b51e8f3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
@@ -0,0 +1,10 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc \
+-drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \
+-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
+-m 1024 -smp 1 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -boot c -usb \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0,format=raw \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-serial pty -device usb-tablet,id=input0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 3feb2fe..5c28253 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -642,6 +642,8 @@ mymain(void)
DO_TEST_FAILURE("reboot-timeout-enabled", NONE);
DO_TEST("bios", QEMU_CAPS_DEVICE, QEMU_CAPS_SGA);
+ DO_TEST("bios-nvram", QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DRIVE_FORMAT, QEMU_CAPS_DRIVE_READONLY);
DO_TEST("clock-utc", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE);
DO_TEST("clock-localtime", NONE);
DO_TEST("clock-localtime-basis-localtime", QEMU_CAPS_RTC);

View File

@ -0,0 +1,579 @@
From e2354416fdccb9649f080cdf912c5dc16d0eb578 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 7 Aug 2014 16:59:21 +0200
Subject: [PATCH] qemu: Automatically create NVRAM store
When using split UEFI image, it may come handy if libvirt manages per
domain _VARS file automatically. While the _CODE file is RO and can be
shared among multiple domains, you certainly don't want to do that on
the _VARS file. This latter one needs to be per domain. So at the
domain startup process, if it's determined that domain needs _VARS
file it's copied from this master _VARS file. The location of the
master file is configurable in qemu.conf.
Temporary, on per domain basis the location of master NVRAM file can
be overridden by this @template attribute I'm inventing to the
<nvram/> element. All it does is holding path to the master NVRAM file
from which local copy is created. If that's the case, the map in
qemu.conf is not consulted.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 742b08e30fd503bc992e864828cbabd7e6a099ec)
---
docs/formatdomain.html.in | 11 +-
docs/schemas/domaincommon.rng | 9 +-
libvirt.spec.in | 2 +
src/Makefile.am | 1 +
src/conf/domain_conf.c | 11 +-
src/conf/domain_conf.h | 1 +
src/qemu/libvirtd_qemu.aug | 3 +
src/qemu/qemu.conf | 14 +++
src/qemu/qemu_conf.c | 94 ++++++++++++++
src/qemu/qemu_conf.h | 5 +
src/qemu/qemu_process.c | 137 +++++++++++++++++++++
src/qemu/test_libvirtd_qemu.aug.in | 3 +
tests/domainschemadata/domain-bios-nvram-empty.xml | 40 ++++++
13 files changed, 325 insertions(+), 6 deletions(-)
create mode 100644 tests/domainschemadata/domain-bios-nvram-empty.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 757035a..a2ea758 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -103,7 +103,7 @@
&lt;os&gt;
&lt;type&gt;hvm&lt;/type&gt;
&lt;loader readonly='on' type='rom'&gt;/usr/lib/xen/boot/hvmloader&lt;/loader&gt;
- &lt;nvram&gt;/var/lib/libvirt/nvram/guest_VARS.fd&lt;/nvram&gt;
+ &lt;nvram template='/usr/share/OVMF/OVMF_VARS.fd'&gt;/var/lib/libvirt/nvram/guest_VARS.fd&lt;/nvram&gt;
&lt;boot dev='hd'/&gt;
&lt;boot dev='cdrom'/&gt;
&lt;bootmenu enable='yes' timeout='3000'/&gt;
@@ -142,9 +142,12 @@
<code>pflash</code>.</dd>
<dt><code>nvram</code></dt>
<dd>Some UEFI firmwares may want to use a non-volatile memory to store
- some variables. In the host, this is represented as a file and the
- path to the file is stored in this element. <span class="since">Since
- 1.2.8</span></dd>
+ some variables. In the host, this is represented as a file and the path
+ to the file is stored in this element. Moreover, when the domain is
+ started up libvirt copies so called master NVRAM store file defined
+ in <code>qemu.conf</code>. If needed, the <code>template</code>
+ attribute can be used to per domain override map of master NVRAM stores
+ from the config file. <span class="since">Since 1.2.8</span></dd>
<dt><code>boot</code></dt>
<dd>The <code>dev</code> attribute takes one of the values "fd", "hd",
"cdrom" or "network" and is used to specify the next boot device
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 5d9c21c..6ae940a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -263,7 +263,14 @@
</optional>
<optional>
<element name="nvram">
- <ref name="absFilePath"/>
+ <optional>
+ <attribute name="template">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
+ <optional>
+ <ref name="absFilePath"/>
+ </optional>
</element>
</optional>
<optional>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 6129f00..935b8c8 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1970,6 +1970,7 @@ exit 0
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
+%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
@@ -2072,6 +2073,7 @@ exit 0
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
+%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
diff --git a/src/Makefile.am b/src/Makefile.am
index 46e411e..fa741a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2679,6 +2679,7 @@ endif WITH_SANLOCK
if WITH_QEMU
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu/channel/target"
+ $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu/nvram"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/qemu"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/cache/libvirt/qemu"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/qemu"
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6ee5c17..84f5f1d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2023,6 +2023,7 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader)
VIR_FREE(loader->path);
VIR_FREE(loader->nvram);
+ VIR_FREE(loader->templt);
VIR_FREE(loader);
}
@@ -12768,6 +12769,7 @@ virDomainDefParseXML(xmlDocPtr xml,
goto error;
def->os.loader->nvram = virXPathString("string(./os/nvram[1])", ctxt);
+ def->os.loader->templt = virXPathString("string(./os/nvram[1]/@template)", ctxt);
}
}
@@ -17866,7 +17868,14 @@ virDomainLoaderDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " type='%s'>", type);
virBufferEscapeString(buf, "%s</loader>\n", loader->path);
- virBufferEscapeString(buf, "<nvram>%s</nvram>\n", loader->nvram);
+ if (loader->nvram || loader->templt) {
+ virBufferAddLit(buf, "<nvram");
+ virBufferEscapeString(buf, " template='%s'", loader->templt);
+ if (loader->nvram)
+ virBufferEscapeString(buf, ">%s</nvram>\n", loader->nvram);
+ else
+ virBufferAddLit(buf, "/>\n");
+ }
}
static bool
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c97a10c..3316fb6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1644,6 +1644,7 @@ struct _virDomainLoaderDef {
int readonly; /* enum virTristateBool */
virDomainLoader type;
char *nvram; /* path to non-volatile RAM */
+ char *templt; /* user override of path to master nvram */
};
void virDomainLoaderDefFree(virDomainLoaderDefPtr loader);
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index e7db7fe..62951da 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -88,6 +88,8 @@ module Libvirtd_qemu =
let log_entry = bool_entry "log_timestamp"
+ let nvram_entry = str_array_entry "nvram"
+
(* Each entry in the config is one of the following ... *)
let entry = vnc_entry
| spice_entry
@@ -100,6 +102,7 @@ module Libvirtd_qemu =
| rpc_entry
| network_entry
| log_entry
+ | nvram_entry
let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
let empty = [ label "#empty" . eol ]
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 7bbbe09..79bba36 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -487,3 +487,17 @@
# Defaults to 1.
#
#log_timestamp = 0
+
+
+# Location of master nvram file
+#
+# When a domain is configured to use UEFI instead of standard
+# BIOS it may use a separate storage for UEFI variables. If
+# that's the case libvirt creates the variable store per domain
+# using this master file as image. Each UEFI firmware can,
+# however, have different variables store. Therefore the nvram is
+# a list of strings when a single item is in form of:
+# ${PATH_TO_UEFI_FW}:${PATH_TO_UEFI_VARS}.
+# Later, when libvirt creates per domain variable store, this
+# list is searched for the master image.
+#nvram = [ "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" ]
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index e2ec54f..ac10b64 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -107,6 +107,9 @@ void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def)
VIR_FREE(def);
}
+#define VIR_QEMU_LOADER_FILE_PATH "/usr/share/OVMF/OVMF_CODE.fd"
+#define VIR_QEMU_NVRAM_FILE_PATH "/usr/share/OVMF/OVMF_VARS.fd"
+
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
{
virQEMUDriverConfigPtr cfg;
@@ -255,6 +258,15 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
cfg->logTimestamp = true;
+ if (VIR_ALLOC_N(cfg->loader, 1) < 0 ||
+ VIR_ALLOC_N(cfg->nvram, 1) < 0)
+ goto error;
+ cfg->nloader = 1;
+
+ if (VIR_STRDUP(cfg->loader[0], VIR_QEMU_LOADER_FILE_PATH) < 0 ||
+ VIR_STRDUP(cfg->nvram[0], VIR_QEMU_NVRAM_FILE_PATH) < 0)
+ goto error;
+
return cfg;
error:
@@ -305,6 +317,14 @@ static void virQEMUDriverConfigDispose(void *obj)
virStringFreeList(cfg->securityDriverNames);
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);
}
@@ -328,6 +348,43 @@ 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)
{
@@ -654,6 +711,43 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp);
+ if ((p = virConfGetValue(conf, "nvram"))) {
+ size_t len;
+ virConfValuePtr pp;
+
+ 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);
+
+ /* Calc length and check items */
+ for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
+ if (pp->type != VIR_CONF_STRING) {
+ virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+ _("nvram must be a list of strings"));
+ goto cleanup;
+ }
+ }
+
+ if (len &&
+ (VIR_ALLOC_N(cfg->loader, len) < 0 ||
+ VIR_ALLOC_N(cfg->nvram, len) < 0))
+ goto cleanup;
+ cfg->nloader = len;
+
+ for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
+ if (virQEMUDriverConfigNVRAMParse(pp->str,
+ &cfg->loader[i],
+ &cfg->nvram[i]) < 0)
+ goto cleanup;
+ }
+ }
+
ret = 0;
cleanup:
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index ae7ac56..1f521e5 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -172,6 +172,11 @@ struct _virQEMUDriverConfig {
int migrationPortMax;
bool logTimestamp;
+
+ /* Pairs of loader:nvram paths. The list is @nloader items long */
+ char **loader;
+ char **nvram;
+ size_t nloader;
};
/* Main driver state */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f68dfbe..5b120d4 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -67,6 +67,7 @@
#include "virstring.h"
#include "virhostdev.h"
#include "storage/storage_driver.h"
+#include "configmake.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3734,6 +3735,135 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
}
+static int
+qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
+ virDomainDefPtr def,
+ bool migrated)
+{
+ int ret = -1;
+ int srcFD = -1;
+ int dstFD = -1;
+ virDomainLoaderDefPtr loader = def->os.loader;
+ bool generated = false;
+ bool created = false;
+
+ /* Unless domain has RO loader of pflash type, we have
+ * nothing to do here. If the loader is RW then it's not
+ * using split code and vars feature, so no nvram file needs
+ * to be created. */
+ if (!loader || loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH ||
+ loader->readonly != VIR_TRISTATE_SWITCH_ON)
+ return 0;
+
+ /* If the nvram path is configured already, there's nothing
+ * we need to do. Unless we are starting the destination side
+ * of migration in which case nvram is configured in the
+ * domain XML but the file doesn't exist yet. Moreover, after
+ * the migration is completed, qemu will invoke a
+ * synchronization write into the nvram file so we don't have
+ * to take care about transmitting the real data on the other
+ * side. */
+ if (loader->nvram && !migrated)
+ return 0;
+
+ /* Autogenerate nvram path if needed.*/
+ if (!loader->nvram) {
+ if (virAsprintf(&loader->nvram,
+ "%s/lib/libvirt/qemu/nvram/%s_VARS.fd",
+ LOCALSTATEDIR, def->name) < 0)
+ goto cleanup;
+
+ generated = true;
+ }
+
+ if (!virFileExists(loader->nvram)) {
+ const char *master_nvram_path = loader->templt;
+ ssize_t r;
+
+ 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];
+ break;
+ }
+ }
+ }
+
+ if (!master_nvram_path) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("unable to find any master var store for "
+ "loader: %s"), loader->path);
+ goto cleanup;
+ }
+
+ if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY,
+ 0, -1, -1, 0)) < 0) {
+ virReportSystemError(-srcFD,
+ _("Failed to open file '%s'"),
+ master_nvram_path);
+ goto cleanup;
+ }
+ if ((dstFD = virFileOpenAs(loader->nvram,
+ O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR,
+ cfg->user, cfg->group, 0)) < 0) {
+ virReportSystemError(-dstFD,
+ _("Failed to create file '%s'"),
+ loader->nvram);
+ goto cleanup;
+ }
+ created = true;
+
+ do {
+ char buf[1024];
+
+ if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) {
+ virReportSystemError(errno,
+ _("Unable to read from file '%s'"),
+ master_nvram_path);
+ goto cleanup;
+ }
+
+ if (safewrite(dstFD, buf, r) < 0) {
+ virReportSystemError(errno,
+ _("Unable to write to file '%s'"),
+ loader->nvram);
+ goto cleanup;
+ }
+ } while (r);
+
+ if (VIR_CLOSE(srcFD) < 0) {
+ virReportSystemError(errno,
+ _("Unable to close file '%s'"),
+ master_nvram_path);
+ goto cleanup;
+ }
+ if (VIR_CLOSE(dstFD) < 0) {
+ virReportSystemError(errno,
+ _("Unable to close file '%s'"),
+ loader->nvram);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ /* We successfully generated the nvram path, but failed to
+ * copy the file content. Roll back. */
+ if (ret < 0) {
+ if (created)
+ unlink(loader->nvram);
+ if (generated)
+ VIR_FREE(loader->nvram);
+ }
+
+ VIR_FORCE_CLOSE(srcFD);
+ VIR_FORCE_CLOSE(dstFD);
+ return ret;
+}
+
+
int qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -3802,6 +3932,13 @@ int qemuProcessStart(virConnectPtr conn,
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup;
+ /* Some things, paths, ... are generated here and we want them to persist.
+ * Fill them in prior to setting the domain def as transient. */
+ VIR_DEBUG("Generating paths");
+
+ if (qemuPrepareNVRAM(cfg, vm->def, migrateFrom) < 0)
+ goto cleanup;
+
/* Do this upfront, so any part of the startup process can add
* runtime state to vm->def that won't be persisted. This let's us
* report implicit runtime defaults in the XML, like vnc listen/socket
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index 7796acc..d2bc2c0 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -74,3 +74,6 @@ module Test_libvirtd_qemu =
{ "migration_port_min" = "49152" }
{ "migration_port_max" = "49215" }
{ "log_timestamp" = "0" }
+{ "nvram"
+ { "1" = "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" }
+}
diff --git a/tests/domainschemadata/domain-bios-nvram-empty.xml b/tests/domainschemadata/domain-bios-nvram-empty.xml
new file mode 100644
index 0000000..e7643f3
--- /dev/null
+++ b/tests/domainschemadata/domain-bios-nvram-empty.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+ <name>test-bios</name>
+ <uuid>362d1fc1-df7d-193e-5c18-49a71bd1da66</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+ <nvram template='/usr/share/OVMF/OVMF_VARS.fd'/>
+ <boot dev='hd'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='tablet' bus='usb'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>

View File

@ -0,0 +1,53 @@
From 884ef00a28244b34d66ada97c8ddd3e7d7ea8ff1 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 11 Sep 2014 12:09:04 +0200
Subject: [PATCH] nvram: Fix permissions
I've noticed two problem with the automatically created NVRAM varstore
file. The first, even though I run qemu as root:root for some reason I
get Permission denied when trying to open the _VARS.fd file. The
problem is, the upper directory misses execute permissions, which in
combination with us dropping some capabilities result in EPERM.
The next thing is, that if I switch SELinux to enforcing mode, I get
another EPERM because the vars file is not labeled correctly. It is
passed to qemu as disk and hence should be labelled as disk. QEMU may
write to it eventually, so this is different to kernel or initrd.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 37d8c75fad297891b80086b125046ed3990eaf59)
---
libvirt.spec.in | 2 +-
src/security/security_selinux.c | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 935b8c8..3cd7b2e 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1970,7 +1970,7 @@ exit 0
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
-%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
+%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index a409c19..b9efbc5 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2298,8 +2298,11 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
mgr) < 0)
return -1;
+ /* This is different than kernel or initrd. The nvram store
+ * is really a disk, qemu can read and write to it. */
if (def->os.loader && def->os.loader->nvram &&
- virSecuritySELinuxSetFilecon(def->os.loader->nvram, data->content_context) < 0)
+ secdef && secdef->imagelabel &&
+ virSecuritySELinuxSetFilecon(def->os.loader->nvram, secdef->imagelabel) < 0)
return -1;
if (def->os.kernel &&

View File

@ -0,0 +1,148 @@
From 03c156e5d54b311291101ca21690b586222be276 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 11 Sep 2014 13:17:11 +0200
Subject: [PATCH] virDomainUndefineFlags: Allow NVRAM unlinking
When a domain is undefined, there are options to remove it's
managed save state or snapshots. However, there's another file
that libvirt creates per domain: the NVRAM variable store file.
Make sure that the file is not left behind if the domain is
undefined.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 273b6581ca8dae11e6ff40e3d13813fdbb37d41b)
---
include/libvirt/libvirt.h.in | 2 ++
src/qemu/qemu_driver.c | 20 +++++++++++++++++++-
tools/virsh-domain.c | 20 ++++++++++++++++----
tools/virsh.pod | 6 +++++-
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a64f597..8996231 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2257,6 +2257,8 @@ typedef enum {
VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = (1 << 1), /* If last use of domain,
then also remove any
snapshot metadata */
+ VIR_DOMAIN_UNDEFINE_NVRAM = (1 << 2), /* Also remove any
+ nvram file */
/* Future undefine control flags should come here. */
} virDomainUndefineFlagsValues;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 239a300..588eba4 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6402,7 +6402,8 @@ qemuDomainUndefineFlags(virDomainPtr dom,
virQEMUDriverConfigPtr cfg = NULL;
virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
- VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
+ VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
+ VIR_DOMAIN_UNDEFINE_NVRAM, -1);
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;
@@ -6451,6 +6452,23 @@ qemuDomainUndefineFlags(virDomainPtr dom,
}
}
+ if (!virDomainObjIsActive(vm) &&
+ vm->def->os.loader && vm->def->os.loader->nvram &&
+ virFileExists(vm->def->os.loader->nvram)) {
+ if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot delete inactive domain with nvram"));
+ goto cleanup;
+ }
+
+ if (unlink(vm->def->os.loader->nvram) < 0) {
+ virReportSystemError(errno,
+ _("failed to remove nvram: %s"),
+ vm->def->os.loader->nvram);
+ goto cleanup;
+ }
+ }
+
if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
goto cleanup;
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c75cd73..d84db51 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -3038,6 +3038,10 @@ static const vshCmdOptDef opts_undefine[] = {
.type = VSH_OT_BOOL,
.help = N_("remove all domain snapshot metadata, if inactive")
},
+ {.name = "nvram",
+ .type = VSH_OT_BOOL,
+ .help = N_("remove nvram file, if inactive")
+ },
{.name = NULL}
};
@@ -3060,6 +3064,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
bool snapshots_metadata = vshCommandOptBool(cmd, "snapshots-metadata");
bool wipe_storage = vshCommandOptBool(cmd, "wipe-storage");
bool remove_all_storage = vshCommandOptBool(cmd, "remove-all-storage");
+ bool nvram = vshCommandOptBool(cmd, "nvram");
/* Positive if these items exist. */
int has_managed_save = 0;
int has_snapshots_metadata = 0;
@@ -3103,6 +3108,9 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
flags |= VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA;
snapshots_safe = true;
}
+ if (nvram) {
+ flags |= VIR_DOMAIN_UNDEFINE_NVRAM;
+ }
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return false;
@@ -3293,11 +3301,15 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
* VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in 0.9.4, the
* VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA flag was not present
* until 0.9.5; skip to piecewise emulation if we couldn't prove
- * above that the new API is safe. */
- if (managed_save_safe && snapshots_safe) {
+ * above that the new API is safe.
+ * Moreover, only the newer UndefineFlags() API understands
+ * the VIR_DOMAIN_UNDEFINE_NVRAM flag. So if user has
+ * specified --nvram we must use the Flags() API. */
+ if ((managed_save_safe && snapshots_safe) || nvram) {
rc = virDomainUndefineFlags(dom, flags);
- if (rc == 0 || (last_error->code != VIR_ERR_NO_SUPPORT &&
- last_error->code != VIR_ERR_INVALID_ARG))
+ if (rc == 0 || nvram ||
+ (last_error->code != VIR_ERR_NO_SUPPORT &&
+ last_error->code != VIR_ERR_INVALID_ARG))
goto out;
vshResetLibvirtError();
}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index ea9267e..a9fad73 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2058,7 +2058,7 @@ Output the device used for the TTY console of the domain. If the information
is not available the processes will provide an exit code of 1.
=item B<undefine> I<domain> [I<--managed-save>] [I<--snapshots-metadata>]
-[ {I<--storage> B<volumes> | I<--remove-all-storage>} I<--wipe-storage>]
+[I<--nvram>] [ {I<--storage> B<volumes> | I<--remove-all-storage>} I<--wipe-storage>]
Undefine a domain. If the domain is running, this converts it to a
transient domain, without stopping it. If the domain is inactive,
@@ -2074,6 +2074,10 @@ domain. Without the flag, attempts to undefine an inactive domain with
snapshot metadata will fail. If the domain is active, this flag is
ignored.
+The I<--nvram> flag ensures no nvram (/domain/os/nvram/) file is
+left behind. If the domain has an nvram file and the flag is
+omitted, the undefine will fail.
+
The I<--storage> flag takes a parameter B<volumes>, which is a comma separated
list of volume target names or source paths of storage volumes to be removed
along with the undefined domain. Volumes can be undefined and thus removed only

View File

@ -0,0 +1,32 @@
From 2b30f114b796aee6f92eb13244f8cd42ef523bfe Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Fri, 12 Sep 2014 13:18:32 +0200
Subject: [PATCH] formatdomain: Update <loader/> example to match the rest
At the beginning when I was inventing <loader/> attributes and
<nvram/> I've introduced this @readonly attribute to the loader
element. It accepted values 'on' and 'off'. However, later, during the
review process, that has changed to 'yes' and 'no', but the example
XML snippet wasn't updated, so while the description is correct, the
example isn't.
Reported-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit dcf7d0423c1ad79e45df4ddd1cb619603cf221e7)
---
docs/formatdomain.html.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a2ea758..5081be3 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -102,7 +102,7 @@
...
&lt;os&gt;
&lt;type&gt;hvm&lt;/type&gt;
- &lt;loader readonly='on' type='rom'&gt;/usr/lib/xen/boot/hvmloader&lt;/loader&gt;
+ &lt;loader readonly='yes' type='rom'&gt;/usr/lib/xen/boot/hvmloader&lt;/loader&gt;
&lt;nvram template='/usr/share/OVMF/OVMF_VARS.fd'&gt;/var/lib/libvirt/nvram/guest_VARS.fd&lt;/nvram&gt;
&lt;boot dev='hd'/&gt;
&lt;boot dev='cdrom'/&gt;

View File

@ -0,0 +1,338 @@
From 2c4e9da2b46d55fda49b20ae48dbdd4e63209565 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Tue, 16 Sep 2014 14:47:47 +0200
Subject: [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>
(cherry picked from commit 4f76621c0edb895431a6fc30c026865dbf1c1316)
---
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>
+&lt;domainCapabilities&gt;
+ ...
+ &lt;os supported='yes'&gt;
+ &lt;loader supported='yes'&gt;
+ &lt;enum name='type'&gt;
+ &lt;value&gt;rom&lt;/value&gt;
+ &lt;value&gt;pflash&lt;/value&gt;
+ &lt;/enum&gt;
+ &lt;enum name='readonly'&gt;
+ &lt;value&gt;yes&lt;/value&gt;
+ &lt;value&gt;no&lt;/value&gt;
+ &lt;/enum&gt;
+ &lt;/loader&gt;
+ &lt;/os&gt;
+ ...
+&lt;domainCapabilities&gt;
+</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 &lt;loader/&gt;
+ element.</dd>
+
+ <dt>readonly</dt>
+ <dd>Options for the <code>readonly</code> attribute of the
+ &lt;loader/&gt; 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 c70a1a8..c999ee4 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);

View File

@ -0,0 +1,192 @@
From 103a146b669a778238485425f4eb69a5a1f5c747 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Wed, 17 Sep 2014 11:33:35 +0200
Subject: [PATCH] qemu_capabilities: Change virQEMUCapsFillDomainCaps signature
Up till now the virQEMUCapsFillDomainCaps() was type of void as
there was no way for it to fail. This is, however, going to
change in the next commit.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 2b2e4a7acff5574dd82bfbd61a638270f6be54ef)
---
src/qemu/qemu_capabilities.c | 25 ++++++++++++++++---------
src/qemu/qemu_capabilities.h | 4 ++--
src/qemu/qemu_driver.c | 3 ++-
tests/domaincapstest.c | 19 ++++++++++++-------
4 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c999ee4..d2e5f47 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3608,7 +3608,7 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps)
}
-static void
+static int
virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsLoaderPtr loader,
virArch arch)
@@ -3629,10 +3629,11 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
VIR_DOMAIN_CAPS_ENUM_SET(loader->readonly,
VIR_TRISTATE_BOOL_YES,
VIR_TRISTATE_BOOL_NO);
+ return 0;
}
-static void
+static int
virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsOSPtr os,
virArch arch)
@@ -3640,11 +3641,13 @@ virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsLoaderPtr loader = &os->loader;
os->device.supported = true;
- virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch);
+ if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0)
+ return -1;
+ return 0;
}
-static void
+static int
virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsDeviceDiskPtr disk)
{
@@ -3667,10 +3670,11 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE))
VIR_DOMAIN_CAPS_ENUM_SET(disk->bus, VIR_DOMAIN_DISK_BUS_USB);
+ return 0;
}
-static void
+static int
virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsDeviceHostdevPtr hostdev)
{
@@ -3715,10 +3719,11 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM);
}
+ return 0;
}
-void
+int
virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
virQEMUCapsPtr qemuCaps)
{
@@ -3729,7 +3734,9 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
domCaps->maxvcpus = maxvcpus;
- virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch);
- virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk);
- virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev);
+ if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 ||
+ virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 ||
+ virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0)
+ return -1;
+ return 0;
}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 0980c00..828bba3 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -324,7 +324,7 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
virQEMUCapsPtr kvmbinCaps,
virArch guestarch);
-void virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
- virQEMUCapsPtr qemuCaps);
+int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
+ virQEMUCapsPtr qemuCaps);
#endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 588eba4..9c1644c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17205,7 +17205,8 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
goto cleanup;
- virQEMUCapsFillDomainCaps(domCaps, qemuCaps);
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ goto cleanup;
ret = virDomainCapsFormat(domCaps);
cleanup:
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index f240643..0c4b09f 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -28,13 +28,13 @@
#define VIR_FROM_THIS VIR_FROM_NONE
-typedef void (*virDomainCapsFill)(virDomainCapsPtr domCaps,
- void *opaque);
+typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps,
+ void *opaque);
#define SET_ALL_BITS(x) \
memset(&(x.values), 0xff, sizeof(x.values))
-static void
+static int
fillAll(virDomainCapsPtr domCaps,
void *opaque ATTRIBUTE_UNUSED)
{
@@ -60,18 +60,20 @@ fillAll(virDomainCapsPtr domCaps,
SET_ALL_BITS(hostdev->subsysType);
SET_ALL_BITS(hostdev->capsType);
SET_ALL_BITS(hostdev->pciBackend);
+ return 0;
}
#ifdef WITH_QEMU
# include "testutilsqemu.h"
-static void
+static int
fillQemuCaps(virDomainCapsPtr domCaps,
void *opaque)
{
virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque;
- virQEMUCapsFillDomainCaps(domCaps, qemuCaps);
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ return -1;
/* The function above tries to query host's KVM & VFIO capabilities by
* calling qemuHostdevHostSupportsPassthroughLegacy() and
@@ -82,6 +84,7 @@ fillQemuCaps(virDomainCapsPtr domCaps,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO);
+ return 0;
}
#endif /* WITH_QEMU */
@@ -99,8 +102,10 @@ buildVirDomainCaps(const char *emulatorbin,
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type)))
goto cleanup;
- if (fillFunc)
- fillFunc(domCaps, opaque);
+ if (fillFunc && fillFunc(domCaps, opaque) < 0) {
+ virObjectUnref(domCaps);
+ domCaps = NULL;
+ }
cleanup:
return domCaps;

View File

@ -0,0 +1,444 @@
From 64041dc7d34d7af3fd611d194bf2ab56729a13fa Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Tue, 16 Sep 2014 19:52:54 -0400
Subject: [PATCH] domaincaps: Expose UEFI binary path, if it exists
Check to see if the UEFI binary mentioned in qemu.conf actually
exists, and if so expose it in domcapabilities like
<loader ...>
<value>/path/to/ovmf</value>
</loader>
We introduce some generic domcaps infrastructure for handling
a dynamic list of string values, it may be of use for future bits.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit f05b6a918e283929f5d837cd1668cdcdb3834b9a)
---
docs/formatdomaincaps.html.in | 6 +++
docs/schemas/domaincaps.rng | 17 +++++---
src/conf/domain_capabilities.c | 29 +++++++++++++
src/conf/domain_capabilities.h | 8 ++++
src/qemu/qemu_capabilities.c | 32 +++++++++++---
src/qemu/qemu_capabilities.h | 7 +++-
src/qemu/qemu_driver.c | 6 ++-
tests/domaincapsschemadata/domaincaps-full.xml | 2 +
.../domaincaps-qemu_1.6.50-1.xml | 1 +
tests/domaincapstest.c | 49 +++++++++++++++++++---
10 files changed, 140 insertions(+), 17 deletions(-)
diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index 34d746d..6959dfe 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -105,6 +105,7 @@
...
&lt;os supported='yes'&gt;
&lt;loader supported='yes'&gt;
+ &lt;value&gt;/usr/share/OVMF/OVMF_CODE.fd&lt;/value&gt;
&lt;enum name='type'&gt;
&lt;value&gt;rom&lt;/value&gt;
&lt;value&gt;pflash&lt;/value&gt;
@@ -122,6 +123,11 @@
<p>For the <code>loader</code> element, the following can occur:</p>
<dl>
+ <dt>value</dt>
+ <dd>List of known loader paths. Currently this is only used
+ to advertise known locations of OVMF binaries for qemu. Binaries
+ will only be listed if they actually exist on disk.</dd>
+
<dt>type</dt>
<dd>Whether loader is a typical BIOS (<code>rom</code>) or
an UEFI binary (<code>pflash</code>). This refers to
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index ad8d966..f4a555f 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -47,6 +47,9 @@
<define name='loader'>
<element name='loader'>
<ref name='supported'/>
+ <optional>
+ <ref name='value'/>
+ </optional>
<ref name='enum'/>
</element>
</define>
@@ -85,6 +88,14 @@
</element>
</define>
+ <define name='value'>
+ <zeroOrMore>
+ <element name='value'>
+ <text/>
+ </element>
+ </zeroOrMore>
+ </define>
+
<define name='supported'>
<attribute name='supported'>
<choice>
@@ -100,11 +111,7 @@
<attribute name='name'>
<text/>
</attribute>
- <zeroOrMore>
- <element name='value'>
- <text/>
- </element>
- </zeroOrMore>
+ <ref name='value'/>
</element>
</zeroOrMore>
</define>
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 5a3c8e7..7c59912 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -48,12 +48,28 @@ VIR_ONCE_GLOBAL_INIT(virDomainCaps)
static void
+virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values)
+{
+ size_t i;
+
+ if (!values || !values->values)
+ return;
+
+ for (i = 0; i < values->nvalues; i++)
+ VIR_FREE(values->values[i]);
+ VIR_FREE(values->values);
+}
+
+
+static void
virDomainCapsDispose(void *obj)
{
virDomainCapsPtr caps = obj;
VIR_FREE(caps->path);
VIR_FREE(caps->machine);
+
+ virDomainCapsStringValuesFree(&caps->os.loader.values);
}
@@ -156,6 +172,18 @@ virDomainCapsEnumFormat(virBufferPtr buf,
return ret;
}
+
+static void
+virDomainCapsStringValuesFormat(virBufferPtr buf,
+ virDomainCapsStringValuesPtr values)
+{
+ size_t i;
+
+ for (i = 0; i < values->nvalues; i++)
+ virBufferEscapeString(buf, "<value>%s</value>\n", values->values[i]);
+}
+
+
#define FORMAT_PROLOGUE(item) \
do { \
virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \
@@ -185,6 +213,7 @@ virDomainCapsLoaderFormat(virBufferPtr buf,
{
FORMAT_PROLOGUE(loader);
+ virDomainCapsStringValuesFormat(buf, &loader->values);
ENUM_PROCESS(loader, type, virDomainLoaderTypeToString);
ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString);
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 768646b..597ac75 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -37,6 +37,13 @@ struct _virDomainCapsEnum {
unsigned int values; /* Bitmask of values supported in the corresponding enum */
};
+typedef struct _virDomainCapsStringValues virDomainCapsStringValues;
+typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr;
+struct _virDomainCapsStringValues {
+ char **values; /* raw string values */
+ size_t nvalues; /* number of strings */
+};
+
typedef struct _virDomainCapsDevice virDomainCapsDevice;
typedef virDomainCapsDevice *virDomainCapsDevicePtr;
struct _virDomainCapsDevice {
@@ -47,6 +54,7 @@ typedef struct _virDomainCapsLoader virDomainCapsLoader;
typedef virDomainCapsLoader *virDomainCapsLoaderPtr;
struct _virDomainCapsLoader {
virDomainCapsDevice device;
+ virDomainCapsStringValues values; /* Info about values for the element */
virDomainCapsEnum type; /* Info about virDomainLoader */
virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */
};
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index d2e5f47..651bacd 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3611,10 +3611,30 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps)
static int
virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsLoaderPtr loader,
- virArch arch)
+ virArch arch,
+ virQEMUDriverConfigPtr cfg)
{
+ size_t i;
+
loader->device.supported = true;
+ if (VIR_ALLOC_N(loader->values.values, cfg->nloader) < 0)
+ return -1;
+
+ for (i = 0; i < cfg->nloader; i++) {
+ const char *filename = cfg->loader[i];
+
+ if (!virFileExists(filename)) {
+ VIR_DEBUG("loader filename=%s does not exist", filename);
+ continue;
+ }
+
+ if (VIR_STRDUP(loader->values.values[loader->values.nvalues],
+ filename) < 0)
+ return -1;
+ loader->values.nvalues++;
+ }
+
VIR_DOMAIN_CAPS_ENUM_SET(loader->type,
VIR_DOMAIN_LOADER_TYPE_ROM);
@@ -3636,12 +3656,13 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
static int
virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsOSPtr os,
- virArch arch)
+ virArch arch,
+ virQEMUDriverConfigPtr cfg)
{
virDomainCapsLoaderPtr loader = &os->loader;
os->device.supported = true;
- if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0)
+ if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch, cfg) < 0)
return -1;
return 0;
}
@@ -3725,7 +3746,8 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps,
int
virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
- virQEMUCapsPtr qemuCaps)
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverConfigPtr cfg)
{
virDomainCapsOSPtr os = &domCaps->os;
virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
@@ -3734,7 +3756,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
domCaps->maxvcpus = maxvcpus;
- if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 ||
+ if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch, cfg) < 0 ||
virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 ||
virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0)
return -1;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 828bba3..cf69e59 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -324,7 +324,12 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
virQEMUCapsPtr kvmbinCaps,
virArch guestarch);
+/* Forward declaration */
+typedef struct _virQEMUDriverConfig virQEMUDriverConfig;
+typedef virQEMUDriverConfig *virQEMUDriverConfigPtr;
+
int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
- virQEMUCapsPtr qemuCaps);
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverConfigPtr cfg);
#endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9c1644c..0d895c6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17133,12 +17133,15 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
int virttype; /* virDomainVirtType */
virDomainCapsPtr domCaps = NULL;
int arch = virArchFromHost(); /* virArch */
+ virQEMUDriverConfigPtr cfg = NULL;
virCheckFlags(0, ret);
if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
return ret;
+ cfg = virQEMUDriverGetConfig(driver);
+
if (qemuHostdevHostSupportsPassthroughLegacy())
virttype = VIR_DOMAIN_VIRT_KVM;
else
@@ -17205,11 +17208,12 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
goto cleanup;
- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
goto cleanup;
ret = virDomainCapsFormat(domCaps);
cleanup:
+ virObjectUnref(cfg);
virObjectUnref(domCaps);
virObjectUnref(qemuCaps);
return ret;
diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml
index 9722772..96202bc 100644
--- a/tests/domaincapsschemadata/domaincaps-full.xml
+++ b/tests/domaincapsschemadata/domaincaps-full.xml
@@ -6,6 +6,8 @@
<vcpu max='255'/>
<os supported='yes'>
<loader supported='yes'>
+ <value>/foo/bar</value>
+ <value>/tmp/my_path</value>
<enum name='type'>
<value>rom</value>
<value>pflash</value>
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
index 568cecb..346ef65 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
@@ -5,6 +5,7 @@
<arch>x86_64</arch>
<os supported='yes'>
<loader supported='yes'>
+ <value>/usr/share/OVMF/OVMF_CODE.fd</value>
<enum name='type'>
<value>rom</value>
<value>pflash</value>
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 0c4b09f..8543963 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -34,6 +34,27 @@ typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps,
#define SET_ALL_BITS(x) \
memset(&(x.values), 0xff, sizeof(x.values))
+static int ATTRIBUTE_SENTINEL
+fillStringValues(virDomainCapsStringValuesPtr values, ...)
+{
+ int ret = 0;
+ va_list list;
+ const char *str;
+
+ va_start(list, values);
+ while ((str = va_arg(list, const char *))) {
+ if (VIR_REALLOC_N(values->values, values->nvalues + 1) < 0 ||
+ VIR_STRDUP(values->values[values->nvalues], str) < 0) {
+ ret = -1;
+ break;
+ }
+ values->nvalues++;
+ }
+ va_end(list);
+
+ return ret;
+}
+
static int
fillAll(virDomainCapsPtr domCaps,
void *opaque ATTRIBUTE_UNUSED)
@@ -49,6 +70,11 @@ fillAll(virDomainCapsPtr domCaps,
loader->device.supported = true;
SET_ALL_BITS(loader->type);
SET_ALL_BITS(loader->readonly);
+ if (fillStringValues(&loader->values,
+ "/foo/bar",
+ "/tmp/my_path",
+ NULL) < 0)
+ return -1;
disk->device.supported = true;
SET_ALL_BITS(disk->diskDevice);
@@ -66,13 +92,21 @@ fillAll(virDomainCapsPtr domCaps,
#ifdef WITH_QEMU
# include "testutilsqemu.h"
+
+struct fillQemuCapsData {
+ virQEMUCapsPtr qemuCaps;
+ virQEMUDriverConfigPtr cfg;
+};
+
static int
fillQemuCaps(virDomainCapsPtr domCaps,
void *opaque)
{
- virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque;
+ struct fillQemuCapsData *data = (struct fillQemuCapsData *) opaque;
+ virQEMUCapsPtr qemuCaps = data->qemuCaps;
+ virQEMUDriverConfigPtr cfg = data->cfg;
- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
return -1;
/* The function above tries to query host's KVM & VFIO capabilities by
@@ -97,7 +131,7 @@ buildVirDomainCaps(const char *emulatorbin,
virDomainCapsFill fillFunc,
void *opaque)
{
- virDomainCapsPtr domCaps;
+ virDomainCapsPtr domCaps, ret = NULL;
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type)))
goto cleanup;
@@ -107,8 +141,9 @@ buildVirDomainCaps(const char *emulatorbin,
domCaps = NULL;
}
+ ret = domCaps;
cleanup:
- return domCaps;
+ return ret;
}
struct test_virDomainCapsFormatData {
@@ -182,13 +217,16 @@ mymain(void)
#ifdef WITH_QEMU
+ virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false);
+
# define DO_TEST_QEMU(Filename, QemuCapsFile, Emulatorbin, Machine, Arch, Type, ...) \
do { \
const char *capsPath = abs_srcdir "/qemucapabilitiesdata/" QemuCapsFile ".caps"; \
virQEMUCapsPtr qemuCaps = qemuTestParseCapabilities(capsPath); \
+ struct fillQemuCapsData fillData = {.qemuCaps = qemuCaps, .cfg = cfg}; \
struct test_virDomainCapsFormatData data = {.filename = Filename, \
.emulatorbin = Emulatorbin, .machine = Machine, .arch = Arch, \
- .type = Type, .fillFunc = fillQemuCaps, .opaque = qemuCaps}; \
+ .type = Type, .fillFunc = fillQemuCaps, .opaque = &fillData}; \
if (!qemuCaps) { \
fprintf(stderr, "Unable to build qemu caps from %s\n", capsPath); \
ret = -1; \
@@ -199,6 +237,7 @@ mymain(void)
DO_TEST_QEMU("qemu_1.6.50-1", "caps_1.6.50-1", "/usr/bin/qemu-system-x86_64",
"pc-1.2", VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_KVM);
+ virObjectUnref(cfg);
#endif /* WITH_QEMU */
return ret;

View File

@ -0,0 +1,40 @@
From 6fcd1ae861279589172783c4937367685469f265 Mon Sep 17 00:00:00 2001
From: Michal Privoznik <mprivozn@redhat.com>
Date: Wed, 17 Sep 2014 17:17:03 +0200
Subject: [PATCH] domaincapstest: Run cleanly on systems missing OVMF firmware
As of f05b6a918e28 the test produces the list of paths that can
be passed to <loader/> and libvirt knows about them. However,
during the process of generating the list the paths are checked
for their presence. This may produce different results on
different systems. Therefore, the path - if missing - is
added to pretend it's there.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b3f42da6b77644107bcbaf720d7ed9cef5c798a2)
---
tests/domaincapstest.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 8543963..067ad4d 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -118,6 +118,17 @@ fillQemuCaps(virDomainCapsPtr domCaps,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO);
+
+ /* Moreover, as of f05b6a918e28 we are expecting to see
+ * OVMF_CODE.fd file which may not exists everywhere. */
+ if (!domCaps->os.loader.values.nvalues) {
+ virDomainCapsLoaderPtr loader = &domCaps->os.loader;
+
+ if (fillStringValues(&loader->values,
+ "/usr/share/OVMF/OVMF_CODE.fd",
+ NULL) < 0)
+ return -1;
+ }
return 0;
}
#endif /* WITH_QEMU */

View File

@ -366,7 +366,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 1.2.8
Release: 3%{?dist}%{?extra_release}
Release: 4%{?dist}%{?extra_release}
License: LGPLv2+
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@ -382,7 +382,6 @@ Source: http://libvirt.org/sources/%{?mainturl}libvirt-%{version}.tar.gz
Patch0001: 0001-network-try-to-eliminate-default-network-conflict-du.patch
Patch0002: 0002-network-detect-conflicting-route-even-if-it-is-the-f.patch
# Fix directory creation at session daemon startup (bz #1139672)
# (Patch 5 is posted but not in git as of 2014-09-15)
Patch0003: 0003-rpc-reformat-the-flow-to-make-a-bit-more-sense.patch
Patch0004: 0004-remove-redundant-pidfile-path-constructions.patch
Patch0005: 0005-util-fix-potential-leak-in-error-codepath.patch
@ -393,6 +392,19 @@ Patch0007: 0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch
Patch0008: 0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch
# Fix preun script (bz #1142367)
Patch0009: 0009-spec-Fix-preun-script-for-daemon.patch
# Don't mess up labelling of /dev/net/tun (bz #1141879)
Patch0010: 0010-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-t.patch
# pflash/nvram support for UEFI/OVMF
Patch0011: 0011-conf-Extend-loader-and-introduce-nvram.patch
Patch0012: 0012-qemu-Implement-extended-loader-and-nvram.patch
Patch0013: 0013-qemu-Automatically-create-NVRAM-store.patch
Patch0014: 0014-nvram-Fix-permissions.patch
Patch0015: 0015-virDomainUndefineFlags-Allow-NVRAM-unlinking.patch
Patch0016: 0016-formatdomain-Update-loader-example-to-match-the-rest.patch
Patch0017: 0017-domaincaps-Expose-UEFI-capability.patch
Patch0018: 0018-qemu_capabilities-Change-virQEMUCapsFillDomainCaps-s.patch
Patch0019: 0019-domaincaps-Expose-UEFI-binary-path-if-it-exists.patch
Patch0020: 0020-domaincapstest-Run-cleanly-on-systems-missing-OVMF-f.patch
%if %{with_libvirtd}
Requires: libvirt-daemon = %{version}-%{release}
@ -1223,7 +1235,6 @@ driver
%patch0001 -p1
%patch0002 -p1
# Fix directory creation at session daemon startup (bz #1139672)
# (Patch 5 is posted but not in git as of 2014-09-15)
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
@ -1234,6 +1245,19 @@ driver
%patch0008 -p1
# Fix preun script (bz #1142367)
%patch0009 -p1
# Don't mess up labelling of /dev/net/tun (bz #1141879)
%patch0010 -p1
# pflash/nvram support for UEFI/OVMF
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%patch0016 -p1
%patch0017 -p1
%patch0018 -p1
%patch0019 -p1
%patch0020 -p1
%build
%if ! %{with_xen}
@ -2004,6 +2028,7 @@ exit 0
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
@ -2106,6 +2131,7 @@ exit 0
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
@ -2309,6 +2335,10 @@ exit 0
%doc examples/systemtap
%changelog
* Thu Sep 18 2014 Cole Robinson <crobinso@redhat.com> - 1.2.8-4
- Don't mess up labelling of /dev/net/tun (bz #1141879)
- pflash/nvram support for UEFI/OVMF
* Wed Sep 17 2014 Cole Robinson <crobinso@redhat.com> - 1.2.8-3
- Fix preun script (bz #1142367)