--- /dev/null
+a0c72cd89f702fe23974bc4e14f73756ad721571 SOURCES/libvirt-1.1.1.tar.gz
+++ /dev/null
-The master branch has no content
-
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
-
-If you find this file in a distro specific branch, it means that no content has been checked in yet
--- /dev/null
+From 640ff93b2835c02f2f317912e7e2abb20cf3c35d Mon Sep 17 00:00:00 2001
+Message-Id: <640ff93b2835c02f2f317912e7e2abb20cf3c35d.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 31 Jul 2013 19:48:17 +0100
+Subject: [PATCH] Add APIs for formatting systemd slice/scope names
+
+https://bugzilla.redhat.com/show_bug.cgi?id=980929
+
+There are some interesting escaping rules to consider when dealing
+with systemd slice/scope names. Thus it is helpful to have APIs
+for formatting names
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+
+(cherry picked from commit 4574b475df830da437aa6384fd1452cecbb4b7d2)
+---
+ src/libvirt_private.syms | 2 ++
+ src/util/virsystemd.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++--
+ src/util/virsystemd.h | 5 +++
+ tests/virsystemdtest.c | 49 ++++++++++++++++++++++++++
+ 4 files changed, 145 insertions(+), 2 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index d9615ea..0247a46 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1935,6 +1935,8 @@ virSysinfoSetup;
+
+ # util/virsystemd.h
+ virSystemdCreateMachine;
++virSystemdMakeScopeName;
++virSystemdMakeSliceName;
+
+
+ # util/virthread.h
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index 11d1153..251b846 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -27,9 +27,96 @@
+ #include "viralloc.h"
+ #include "virutil.h"
+ #include "virlog.h"
++#include "virerror.h"
+
+ #define VIR_FROM_THIS VIR_FROM_SYSTEMD
+
++
++static void virSystemdEscapeName(virBufferPtr buf,
++ const char *name)
++{
++ static const char hextable[16] = "0123456789abcdef";
++
++#define ESCAPE(c) \
++ do { \
++ virBufferAddChar(buf, '\\'); \
++ virBufferAddChar(buf, 'x'); \
++ virBufferAddChar(buf, hextable[(c >> 4) & 15]); \
++ virBufferAddChar(buf, hextable[c & 15]); \
++ } while (0)
++
++#define VALID_CHARS \
++ "0123456789" \
++ "abcdefghijklmnopqrstuvwxyz" \
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
++ ":-_.\\"
++
++ if (*name == '.') {
++ ESCAPE(*name);
++ name++;
++ }
++
++ while (*name) {
++ if (*name == '/')
++ virBufferAddChar(buf, '-');
++ else if (*name == '-' ||
++ *name == '\\' ||
++ !strchr(VALID_CHARS, *name))
++ ESCAPE(*name);
++ else
++ virBufferAddChar(buf, *name);
++ name++;
++ }
++
++#undef ESCAPE
++#undef VALID_CHARS
++}
++
++
++char *virSystemdMakeScopeName(const char *name,
++ const char *drivername,
++ const char *partition)
++{
++ virBuffer buf = VIR_BUFFER_INITIALIZER;
++
++ if (*partition == '/')
++ partition++;
++
++ virSystemdEscapeName(&buf, partition);
++ virBufferAddChar(&buf, '-');
++ virSystemdEscapeName(&buf, drivername);
++ virBufferAddLit(&buf, "\\x2d");
++ virSystemdEscapeName(&buf, name);
++ virBufferAddLit(&buf, ".scope");
++
++ if (virBufferError(&buf)) {
++ virReportOOMError();
++ return NULL;
++ }
++
++ return virBufferContentAndReset(&buf);
++}
++
++
++char *virSystemdMakeSliceName(const char *partition)
++{
++ virBuffer buf = VIR_BUFFER_INITIALIZER;
++
++ if (*partition == '/')
++ partition++;
++
++ virSystemdEscapeName(&buf, partition);
++ virBufferAddLit(&buf, ".slice");
++
++ if (virBufferError(&buf)) {
++ virReportOOMError();
++ return NULL;
++ }
++
++ return virBufferContentAndReset(&buf);
++}
++
++
+ /**
+ * virSystemdCreateMachine:
+ * @name: driver unique name of the machine
+@@ -75,8 +162,8 @@ int virSystemdCreateMachine(const char *name,
+ goto cleanup;
+
+ if (partition) {
+- if (virAsprintf(&slicename, "%s.slice", partition) < 0)
+- goto cleanup;
++ if (!(slicename = virSystemdMakeSliceName(partition)))
++ goto cleanup;
+ } else {
+ if (VIR_STRDUP(slicename, "") < 0)
+ goto cleanup;
+diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h
+index 9ca4e0b..414ae5a 100644
+--- a/src/util/virsystemd.h
++++ b/src/util/virsystemd.h
+@@ -24,6 +24,11 @@
+
+ # include "internal.h"
+
++char *virSystemdMakeScopeName(const char *name,
++ const char *drivername,
++ const char *slicename);
++char *virSystemdMakeSliceName(const char *partition);
++
+ int virSystemdCreateMachine(const char *name,
+ const char *drivername,
+ bool privileged,
+diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c
+index bcf3ad3..a9c6d32 100644
+--- a/tests/virsystemdtest.c
++++ b/tests/virsystemdtest.c
+@@ -138,6 +138,38 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED)
+ return 0;
+ }
+
++
++struct testScopeData {
++ const char *name;
++ const char *partition;
++ const char *expected;
++};
++
++static int
++testScopeName(const void *opaque)
++{
++ const struct testScopeData *data = opaque;
++ int ret = -1;
++ char *actual = NULL;
++
++ if (!(actual = virSystemdMakeScopeName(data->name,
++ "lxc",
++ data->partition)))
++ goto cleanup;
++
++ if (STRNEQ(actual, data->expected)) {
++ fprintf(stderr, "Expected '%s' but got '%s'\n",
++ data->expected, actual);
++ goto cleanup;
++ }
++
++ ret = 0;
++
++ cleanup:
++ VIR_FREE(actual);
++ return ret;
++}
++
+ static int
+ mymain(void)
+ {
+@@ -152,6 +184,23 @@ mymain(void)
+ if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
+ ret = -1;
+
++#define TEST_SCOPE(name, partition, unitname) \
++ do { \
++ struct testScopeData data = { \
++ name, partition, unitname \
++ }; \
++ if (virtTestRun("Test scopename", 1, testScopeName, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
++ TEST_SCOPE("demo", "/machine", "machine-lxc\\x2ddemo.scope");
++ TEST_SCOPE("demo-name", "/machine", "machine-lxc\\x2ddemo\\x2dname.scope");
++ TEST_SCOPE("demo!name", "/machine", "machine-lxc\\x2ddemo\\x21name.scope");
++ TEST_SCOPE(".demo", "/machine", "machine-lxc\\x2d\\x2edemo.scope");
++ TEST_SCOPE("demo", "/machine/eng-dept", "machine-eng\\x2ddept-lxc\\x2ddemo.scope");
++ TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff",
++ "machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope");
++
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 69da992ba2381c0a8e49c5c05c3f8f5d3f0b5407 Mon Sep 17 00:00:00 2001
+Message-Id: <69da992ba2381c0a8e49c5c05c3f8f5d3f0b5407.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:35:59 +0100
+Subject: [PATCH] Add a man page for virtlockd daemon
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=991494
+
+Create a virtlockd.pod.in file containing the man page
+content for virtlockd.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 6ff0cffd55dae2fa07e6e8dc844312a87946678c)
+---
+ .gitignore | 2 +
+ libvirt.spec.in | 1 +
+ src/Makefile.am | 24 ++++++-
+ src/locking/virtlockd.pod.in | 158 +++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 184 insertions(+), 1 deletion(-)
+ create mode 100644 src/locking/virtlockd.pod.in
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 62e427e..5a7e05a 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1997,9 +1997,31 @@ virtlockd.init: locking/virtlockd.init.in $(top_builddir)/config.status
+ chmod a+x $@-t && \
+ mv $@-t $@
+
++POD2MAN = pod2man -c "Virtualization Support" \
++ -r "$(PACKAGE)-$(VERSION)" -s 8
+
++$(srcdir)/virtlockd.8.in: locking/virtlockd.pod.in $(top_srcdir)/configure.ac
++ $(AM_V_GEN)$(POD2MAN) --name VIRTLOCKD $< $@ \
++ && if grep 'POD ERROR' $@ ; then rm $@; exit 1; fi
++
++virtlockd.8: $(srcdir)/virtlockd.8.in
++ $(AM_V_GEN)sed \
++ -e 's|[@]sysconfdir[@]|$(sysconfdir)|g' \
++ -e 's|[@]localstatedir[@]|$(localstatedir)|g' \
++ < $< > $@-t && \
++ mv $@-t $@
++
++man8_MANS = virtlockd.8
++
++MAINTAINERCLEANFILES += $(srcdir)/virtlockd.8.in
++
++EXTRA_DIST += \
++ locking/virtlockd.service.in \
++ locking/virtlockd.socket.in \
++ locking/virtlockd.pod.in \
++ virtlockd.8.in \
++ $(NULL)
+
+-EXTRA_DIST += locking/virtlockd.service.in locking/virtlockd.socket.in
+
+ if WITH_LIBVIRTD
+ if LIBVIRT_INIT_SCRIPT_SYSTEMD
+diff --git a/src/locking/virtlockd.pod.in b/src/locking/virtlockd.pod.in
+new file mode 100644
+index 0000000..f5748ca
+--- /dev/null
++++ b/src/locking/virtlockd.pod.in
+@@ -0,0 +1,158 @@
++=head1 NAME
++
++virtlockd - libvirt lock management daemon
++
++=head1 SYNOPSIS
++
++B<virtlockd> [ -dv ] [ -f config_file ] [ -p pid_file ]
++
++B<virtlockd> --version
++
++=head1 DESCRIPTION
++
++The B<virtlockd> program is a server side daemon component of the libvirt
++virtualization management system that is used to manage locks held against
++virtual machine resources, such as their disks.
++
++This daemon is not used directly by libvirt client applications, rather it
++is called on their behalf by B<libvirtd>. By maintaining the locks in a
++standalone daemon, the main libvirtd daemon can be restarted without risk
++of losing locks. The B<virtlockd> daemon has the ability to re-exec()
++itself upon receiving SIGUSR1, to allow live upgrades without downtime.
++
++The virtlockd daemon listens for requests on a local Unix domain socket.
++
++=head1 OPTIONS
++
++=over
++
++=item B<-d, --daemon>
++
++Run as a daemon and write PID file.
++
++=item B<-f, --config> I<FILE>
++
++Use this configuration file, overriding the default value.
++
++=item B<-p, --pid-file> I<FILE>
++
++Use this name for the PID file, overriding the default value.
++
++=item B<-v, --verbose>
++
++Enable output of verbose messages.
++
++=item B< --version>
++
++Display version information then exit.
++
++=back
++
++=head1 SIGNALS
++
++On receipt of B<SIGUSR1> virtlockd will re-exec() its binary, while
++maintaining all current locks and clients. This allows for live
++upgrades of the virtlockd service.
++
++=head1 FILES
++
++=head2 When run as B<root>.
++
++=over
++
++=item F<SYSCONFDIR/virtlockd.conf>
++
++The default configuration file used by virtlockd, unless overridden on the
++command line using the B<-f>|B<--config> option.
++
++=item F<LOCALSTATEDIR/run/libvirt/virtlockd-sock>
++
++The sockets libvirtd will use.
++
++=item F<LOCALSTATEDIR/run/virtlockd.pid>
++
++The PID file to use, unless overridden by the B<-p>|B<--pid-file> option.
++
++=back
++
++=head2 When run as B<non-root>.
++
++=over
++
++=item F<$XDG_CONFIG_HOME/virtlockd.conf>
++
++The default configuration file used by libvirtd, unless overridden on the
++command line using the B<-f>|B<--config> option.
++
++=item F<$XDG_RUNTIME_DIR/libvirt/virtlockd-sock>
++
++The socket libvirtd will use.
++
++=item F<$XDG_RUNTIME_DIR/libvirt/virtlockd.pid>
++
++The PID file to use, unless overridden by the B<-p>|B<--pid-file> option.
++
++=item If $XDG_CONFIG_HOME is not set in your environment, libvirtd will use F<$HOME/.config>
++
++=item If $XDG_RUNTIME_DIR is not set in your environment, libvirtd will use F<$HOME/.cache>
++
++=back
++
++=head1 EXAMPLES
++
++To retrieve the version of virtlockd:
++
++ # virtlockd --version
++ virtlockd (libvirt) 1.1.1
++ #
++
++To start virtlockd, instructing it to daemonize and create a PID file:
++
++ # virtlockd -d
++ # ls -la LOCALSTATEDIR/run/virtlockd.pid
++ -rw-r--r-- 1 root root 6 Jul 9 02:40 LOCALSTATEDIR/run/virtlockd.pid
++ #
++
++=head1 BUGS
++
++Please report all bugs you discover. This should be done via either:
++
++=over
++
++=item a) the mailing list
++
++L<http://libvirt.org/contact.html>
++
++=item or,
++
++B<>
++
++=item b) the bug tracker
++
++L<http://libvirt.org/bugs.html>
++
++=item Alternatively, you may report bugs to your software distributor / vendor.
++
++=back
++
++=head1 AUTHORS
++
++Please refer to the AUTHORS file distributed with libvirt.
++
++=head1 COPYRIGHT
++
++Copyright (C) 2006-2013 Red Hat, Inc., and the authors listed in the
++libvirt AUTHORS file.
++
++=head1 LICENSE
++
++virtlockd is distributed under the terms of the GNU LGPL v2.1+.
++This is free software; see the source for copying conditions. There
++is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
++PURPOSE
++
++=head1 SEE ALSO
++
++L<libvirtd(8)>, L<http://www.libvirt.org/>
++
++=cut
+--
+1.8.3.2
+
--- /dev/null
+From bc84df329033b0162efd5e4fd2753666d44be3ee Mon Sep 17 00:00:00 2001
+Message-Id: <bc84df329033b0162efd5e4fd2753666d44be3ee.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:18 +0100
+Subject: [PATCH] Add a method for closing the dbus system bus connection
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=998365
+
+If the dbus system bus connection is marked as private, then
+allow it to be closed.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 489beb0aba5aad0e5423e123db9a7ab67421ca48)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 1 +
+ src/util/virdbus.c | 12 ++++++++++++
+ src/util/virdbus.h | 1 +
+ 3 files changed, 14 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index c91a9f9..5e4de67 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1292,6 +1292,7 @@ virConfWriteMem;
+
+ # util/virdbus.h
+ virDBusCallMethod;
++virDBusCloseSystemBus;
+ virDBusGetSessionBus;
+ virDBusGetSystemBus;
+ virDBusHasSystemBus;
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index bcc5b1c..da69430 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -122,6 +122,14 @@ virDBusHasSystemBus(void)
+ }
+
+
++void virDBusCloseSystemBus(void)
++{
++ if (systembus && !sharedBus) {
++ dbus_connection_close(systembus);
++ systembus = NULL;
++ }
++}
++
+ static void virDBusSessionBusInit(void)
+ {
+ sessionbus = virDBusBusInit(DBUS_BUS_SESSION, &sessiondbuserr);
+@@ -1293,6 +1301,10 @@ virDBusHasSystemBus(void)
+ return false;
+ }
+
++void virDBusCloseSystemBus(void)
++{
++ /* nothing */
++}
+
+ DBusConnection *virDBusGetSessionBus(void)
+ {
+diff --git a/src/util/virdbus.h b/src/util/virdbus.h
+index 125a405..979c566 100644
+--- a/src/util/virdbus.h
++++ b/src/util/virdbus.h
+@@ -35,6 +35,7 @@ void virDBusSetSharedBus(bool shared);
+
+ DBusConnection *virDBusGetSystemBus(void);
+ bool virDBusHasSystemBus(void);
++void virDBusCloseSystemBus(void);
+ DBusConnection *virDBusGetSessionBus(void);
+
+ int virDBusCallMethod(DBusConnection *conn,
+--
+1.8.3.2
+
--- /dev/null
+From 07ed15bbbd7c0fc2c946620f15f1963882144633 Mon Sep 17 00:00:00 2001
+Message-Id: <07ed15bbbd7c0fc2c946620f15f1963882144633.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:36:00 +0100
+Subject: [PATCH] Add an example config file for virtlockd
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=991494
+
+The virtlockd daemon supports an /etc/libvirt/virtlockd.conf
+config file, but we never installed a default config, nor
+created any augeas scripts. This change addresses that omission.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 38550ae80978d590a0dccf79108ec96180771fe1)
+---
+ .gitignore | 1 +
+ libvirt.spec.in | 3 ++
+ src/Makefile.am | 20 ++++++++++++-
+ src/locking/test_virtlockd.aug.in | 12 ++++++++
+ src/locking/virtlockd.aug | 44 ++++++++++++++++++++++++++++
+ src/locking/virtlockd.conf | 60 +++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 139 insertions(+), 1 deletion(-)
+ create mode 100644 src/locking/test_virtlockd.aug.in
+ create mode 100644 src/locking/virtlockd.aug
+ create mode 100644 src/locking/virtlockd.conf
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 5a7e05a..12ca204 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1586,7 +1586,7 @@ check-local: check-augeas
+ $(NULL)
+
+ check-augeas: check-augeas-qemu check-augeas-lxc check-augeas-sanlock \
+- check-augeas-lockd
++ check-augeas-lockd check-augeas-virtlockd
+
+ AUG_GENTEST = $(PERL) $(top_srcdir)/build-aux/augeas-gentest.pl
+ EXTRA_DIST += $(top_srcdir)/build-aux/augeas-gentest.pl
+@@ -1634,11 +1634,20 @@ test_libvirt_lockd.aug: locking/test_libvirt_lockd.aug.in \
+ locking/qemu-lockd.conf $(AUG_GENTEST)
+ $(AM_V_GEN)$(AUG_GENTEST) locking/qemu-lockd.conf $< $@
+
++test_virtlockd.aug: locking/test_virtlockd.aug.in \
++ locking/virtlockd.conf $(AUG_GENTEST)
++ $(AM_V_GEN)$(AUG_GENTEST) locking/virtlockd.conf $< $@
++
+ check-augeas-lockd: test_libvirt_lockd.aug
+ $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
+ '$(AUGPARSE)' -I $(srcdir)/locking test_libvirt_lockd.aug; \
+ fi
+
++check-augeas-virtlockd: test_virtlockd.aug
++ $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
++ '$(AUGPARSE)' -I $(srcdir)/locking test_virtlockd.aug; \
++ fi
++
+ #
+ # Build our version script. This is composed of three parts:
+ #
+@@ -2013,6 +2022,12 @@ virtlockd.8: $(srcdir)/virtlockd.8.in
+
+ man8_MANS = virtlockd.8
+
++conf_DATA += locking/virtlockd.conf
++
++augeas_DATA += locking/virtlockd.aug
++augeastest_DATA += test_virtlockd.aug
++
++CLEANFILES += test_virtlockd.aug
+ MAINTAINERCLEANFILES += $(srcdir)/virtlockd.8.in
+
+ EXTRA_DIST += \
+@@ -2020,6 +2035,9 @@ EXTRA_DIST += \
+ locking/virtlockd.socket.in \
+ locking/virtlockd.pod.in \
+ virtlockd.8.in \
++ locking/virtlockd.aug \
++ locking/virtlockd.conf \
++ locking/test_virtlockd.aug.in \
+ $(NULL)
+
+
+diff --git a/src/locking/test_virtlockd.aug.in b/src/locking/test_virtlockd.aug.in
+new file mode 100644
+index 0000000..dcd47c3
+--- /dev/null
++++ b/src/locking/test_virtlockd.aug.in
+@@ -0,0 +1,12 @@
++module Test_virtlockd =
++ let conf = "log_level = 3
++log_filters=\"3:remote 4:event\"
++log_outputs=\"3:syslog:libvirtd\"
++log_buffer_size = 64
++"
++
++ test Libvirtd.lns get conf =
++ { "log_level" = "3" }
++ { "log_filters" = "3:remote 4:event" }
++ { "log_outputs" = "3:syslog:libvirtd" }
++ { "log_buffer_size" = "64" }
+diff --git a/src/locking/virtlockd.aug b/src/locking/virtlockd.aug
+new file mode 100644
+index 0000000..9d20e72
+--- /dev/null
++++ b/src/locking/virtlockd.aug
+@@ -0,0 +1,44 @@
++(* /etc/libvirt/libvirtd.conf *)
++
++module Libvirtd =
++ autoload xfm
++
++ let eol = del /[ \t]*\n/ "\n"
++ let value_sep = del /[ \t]*=[ \t]*/ " = "
++ let indent = del /[ \t]*/ ""
++
++ let array_sep = del /,[ \t\n]*/ ", "
++ let array_start = del /\[[ \t\n]*/ "[ "
++ let array_end = del /\]/ "]"
++
++ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
++ let bool_val = store /0|1/
++ let int_val = store /[0-9]+/
++ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
++ let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
++
++ let str_entry (kw:string) = [ key kw . value_sep . str_val ]
++ let bool_entry (kw:string) = [ key kw . value_sep . bool_val ]
++ let int_entry (kw:string) = [ key kw . value_sep . int_val ]
++ let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
++
++
++ (* Config entry grouped by function - same order as example config *)
++ let logging_entry = int_entry "log_level"
++ | str_entry "log_filters"
++ | str_entry "log_outputs"
++ | int_entry "log_buffer_size"
++
++ (* Each enty in the config is one of the following three ... *)
++ let entry = logging_entry
++ let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
++ let empty = [ label "#empty" . eol ]
++
++ let record = indent . entry . eol
++
++ let lns = ( record | comment | empty ) *
++
++ let filter = incl "/etc/libvirt/virtlockd.conf"
++ . Util.stdexcl
++
++ let xfm = transform lns filter
+diff --git a/src/locking/virtlockd.conf b/src/locking/virtlockd.conf
+new file mode 100644
+index 0000000..b6450b4
+--- /dev/null
++++ b/src/locking/virtlockd.conf
+@@ -0,0 +1,60 @@
++# Master virtlockd daemon configuration file
++#
++
++#################################################################
++#
++# Logging controls
++#
++
++# Logging level: 4 errors, 3 warnings, 2 information, 1 debug
++# basically 1 will log everything possible
++#log_level = 3
++
++# Logging filters:
++# A filter allows to select a different logging level for a given category
++# of logs
++# The format for a filter is one of:
++# x:name
++# x:+name
++# where name is a string which is matched against source file name,
++# e.g., "remote", "qemu", or "util/json", the optional "+" prefix
++# tells libvirt to log stack trace for each message matching name,
++# and x is the minimal level where matching messages should be logged:
++# 1: DEBUG
++# 2: INFO
++# 3: WARNING
++# 4: ERROR
++#
++# Multiple filter can be defined in a single @filters, they just need to be
++# separated by spaces.
++#
++# e.g. to only get warning or errors from the remote layer and only errors
++# from the event layer:
++#log_filters="3:remote 4:event"
++
++# Logging outputs:
++# An output is one of the places to save logging information
++# The format for an output can be:
++# x:stderr
++# output goes to stderr
++# x:syslog:name
++# use syslog for the output and use the given name as the ident
++# x:file:file_path
++# output to a file, with the given filepath
++# In all case the x prefix is the minimal level, acting as a filter
++# 1: DEBUG
++# 2: INFO
++# 3: WARNING
++# 4: ERROR
++#
++# Multiple output can be defined, they just need to be separated by spaces.
++# e.g. to log all warnings and errors to syslog under the virtlockd ident:
++#log_outputs="3:syslog:virtlockd"
++#
++
++# Log debug buffer size: default 64
++# The daemon keeps an internal debug log buffer which will be dumped in case
++# of crash or upon receiving a SIGUSR2 signal. This setting allows to override
++# the default buffer size in kilobytes.
++# If value is 0 or less the debug log buffer is deactivated
++#log_buffer_size = 64
+--
+1.8.3.2
+
--- /dev/null
+From f79b8cfc288deb39dc652a7a552f8bcb85dc1148 Mon Sep 17 00:00:00 2001
+Message-Id: <f79b8cfc288deb39dc652a7a552f8bcb85dc1148.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:06 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllDomains RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllDomains call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 9e97128ba5a1045b71b50adb23993f09628f0a24)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 15 +++++++++++----
+ src/remote/remote_protocol.x | 15 +++++----------
+ 3 files changed, 23 insertions(+), 14 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index e228cba..8289cb5 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -1050,6 +1050,13 @@ remoteDispatchConnectListAllDomains(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (ndomains > REMOTE_DOMAIN_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domains '%d' for limit '%d'"),
++ ndomains, REMOTE_DOMAIN_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (doms && ndomains) {
+ if (VIR_ALLOC_N(ret->domains.domains_val, ndomains) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 14c16f6..cd2b9a9 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -1370,10 +1370,10 @@ remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids)
+
+ remoteDriverLock(priv);
+
+- if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
++ if (maxids > REMOTE_DOMAIN_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+- _("too many remote domain IDs: %d > %d"),
+- maxids, REMOTE_DOMAIN_ID_LIST_MAX);
++ _("Too many domains '%d' for limit '%d'"),
++ maxids, REMOTE_DOMAIN_LIST_MAX);
+ goto done;
+ }
+ args.maxids = maxids;
+@@ -1386,7 +1386,7 @@ remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids)
+
+ if (ret.ids.ids_len > maxids) {
+ virReportError(VIR_ERR_RPC,
+- _("too many remote domain IDs: %d > %d"),
++ _("Too many domains '%d' for limit '%d'"),
+ ret.ids.ids_len, maxids);
+ goto cleanup;
+ }
+@@ -1433,6 +1433,13 @@ remoteConnectListAllDomains(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.domains.domains_len > REMOTE_DOMAIN_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domains '%d' for limit '%d'"),
++ ret.domains.domains_len, REMOTE_DOMAIN_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (domains) {
+ if (VIR_ALLOC_N(doms, ret.domains.domains_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 9e3918c..718e398 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -73,13 +73,8 @@ typedef string remote_nonnull_string<REMOTE_STRING_MAX>;
+ /* A long string, which may be NULL. */
+ typedef remote_nonnull_string *remote_string;
+
+-/* This just places an upper limit on the length of lists of
+- * domain IDs which may be sent via the protocol.
+- */
+-const REMOTE_DOMAIN_ID_LIST_MAX = 16384;
+-
+-/* Upper limit on lists of domain names. */
+-const REMOTE_DOMAIN_NAME_LIST_MAX = 16384;
++/* Upper limit on lists of domains. */
++const REMOTE_DOMAIN_LIST_MAX = 16384;
+
+ /* Upper limit on cpumap (bytes) passed to virDomainPinVcpu. */
+ const REMOTE_CPUMAP_MAX = 2048;
+@@ -724,7 +719,7 @@ struct remote_connect_list_domains_args {
+ };
+
+ struct remote_connect_list_domains_ret {
+- int ids<REMOTE_DOMAIN_ID_LIST_MAX>; /* insert@1 */
++ int ids<REMOTE_DOMAIN_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_num_of_domains_ret {
+@@ -990,7 +985,7 @@ struct remote_connect_list_defined_domains_args {
+ };
+
+ struct remote_connect_list_defined_domains_ret {
+- remote_nonnull_string names<REMOTE_DOMAIN_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_DOMAIN_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_num_of_defined_domains_ret {
+@@ -2665,7 +2660,7 @@ struct remote_connect_list_all_domains_args {
+ };
+
+ struct remote_connect_list_all_domains_ret {
+- remote_nonnull_domain domains<>;
++ remote_nonnull_domain domains<REMOTE_DOMAIN_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From 0c0ab54756999324d57973ff4b0102a54bc0b7af Mon Sep 17 00:00:00 2001
+Message-Id: <0c0ab54756999324d57973ff4b0102a54bc0b7af.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:10 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllInterfaces RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllInterfaces call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 8be2172897c272ead150ad59a63946ab97562a11)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 13 +++++--------
+ 3 files changed, 19 insertions(+), 8 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index b6501e0..871b0df 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4256,6 +4256,13 @@ remoteDispatchConnectListAllInterfaces(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nifaces > REMOTE_INTERFACE_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many interfaces '%d' for limit '%d'"),
++ nifaces, REMOTE_INTERFACE_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (ifaces && nifaces) {
+ if (VIR_ALLOC_N(ret->ifaces.ifaces_val, nifaces) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index e555704..4d82452 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -2909,6 +2909,13 @@ remoteConnectListAllInterfaces(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.ifaces.ifaces_len > REMOTE_INTERFACE_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many interfaces '%d' for limit '%d'"),
++ ret.ifaces.ifaces_len, REMOTE_INTERFACE_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (ifaces) {
+ if (VIR_ALLOC_N(tmp_ifaces, ret.ifaces.ifaces_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index f1e27fa..573d63f 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -91,11 +91,8 @@ const REMOTE_MIGRATE_COOKIE_MAX = 16384;
+ /* Upper limit on lists of networks. */
+ const REMOTE_NETWORK_LIST_MAX = 16384;
+
+-/* Upper limit on lists of interface names. */
+-const REMOTE_INTERFACE_NAME_LIST_MAX = 16384;
+-
+-/* Upper limit on lists of defined interface names. */
+-const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384;
++/* Upper limit on lists of interfaces. */
++const REMOTE_INTERFACE_LIST_MAX = 16384;
+
+ /* Upper limit on lists of storage pools. */
+ const REMOTE_STORAGE_POOL_LIST_MAX = 4096;
+@@ -1478,7 +1475,7 @@ struct remote_connect_list_interfaces_args {
+ };
+
+ struct remote_connect_list_interfaces_ret {
+- remote_nonnull_string names<REMOTE_INTERFACE_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_INTERFACE_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_num_of_defined_interfaces_ret {
+@@ -1490,7 +1487,7 @@ struct remote_connect_list_defined_interfaces_args {
+ };
+
+ struct remote_connect_list_defined_interfaces_ret {
+- remote_nonnull_string names<REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_INTERFACE_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_interface_lookup_by_name_args {
+@@ -2701,7 +2698,7 @@ struct remote_connect_list_all_interfaces_args {
+ };
+
+ struct remote_connect_list_all_interfaces_ret {
+- remote_nonnull_interface ifaces<>;
++ remote_nonnull_interface ifaces<REMOTE_INTERFACE_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From d7fbd5a9272eeaadebf5511045a9904f4f26bd1e Mon Sep 17 00:00:00 2001
+Message-Id: <d7fbd5a9272eeaadebf5511045a9904f4f26bd1e.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:12 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllNWFilters RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllNWFilters call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 12034511a195bdbcc06401dfec07ce4837e1f5b4)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 8 ++++----
+ 3 files changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 697aa58..e19b42d 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4374,6 +4374,13 @@ remoteDispatchConnectListAllNWFilters(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nfilters > REMOTE_NWFILTER_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many network filters '%d' for limit '%d'"),
++ nfilters, REMOTE_NWFILTER_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (filters && nfilters) {
+ if (VIR_ALLOC_N(ret->filters.filters_val, nfilters) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index b170a06..d486fa5 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -3041,6 +3041,13 @@ remoteConnectListAllNWFilters(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.filters.filters_len > REMOTE_NWFILTER_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many network filters '%d' for limit '%d'"),
++ ret.filters.filters_len, REMOTE_NWFILTER_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (filters) {
+ if (VIR_ALLOC_N(tmp_filters, ret.filters.filters_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 21059c8..b2841a7 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -106,8 +106,8 @@ const REMOTE_NODE_DEVICE_LIST_MAX = 16384;
+ /* Upper limit on lists of node device capabilities. */
+ const REMOTE_NODE_DEVICE_CAPS_LIST_MAX = 65536;
+
+-/* Upper limit on lists of network filter names. */
+-const REMOTE_NWFILTER_NAME_LIST_MAX = 1024;
++/* Upper limit on lists of network filters. */
++const REMOTE_NWFILTER_LIST_MAX = 1024;
+
+ /* Upper limit on list of scheduler parameters. */
+ const REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX = 16;
+@@ -1423,7 +1423,7 @@ struct remote_connect_list_nwfilters_args {
+ };
+
+ struct remote_connect_list_nwfilters_ret {
+- remote_nonnull_string names<REMOTE_NWFILTER_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_NWFILTER_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_nwfilter_lookup_by_uuid_args {
+@@ -2718,7 +2718,7 @@ struct remote_connect_list_all_nwfilters_args {
+ };
+
+ struct remote_connect_list_all_nwfilters_ret {
+- remote_nonnull_nwfilter filters<>;
++ remote_nonnull_nwfilter filters<REMOTE_NWFILTER_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From c492435723a14ee2fa5991228c98a791ad68c7ac Mon Sep 17 00:00:00 2001
+Message-Id: <c492435723a14ee2fa5991228c98a791ad68c7ac.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:09 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllNetworks RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllNetworks call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 174f7dd5bafb1a6d8e341078149855cd2d790082)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 10 +++++-----
+ 3 files changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 512170b..b6501e0 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4197,6 +4197,13 @@ remoteDispatchConnectListAllNetworks(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nnets > REMOTE_NETWORK_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many networks '%d' for limit '%d'"),
++ nnets, REMOTE_NETWORK_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (nets && nnets) {
+ if (VIR_ALLOC_N(ret->nets.nets_val, nnets) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 542cb39..e555704 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -2843,6 +2843,13 @@ remoteConnectListAllNetworks(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.nets.nets_len > REMOTE_NETWORK_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many networks '%d' for limit '%d'"),
++ ret.nets.nets_len, REMOTE_NETWORK_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (nets) {
+ if (VIR_ALLOC_N(tmp_nets, ret.nets.nets_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 2034aa1..f1e27fa 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -88,8 +88,8 @@ const REMOTE_CPUMAPS_MAX = 8388608;
+ /* Upper limit on migrate cookie. */
+ const REMOTE_MIGRATE_COOKIE_MAX = 16384;
+
+-/* Upper limit on lists of network names. */
+-const REMOTE_NETWORK_NAME_LIST_MAX = 16384;
++/* Upper limit on lists of networks. */
++const REMOTE_NETWORK_LIST_MAX = 16384;
+
+ /* Upper limit on lists of interface names. */
+ const REMOTE_INTERFACE_NAME_LIST_MAX = 16384;
+@@ -1317,7 +1317,7 @@ struct remote_connect_list_networks_args {
+ };
+
+ struct remote_connect_list_networks_ret {
+- remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_NETWORK_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_num_of_defined_networks_ret {
+@@ -1329,7 +1329,7 @@ struct remote_connect_list_defined_networks_args {
+ };
+
+ struct remote_connect_list_defined_networks_ret {
+- remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_NETWORK_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_network_lookup_by_uuid_args {
+@@ -2691,7 +2691,7 @@ struct remote_connect_list_all_networks_args {
+ };
+
+ struct remote_connect_list_all_networks_ret {
+- remote_nonnull_network nets<>;
++ remote_nonnull_network nets<REMOTE_NETWORK_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From d7661c0cf4ed8d2fbb974659a329e52b28b5e178 Mon Sep 17 00:00:00 2001
+Message-Id: <d7661c0cf4ed8d2fbb974659a329e52b28b5e178.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:11 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllNodeDevices RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllNodeDevices call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 1dcff6a7ea668feeeec55ee577e5182a1c0082e4)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 8 ++++----
+ 3 files changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 871b0df..697aa58 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4315,6 +4315,13 @@ remoteDispatchConnectListAllNodeDevices(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (ndevices > REMOTE_NODE_DEVICE_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many node devices '%d' for limit '%d'"),
++ ndevices, REMOTE_NODE_DEVICE_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (devices && ndevices) {
+ if (VIR_ALLOC_N(ret->devices.devices_val, ndevices) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 4d82452..b170a06 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -2975,6 +2975,13 @@ remoteConnectListAllNodeDevices(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.devices.devices_len > REMOTE_NODE_DEVICE_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many node devices '%d' for limit '%d'"),
++ ret.devices.devices_len, REMOTE_NODE_DEVICE_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (devices) {
+ if (VIR_ALLOC_N(tmp_devices, ret.devices.devices_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 573d63f..21059c8 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -100,8 +100,8 @@ const REMOTE_STORAGE_POOL_LIST_MAX = 4096;
+ /* Upper limit on lists of storage vols. */
+ const REMOTE_STORAGE_VOL_LIST_MAX = 16384;
+
+-/* Upper limit on lists of node device names. */
+-const REMOTE_NODE_DEVICE_NAME_LIST_MAX = 16384;
++/* Upper limit on lists of node devices. */
++const REMOTE_NODE_DEVICE_LIST_MAX = 16384;
+
+ /* Upper limit on lists of node device capabilities. */
+ const REMOTE_NODE_DEVICE_CAPS_LIST_MAX = 65536;
+@@ -1863,7 +1863,7 @@ struct remote_node_list_devices_args {
+ };
+
+ struct remote_node_list_devices_ret {
+- remote_nonnull_string names<REMOTE_NODE_DEVICE_NAME_LIST_MAX>; /* insert@2 */
++ remote_nonnull_string names<REMOTE_NODE_DEVICE_LIST_MAX>; /* insert@2 */
+ };
+
+ struct remote_node_device_lookup_by_name_args {
+@@ -2708,7 +2708,7 @@ struct remote_connect_list_all_node_devices_args {
+ };
+
+ struct remote_connect_list_all_node_devices_ret {
+- remote_nonnull_node_device devices<>;
++ remote_nonnull_node_device devices<REMOTE_NODE_DEVICE_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From 6040b8ad9a04434782f7cd037db33768456e151a Mon Sep 17 00:00:00 2001
+Message-Id: <6040b8ad9a04434782f7cd037db33768456e151a.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:13 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllSecrets RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllSecrets call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 47fb5672f2f4e9efcd4e9ec30f5e723c46fa8e6f)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 6 +++---
+ 3 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index e19b42d..6ace7af 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4433,6 +4433,13 @@ remoteDispatchConnectListAllSecrets(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nsecrets > REMOTE_SECRET_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many secrets '%d' for limit '%d'"),
++ nsecrets, REMOTE_SECRET_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (secrets && nsecrets) {
+ if (VIR_ALLOC_N(ret->secrets.secrets_val, nsecrets) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index d486fa5..62e77a5 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -3107,6 +3107,13 @@ remoteConnectListAllSecrets(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.secrets.secrets_len > REMOTE_SECRET_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many secrets '%d' for limit '%d'"),
++ ret.secrets.secrets_len, REMOTE_SECRET_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (secrets) {
+ if (VIR_ALLOC_N(tmp_secrets, ret.secrets.secrets_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index b2841a7..a1c23da 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -188,7 +188,7 @@ const REMOTE_SECRET_VALUE_MAX = 65536;
+ /*
+ * Upper limit on list of secrets.
+ */
+-const REMOTE_SECRET_UUID_LIST_MAX = 16384;
++const REMOTE_SECRET_LIST_MAX = 16384;
+
+ /*
+ * Upper limit on list of CPUs accepted when computing a baseline CPU.
+@@ -2002,7 +2002,7 @@ struct remote_connect_list_secrets_args {
+ };
+
+ struct remote_connect_list_secrets_ret {
+- remote_nonnull_string uuids<REMOTE_SECRET_UUID_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string uuids<REMOTE_SECRET_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_secret_lookup_by_uuid_args {
+@@ -2728,7 +2728,7 @@ struct remote_connect_list_all_secrets_args {
+ };
+
+ struct remote_connect_list_all_secrets_ret {
+- remote_nonnull_secret secrets<>;
++ remote_nonnull_secret secrets<REMOTE_SECRET_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From 68580ef359c7940d5f4b88f2ed2612d99a32cbf0 Mon Sep 17 00:00:00 2001
+Message-Id: <68580ef359c7940d5f4b88f2ed2612d99a32cbf0.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:07 +0100
+Subject: [PATCH] Add bounds checking on virConnectListAllStoragePools RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virConnectListAllStoragePools call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit c853fa8febad5c4990936521f9426f3e3df74f98)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 10 +++++-----
+ 3 files changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 8289cb5..42c1c47 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4073,6 +4073,13 @@ remoteDispatchConnectListAllStoragePools(virNetServerPtr server ATTRIBUTE_UNUSED
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (npools > REMOTE_STORAGE_POOL_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many storage pools '%d' for limit '%d'"),
++ npools, REMOTE_STORAGE_POOL_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (pools && npools) {
+ if (VIR_ALLOC_N(ret->pools.pools_val, npools) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index cd2b9a9..622647b 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -3276,6 +3276,13 @@ remoteConnectListAllStoragePools(virConnectPtr conn,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.pools.pools_len > REMOTE_STORAGE_POOL_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many storage pools '%d' for limit '%d'"),
++ ret.pools.pools_len, REMOTE_STORAGE_POOL_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (pools) {
+ if (VIR_ALLOC_N(tmp_pools, ret.pools.pools_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 718e398..6e996b4 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -97,8 +97,8 @@ const REMOTE_INTERFACE_NAME_LIST_MAX = 16384;
+ /* Upper limit on lists of defined interface names. */
+ const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384;
+
+-/* Upper limit on lists of storage pool names. */
+-const REMOTE_STORAGE_POOL_NAME_LIST_MAX = 4096;
++/* Upper limit on lists of storage pools. */
++const REMOTE_STORAGE_POOL_LIST_MAX = 4096;
+
+ /* Upper limit on lists of storage vol names. */
+ const REMOTE_STORAGE_VOL_NAME_LIST_MAX = 16384;
+@@ -1604,7 +1604,7 @@ struct remote_connect_list_storage_pools_args {
+ };
+
+ struct remote_connect_list_storage_pools_ret {
+- remote_nonnull_string names<REMOTE_STORAGE_POOL_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_STORAGE_POOL_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_num_of_defined_storage_pools_ret {
+@@ -1616,7 +1616,7 @@ struct remote_connect_list_defined_storage_pools_args {
+ };
+
+ struct remote_connect_list_defined_storage_pools_ret {
+- remote_nonnull_string names<REMOTE_STORAGE_POOL_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_STORAGE_POOL_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_connect_find_storage_pool_sources_args {
+@@ -2670,7 +2670,7 @@ struct remote_connect_list_all_storage_pools_args {
+ };
+
+ struct remote_connect_list_all_storage_pools_ret {
+- remote_nonnull_storage_pool pools<>;
++ remote_nonnull_storage_pool pools<REMOTE_STORAGE_POOL_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From c0d1584975c670974915498f02da48887f26fb9e Mon Sep 17 00:00:00 2001
+Message-Id: <c0d1584975c670974915498f02da48887f26fb9e.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:05 +0100
+Subject: [PATCH] Add bounds checking on virDomain{SnapshotListAllChildren,
+ ListAllSnapshots} RPC calls
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virDomain{SnapshotListAllChildren,ListAllSnapshots}
+calls were not bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit a43d4f543c31a17ab3a29ad8e01828ff30390622)
+---
+ daemon/remote.c | 14 ++++++++++++++
+ src/remote/remote_driver.c | 16 ++++++++++++++++
+ src/remote/remote_protocol.x | 10 +++++-----
+ 3 files changed, 35 insertions(+), 5 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index ad78011..e228cba 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -3934,6 +3934,13 @@ remoteDispatchDomainListAllSnapshots(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nsnaps > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domain snapshots '%d' for limit '%d'"),
++ nsnaps, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (snaps && nsnaps) {
+ if (VIR_ALLOC_N(ret->snapshots.snapshots_val, nsnaps) < 0)
+ goto cleanup;
+@@ -3996,6 +4003,13 @@ remoteDispatchDomainSnapshotListAllChildren(virNetServerPtr server ATTRIBUTE_UNU
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nsnaps > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domain snapshots '%d' for limit '%d'"),
++ nsnaps, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (snaps && nsnaps) {
+ if (VIR_ALLOC_N(ret->snapshots.snapshots_val, nsnaps) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 33b2b0f..14c16f6 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -5760,6 +5760,14 @@ remoteDomainListAllSnapshots(virDomainPtr dom,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domain snapshots '%d' for limit '%d'"),
++ ret.snapshots.snapshots_len,
++ REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (snapshots) {
+ if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0)
+ goto cleanup;
+@@ -5819,6 +5827,14 @@ remoteDomainSnapshotListAllChildren(virDomainSnapshotPtr parent,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many domain snapshots '%d' for limit '%d'"),
++ ret.snapshots.snapshots_len,
++ REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (snapshots) {
+ if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index eff7e1c..9e3918c 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -154,7 +154,7 @@ const REMOTE_AUTH_TYPE_LIST_MAX = 20;
+ const REMOTE_DOMAIN_MEMORY_STATS_MAX = 1024;
+
+ /* Upper limit on lists of domain snapshots. */
+-const REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX = 1024;
++const REMOTE_DOMAIN_SNAPSHOT_LIST_MAX = 1024;
+
+ /* Maximum length of a block peek buffer message.
+ * Note applications need to be aware of this limit and issue multiple
+@@ -2396,7 +2396,7 @@ struct remote_domain_snapshot_list_names_args {
+ };
+
+ struct remote_domain_snapshot_list_names_ret {
+- remote_nonnull_string names<REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_DOMAIN_SNAPSHOT_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_domain_list_all_snapshots_args {
+@@ -2406,7 +2406,7 @@ struct remote_domain_list_all_snapshots_args {
+ };
+
+ struct remote_domain_list_all_snapshots_ret {
+- remote_nonnull_domain_snapshot snapshots<>;
++ remote_nonnull_domain_snapshot snapshots<REMOTE_DOMAIN_SNAPSHOT_LIST_MAX>;
+ int ret;
+ };
+
+@@ -2426,7 +2426,7 @@ struct remote_domain_snapshot_list_children_names_args {
+ };
+
+ struct remote_domain_snapshot_list_children_names_ret {
+- remote_nonnull_string names<REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_DOMAIN_SNAPSHOT_LIST_MAX>; /* insert@1 */
+ };
+
+ struct remote_domain_snapshot_list_all_children_args {
+@@ -2436,7 +2436,7 @@ struct remote_domain_snapshot_list_all_children_args {
+ };
+
+ struct remote_domain_snapshot_list_all_children_ret {
+- remote_nonnull_domain_snapshot snapshots<>;
++ remote_nonnull_domain_snapshot snapshots<REMOTE_DOMAIN_SNAPSHOT_LIST_MAX>;
+ int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From d6add35e43b45b892ad9eb015d29c0b2720001c2 Mon Sep 17 00:00:00 2001
+Message-Id: <d6add35e43b45b892ad9eb015d29c0b2720001c2.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:04 +0100
+Subject: [PATCH] Add bounds checking on virDomainGetJobStats RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virDomainGetJobStats call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 6d7d0b1869ed293e3208d11f375cecea0129dfc5)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 8 ++++++++
+ src/remote/remote_protocol.x | 5 ++++-
+ 3 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index a11ba94..ad78011 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4579,6 +4579,13 @@ remoteDispatchDomainGetJobStats(virNetServerPtr server ATTRIBUTE_UNUSED,
+ &nparams, args->flags) < 0)
+ goto cleanup;
+
++ if (nparams > REMOTE_DOMAIN_JOB_STATS_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many job stats '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_JOB_STATS_MAX);
++ goto cleanup;
++ }
++
+ if (remoteSerializeTypedParameters(params, nparams,
+ &ret->params.params_val,
+ &ret->params.params_len,
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 30f8f90..33b2b0f 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -5998,6 +5998,14 @@ remoteDomainGetJobStats(virDomainPtr domain,
+ (xdrproc_t) xdr_remote_domain_get_job_stats_ret, (char *) &ret) == -1)
+ goto done;
+
++ if (ret.params.params_len > REMOTE_DOMAIN_JOB_STATS_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many job stats '%d' for limit '%d'"),
++ ret.params.params_len,
++ REMOTE_DOMAIN_JOB_STATS_MAX);
++ goto cleanup;
++ }
++
+ *type = ret.type;
+
+ if (remoteDeserializeTypedParameters(ret.params.params_val,
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 4262c34..eff7e1c 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -237,6 +237,9 @@ const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
+ /* Upper limit on migrate parameters */
+ const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64;
+
++/* Upper limit on number of job stats */
++const REMOTE_DOMAIN_JOB_STATS_MAX = 16;
++
+ /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
+ typedef opaque remote_uuid[VIR_UUID_BUFLEN];
+
+@@ -2196,7 +2199,7 @@ struct remote_domain_get_job_stats_args {
+
+ struct remote_domain_get_job_stats_ret {
+ int type;
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_JOB_STATS_MAX>;
+ };
+
+
+--
+1.8.3.2
+
--- /dev/null
+From b88f552daa9be63938e79092f078ce06da185cb6 Mon Sep 17 00:00:00 2001
+Message-Id: <b88f552daa9be63938e79092f078ce06da185cb6.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:03 +0100
+Subject: [PATCH] Add bounds checking on virDomainMigrate*Params RPC calls
+ (CVE-2013-4292)
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The parameters for the virDomainMigrate*Params RPC calls were
+not bounds checks, meaning a malicious client can cause libvirtd
+to consume arbitrary memory
+
+This issue was introduced in the 1.1.0 release of libvirt
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit fd6f6a48619eb221afeb1c5965537534cd54e01d)
+---
+ daemon/remote.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ src/remote/remote_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ src/remote/remote_protocol.x | 15 +++++++++------
+ 3 files changed, 93 insertions(+), 6 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 03d5557..a11ba94 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4620,6 +4620,13 @@ remoteDispatchDomainMigrateBegin3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+@@ -4671,6 +4678,13 @@ remoteDispatchDomainMigratePrepare3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
+ args->params.params_len,
+ 0, &nparams)))
+@@ -4726,6 +4740,13 @@ remoteDispatchDomainMigratePrepareTunnel3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
+ args->params.params_len,
+ 0, &nparams)))
+@@ -4790,6 +4811,13 @@ remoteDispatchDomainMigratePerform3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+@@ -4845,6 +4873,13 @@ remoteDispatchDomainMigrateFinish3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
+ args->params.params_len,
+ 0, &nparams)))
+@@ -4897,6 +4932,13 @@ remoteDispatchDomainMigrateConfirm3Params(
+ goto cleanup;
+ }
+
++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 71d0034..30f8f90 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -6037,6 +6037,13 @@ remoteDomainMigrateBegin3Params(virDomainPtr domain,
+ make_nonnull_domain(&args.dom, domain);
+ args.flags = flags;
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (remoteSerializeTypedParameters(params, nparams,
+ &args.params.params_val,
+ &args.params.params_len) < 0) {
+@@ -6096,6 +6103,13 @@ remoteDomainMigratePrepare3Params(virConnectPtr dconn,
+ memset(&args, 0, sizeof(args));
+ memset(&ret, 0, sizeof(ret));
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (remoteSerializeTypedParameters(params, nparams,
+ &args.params.params_val,
+ &args.params.params_len) < 0) {
+@@ -6171,6 +6185,13 @@ remoteDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+ memset(&args, 0, sizeof(args));
+ memset(&ret, 0, sizeof(ret));
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ args.cookie_in.cookie_in_val = (char *)cookiein;
+ args.cookie_in.cookie_in_len = cookieinlen;
+ args.flags = flags;
+@@ -6250,6 +6271,13 @@ remoteDomainMigratePerform3Params(virDomainPtr dom,
+ memset(&args, 0, sizeof(args));
+ memset(&ret, 0, sizeof(ret));
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ make_nonnull_domain(&args.dom, dom);
+ args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
+ args.cookie_in.cookie_in_val = (char *)cookiein;
+@@ -6315,6 +6343,13 @@ remoteDomainMigrateFinish3Params(virConnectPtr dconn,
+ memset(&args, 0, sizeof(args));
+ memset(&ret, 0, sizeof(ret));
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ args.cookie_in.cookie_in_val = (char *)cookiein;
+ args.cookie_in.cookie_in_len = cookieinlen;
+ args.flags = flags;
+@@ -6380,6 +6415,13 @@ remoteDomainMigrateConfirm3Params(virDomainPtr domain,
+
+ memset(&args, 0, sizeof(args));
+
++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many migration parameters '%d' for limit '%d'"),
++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
++ goto cleanup;
++ }
++
+ make_nonnull_domain(&args.dom, domain);
+ args.cookie_in.cookie_in_len = cookieinlen;
+ args.cookie_in.cookie_in_val = (char *) cookiein;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 7cfebdf..4262c34 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -234,6 +234,9 @@ const REMOTE_DOMAIN_DISK_ERRORS_MAX = 256;
+ */
+ const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
+
++/* Upper limit on migrate parameters */
++const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64;
++
+ /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
+ typedef opaque remote_uuid[VIR_UUID_BUFLEN];
+
+@@ -2770,7 +2773,7 @@ struct remote_domain_fstrim_args {
+
+ struct remote_domain_migrate_begin3_params_args {
+ remote_nonnull_domain dom;
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ unsigned int flags;
+ };
+
+@@ -2780,7 +2783,7 @@ struct remote_domain_migrate_begin3_params_ret {
+ };
+
+ struct remote_domain_migrate_prepare3_params_args {
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
+ unsigned int flags;
+ };
+@@ -2791,7 +2794,7 @@ struct remote_domain_migrate_prepare3_params_ret {
+ };
+
+ struct remote_domain_migrate_prepare_tunnel3_params_args {
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
+ unsigned int flags;
+ };
+@@ -2803,7 +2806,7 @@ struct remote_domain_migrate_prepare_tunnel3_params_ret {
+ struct remote_domain_migrate_perform3_params_args {
+ remote_nonnull_domain dom;
+ remote_string dconnuri;
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
+ unsigned int flags;
+ };
+@@ -2813,7 +2816,7 @@ struct remote_domain_migrate_perform3_params_ret {
+ };
+
+ struct remote_domain_migrate_finish3_params_args {
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
+ unsigned int flags;
+ int cancelled;
+@@ -2826,7 +2829,7 @@ struct remote_domain_migrate_finish3_params_ret {
+
+ struct remote_domain_migrate_confirm3_params_args {
+ remote_nonnull_domain dom;
+- remote_typed_param params<>;
++ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
+ opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
+ unsigned int flags;
+ int cancelled;
+--
+1.8.3.2
+
--- /dev/null
+From 6a7837f5eaf8dd9c6cf0b4319a0ae0ee747d3227 Mon Sep 17 00:00:00 2001
+Message-Id: <6a7837f5eaf8dd9c6cf0b4319a0ae0ee747d3227.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:08 +0100
+Subject: [PATCH] Add bounds checking on virStoragePoolListAllVolumes RPC call
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The return values for the virStoragePoolListAllVolumes call were not
+bounds checked. This is a robustness issue for clients if
+something where to cause corruption of the RPC stream data.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 046acaf37bc95d895f0a7d04a3a06ac992701711)
+---
+ daemon/remote.c | 7 +++++++
+ src/remote/remote_driver.c | 7 +++++++
+ src/remote/remote_protocol.x | 8 ++++----
+ 3 files changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 42c1c47..512170b 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -4136,6 +4136,13 @@ remoteDispatchStoragePoolListAllVolumes(virNetServerPtr server ATTRIBUTE_UNUSED,
+ args->flags)) < 0)
+ goto cleanup;
+
++ if (nvols > REMOTE_STORAGE_VOL_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many storage volumes '%d' for limit '%d'"),
++ nvols, REMOTE_STORAGE_VOL_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (vols && nvols) {
+ if (VIR_ALLOC_N(ret->vols.vols_val, nvols) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 622647b..542cb39 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -3343,6 +3343,13 @@ remoteStoragePoolListAllVolumes(virStoragePoolPtr pool,
+ (char *) &ret) == -1)
+ goto done;
+
++ if (ret.vols.vols_len > REMOTE_STORAGE_VOL_LIST_MAX) {
++ virReportError(VIR_ERR_RPC,
++ _("Too many storage volumes '%d' for limit '%d'"),
++ ret.vols.vols_len, REMOTE_STORAGE_VOL_LIST_MAX);
++ goto cleanup;
++ }
++
+ if (vols) {
+ if (VIR_ALLOC_N(tmp_vols, ret.vols.vols_len + 1) < 0)
+ goto cleanup;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 6e996b4..2034aa1 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -100,8 +100,8 @@ const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384;
+ /* Upper limit on lists of storage pools. */
+ const REMOTE_STORAGE_POOL_LIST_MAX = 4096;
+
+-/* Upper limit on lists of storage vol names. */
+-const REMOTE_STORAGE_VOL_NAME_LIST_MAX = 16384;
++/* Upper limit on lists of storage vols. */
++const REMOTE_STORAGE_VOL_LIST_MAX = 16384;
+
+ /* Upper limit on lists of node device names. */
+ const REMOTE_NODE_DEVICE_NAME_LIST_MAX = 16384;
+@@ -1746,7 +1746,7 @@ struct remote_storage_pool_list_volumes_args {
+ };
+
+ struct remote_storage_pool_list_volumes_ret {
+- remote_nonnull_string names<REMOTE_STORAGE_VOL_NAME_LIST_MAX>; /* insert@1 */
++ remote_nonnull_string names<REMOTE_STORAGE_VOL_LIST_MAX>; /* insert@1 */
+ };
+
+
+@@ -2681,7 +2681,7 @@ struct remote_storage_pool_list_all_volumes_args {
+ };
+
+ struct remote_storage_pool_list_all_volumes_ret {
+- remote_nonnull_storage_vol vols<>;
++ remote_nonnull_storage_vol vols<REMOTE_STORAGE_VOL_LIST_MAX>;
+ unsigned int ret;
+ };
+
+--
+1.8.3.2
+
--- /dev/null
+From bdb62336234cc454d7c5b1e539ad764984c946e2 Mon Sep 17 00:00:00 2001
+Message-Id: <bdb62336234cc454d7c5b1e539ad764984c946e2.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:38:28 +0100
+Subject: [PATCH] Add documentation for access control system
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+This adds two new pages to the website, acl.html describing
+the general access control framework and permissions models,
+and aclpolkit.html describing the use of polkit as an
+access control driver.
+
+page.xsl is modified to support a new syntax
+
+ <div id="include" filename="somefile.htmlinc"/>
+
+which will cause the XSL transform to replace that <div>
+with the contents of 'somefile.htmlinc'. We use this in
+the acl.html.in file, to pull the table of permissions
+for each libvirt object. This table is autogenerated
+from the enums in src/access/viraccessperms.h by the
+genaclperms.pl script.
+
+newapi.xsl is modified so that the list of permissions
+checks shown against each API will link to the description
+of the permissions in acl.html
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit da13f2c70c06c38c4f8feba1a5725652d2f1efc7)
+---
+ .gitignore | 1 +
+ docs/Makefile.am | 12 +-
+ docs/acl.html.in | 100 ++++++++++++
+ docs/aclpolkit.html.in | 410 +++++++++++++++++++++++++++++++++++++++++++++++++
+ docs/auth.html.in | 6 +-
+ docs/genaclperms.pl | 124 +++++++++++++++
+ docs/newapi.xsl | 4 +-
+ docs/page.xsl | 11 ++
+ docs/sitemap.html.in | 10 ++
+ src/Makefile.am | 2 +-
+ 10 files changed, 674 insertions(+), 6 deletions(-)
+ create mode 100644 docs/acl.html.in
+ create mode 100644 docs/aclpolkit.html.in
+ create mode 100755 docs/genaclperms.pl
+
+diff --git a/docs/Makefile.am b/docs/Makefile.am
+index aabee44..0b0d2d4 100644
+--- a/docs/Makefile.am
++++ b/docs/Makefile.am
+@@ -128,7 +128,7 @@ fig = \
+ migration-unmanaged-direct.fig
+
+ EXTRA_DIST= \
+- apibuild.py \
++ apibuild.py genaclperms.pl \
+ site.xsl newapi.xsl news.xsl page.xsl \
+ hacking1.xsl hacking2.xsl wrapstring.xsl \
+ $(dot_html) $(dot_html_in) $(gif) $(apihtml) $(apipng) \
+@@ -139,6 +139,16 @@ EXTRA_DIST= \
+ sitemap.html.in \
+ todo.pl hvsupport.pl todo.cfg-example
+
++BUILT_SOURCES += aclperms.htmlinc
++
++CLEANFILES = $(srcdir)/aclperms.htmlinc
++
++acl.html:: $(srcdir)/aclperms.htmlinc
++
++$(srcdir)/aclperms.htmlinc: $(top_srcdir)/src/access/viraccessperm.h \
++ $(srcdir)/genaclperms.pl Makefile.am
++ $(PERL) $(srcdir)/genaclperms.pl $< > $@
++
+ MAINTAINERCLEANFILES = \
+ $(addprefix $(srcdir)/,$(dot_html)) \
+ $(addprefix $(srcdir)/,$(apihtml)) \
+diff --git a/docs/acl.html.in b/docs/acl.html.in
+new file mode 100644
+index 0000000..2d228e2
+--- /dev/null
++++ b/docs/acl.html.in
+@@ -0,0 +1,100 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns="http://www.w3.org/1999/xhtml">
++ <body>
++ <h1>Client access control</h1>
++ <p>
++ Libvirt's client access control framework allows administrators
++ to setup fine grained permission rules across client users,
++ managed objects and API operations. This allows client connections
++ to be locked down to a minimal set of privileges.
++ </p>
++
++ <ul id="toc"></ul>
++
++ <h2><a name="intro">Access control introduction</a></h2>
++
++ <p>
++ In a default configuration, the libvirtd daemon has three levels
++ of access control. All connections start off in an unauthenticated
++ state, where the only API operations allowed are those required
++ to complete authentication. After successful authentication, a
++ connection either has full, unrestricted access to all libvirt
++ API calls, or is locked down to only "read only" operations,
++ according to what socket a client connection originated on.
++ </p>
++
++ <p>
++ The access control framework allows authenticated connections to
++ have fine grained permission rules to be defined by the administrator.
++ Every API call in libvirt has a set of permissions that will
++ be validated against the object being used. For example, the
++ <code>virDomainSetSchedulerParametersFlags</code> method will
++ check whether the client user has the <code>write</code>
++ permission on the <code>domain</code> object instance passed
++ in as a parameter. Further permissions will also be checked
++ if certain flags are set in the API call. In addition to
++ checks on the object passed in to an API call, some methods
++ will filter their results. For example the <code>virConnectListAllDomains</code>
++ method will check the <code>search_domains</code> on the <code>connect</code>
++ object, but will also filter the returned <code>domain</code>
++ objects to only those on which the client user has the
++ <code>getattr</code> permission.
++ </p>
++
++ <h2><a name="drivers">Access control drivers</a></h2>
++
++ <p>
++ The access control framework is designed as a pluggable
++ system to enable future integration with arbitrary access
++ control technologies. By default, the <code>none</code>
++ driver is used, which does no access control checks at
++ all. At this time, libvirt ships with support for using
++ <a href="http://www.freedesktop.org/wiki/Software/polkit/">polkit</a> as a real access
++ control driver. To learn how to use the polkit access
++ driver consult <a href="aclpolkit.html">the configuration
++ docs</a>.
++ </p>
++
++ <p>
++ The access driver is configured in the <code>libvirtd.conf</code>
++ configuration file, using the <code>access_drivers</code>
++ parameter. This parameter accepts an array of access control
++ driver names. If more than one access driver is requested,
++ then all must succeed in order for access to be granted.
++ To enable 'polkit' as the driver:
++ </p>
++
++ <pre>
++# augtool -s set '/files/etc/libvirt/libvirtd.conf/access_drivers[1]' polkit
++ </pre>
++
++ <p>
++ And to reset back to the default (no-op) driver
++ </p>
++
++
++ <pre>
++# augtool -s rm /files/etc/libvirt/libvirtd.conf/access_drivers
++ </pre>
++
++ <p>
++ <strong>Note:</strong> changes to libvirtd.conf require that
++ the libvirtd daemon be restarted.
++ </p>
++
++ <h2><a name="perms">Objects and permissions</a></h2>
++
++ <p>
++ Libvirt applies access control to all the main object
++ types in its API. Each object type, in turn, has a set
++ of permissions defined. To determine what permissions
++ are checked for specific API call, consult the
++ <a href="html/libvirt-libvirt.html">API reference manual</a>
++ documentation for the API in question.
++ </p>
++
++ <div id="include" filename="aclperms.htmlinc"/>
++
++ </body>
++</html>
+diff --git a/docs/aclpolkit.html.in b/docs/aclpolkit.html.in
+new file mode 100644
+index 0000000..3b0d81a
+--- /dev/null
++++ b/docs/aclpolkit.html.in
+@@ -0,0 +1,410 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns="http://www.w3.org/1999/xhtml">
++ <body>
++ <h1>Polkit access control</h1>
++
++ <p>
++ Libvirt's client <a href="acl.html">access control framework</a> allows
++ administrators to setup fine grained permission rules across client users,
++ managed objects and API operations. This allows client connections
++ to be locked down to a minimal set of privileges. The polkit driver
++ provides a simple implementation of the access control framework.
++ </p>
++
++ <ul id="toc"></ul>
++
++ <h2><a name="intro">Introduction</a></h2>
++
++ <p>
++ A default install of libvirt will typically use
++ <a href="http://www.freedesktop.org/wiki/Software/polkit/">polkit</a>
++ to authenticate the initial user connection to libvirtd. This is a
++ very coarse grained check though, either allowing full read-write
++ access to all APIs, or just read-only access. The polkit access
++ control driver in libvirt builds on this capability to allow for
++ fine grained control over the operations a user may perform on an
++ object.
++ </p>
++
++ <h2><a name="perms">Permission names</a></h2>
++
++ <p>
++ The libvirt <a href="acl.html#perms">object names and permission names</a>
++ are mapped onto polkit action names using the simple pattern:
++ </p>
++
++ <pre>org.libvirt.api.$object.$permission
++</pre>
++
++ <p>
++ The only caveat is that any underscore characters in the
++ object or permission names are converted to hyphens. So,
++ for example, the <code>search_storage_vols</code> permission
++ on the <code>storage_pool</code> object maps to the polkit
++ action:
++ </p>
++ <pre>org.libvirt.api.storage-pool.search-storage-vols
++</pre>
++
++ <p>
++ The default policy for any permission which corresponds to
++ a "read only" operation, is to allow access. All other
++ permissions default to deny access.
++ </p>
++
++ <h2><a name="attrs">Object identity attributes</a></h2>
++
++ <p>
++ To allow polkit authorization rules to be written to match
++ against individual object instances, libvirt provides a number
++ of authorization detail attributes when performing a permission
++ check. The set of attributes varies according to the type
++ of object being checked
++ </p>
++
++ <h3><a name="object_connect">virConnectPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_domain">virDomainPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>domain_name</td>
++ <td>Name of the domain, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>domain_uuid</td>
++ <td>UUID of the domain, globally unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_interface">virInterfacePtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>interface_name</td>
++ <td>Name of the network interface, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>interface_mac</td>
++ <td>MAC address of the network interface, not unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_network">virNetworkPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>network_name</td>
++ <td>Name of the network, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>network_uuid</td>
++ <td>UUID of the network, globally unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_node_device">virNodeDevicePtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>node_device_name</td>
++ <td>Name of the node device, unique to the local host</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_nwfilter">virNWFilterPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>nwfilter_name</td>
++ <td>Name of the network filter, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>nwfilter_uuid</td>
++ <td>UUID of the network filter, globally unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_secret">virSecretPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>secret_uuid</td>
++ <td>UUID of the secret, globally unique</td>
++ </tr>
++ <tr>
++ <td>secret_usage_volume</td>
++ <td>Name of the associated volume, if any</td>
++ </tr>
++ <tr>
++ <td>secret_usage_ceph</td>
++ <td>Name of the associated Ceph server, if any</td>
++ </tr>
++ <tr>
++ <td>secret_usage_target</td>
++ <td>Name of the associated iSCSI target, if any</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_storage_pool">virStoragePoolPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>pool_name</td>
++ <td>Name of the storage pool, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>pool_uuid</td>
++ <td>UUID of the storage pool, globally unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++ <h3><a name="object_storage_vol">virStorageVolPtr</a></h3>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Attribute</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++ <tr>
++ <td>connect_driver</td>
++ <td>Name of the libvirt connection driver</td>
++ </tr>
++ <tr>
++ <td>pool_name</td>
++ <td>Name of the storage pool, unique to the local host</td>
++ </tr>
++ <tr>
++ <td>pool_uuid</td>
++ <td>UUID of the storage pool, globally unique</td>
++ </tr>
++ <tr>
++ <td>vol_name</td>
++ <td>Name of the storage volume, unique to the pool</td>
++ </tr>
++ <tr>
++ <td>vol_key</td>
++ <td>Key of the storage volume, globally unique</td>
++ </tr>
++ </tbody>
++ </table>
++
++
++ <h2><a name="user">User identity attributes</a></h2>
++
++ <p>
++ At this point in time, the only attribute provided by
++ libvirt to identify the user invoking the operation
++ is the PID of the client program. This means that the
++ polkit access control driver is only useful if connections
++ to libvirt are restricted to its UNIX domain socket. If
++ connections are being made to a TCP socket, no identifying
++ information is available and access will be denied.
++ Also note that if the client is connecting via an SSH
++ tunnel, it is the local SSH user that will be identified.
++ In future versions, it is expected that more information
++ about the client user will be provided, including the
++ SASL / Kerberos username and/or x509 distinguished
++ name obtained from the authentication provider in use.
++ </p>
++
++
++ <h2><a name="checks">Writing acces control policies</a></h2>
++
++ <p>
++ If using versions of polkit prior to 0.106 then it is only
++ possible to validate (user, permission) pairs via the <code>.pkla</code>
++ files. Fully validation of the (user, permission, object) triple
++ requires the new JavaScript <code>.rules</code> support that
++ was introduced in version 0.106. The latter is what will be
++ described here.
++ </p>
++
++ <p>
++ Libvirt does not ship any rules files by default. It merely
++ provides a definition of the default behaviour for each
++ action (permission). As noted earlier, permissions which
++ correspond to read-only operations in libvirt will be allowed
++ to all users by default; everything else is denied by default.
++ Defining custom rules requires creation of a file in the
++ <code>/etc/polkit-1/rules.d</code> directory with a name
++ chosen by the administrator (<code>100-libvirt-acl.rules</code>
++ would be a reasonable choice). See the <code>polkit(8)</code>
++ manual page for a description of how to write these files
++ in general. The key idea is to create a file containing
++ something like
++ </p>
++
++ <pre>
++ polkit.addRule(function(action, subject) {
++ ....logic to check 'action' and 'subject'...
++ });
++ </pre>
++
++ <p>
++ In this code snippet above, the <code>action</code> object
++ instance will represent the libvirt permission being checked
++ along with identifying attributes for the object it is being
++ applied to. The <code>subject</code> meanwhile will identify
++ the libvirt client app (with the caveat above about it only
++ dealing with local clients connected via the UNIX socket).
++ On the <code>action</code> object, the permission name is
++ accessible via the <code>id</code> attribute, while the
++ object identifying attributes are exposed via a set of
++ attributes with the naming convention <code>_detail_[attrname]</code>.
++ For example, the 'domain_name' attribute would be exposed via
++ a property <code>_detail_domain_name</code>.
++ </p>
++
++ <h3><a name="exconnect">Example: restricting ability to connect to drivers</a></h3>
++
++ <p>
++ Consider a local user <code>berrange</code>
++ who has been granted permission to connect to libvirt in
++ full read-write mode. The goal is to only allow them to
++ use the <code>QEMU</code> driver and not the Xen or LXC
++ drivers which are also available in libvirtd.
++ To achieve this we need to write a rule which checks
++ whether the <code>_detail_connect_driver</code> attribute
++ is <code>QEMU</code>, and match on an action
++ name of <code>org.libvirt.api.connect.getattr</code>. Using
++ the javascript rules format, this ends up written as
++ </p>
++
++ <pre>
++polkit.addRule(function(action, subject) {
++ if (action.id == "org.libvirt.api.connect.getattr" &&
++ subject.user == "berrange") {
++ if (action._detail_connect_driver == 'QEMU') {
++ return polkit.Result.YES;
++ } else {
++ return polkit.Result.NO;
++ }
++ }
++});
++ </pre>
++
++ <h3><a name="exdomain">Example: restricting access to a single domain</a></h3>
++
++ <p>
++ Consider a local user <code>berrange</code>
++ who has been granted permission to connect to libvirt in
++ full read-write mode. The goal is to only allow them to
++ see the domain called <code>demo</code> on the LXC driver.
++ To achieve this we need to write a rule which checks
++ whether the <code>_detail_connect_driver</code> attribute
++ is <code>LXC</code> and the <code>_detail_domain_name</code>
++ attribute is <code>demo</code>, and match on a action
++ name of <code>org.libvirt.api.domain.getattr</code>. Using
++ the javascript rules format, this ends up written as
++ </p>
++
++ <pre>
++polkit.addRule(function(action, subject) {
++ if (action.id == "org.libvirt.api.domain.getattr" &&
++ subject.user == "berrange") {
++ if (action._detail_connect_driver == 'LXC' &&
++ action._detail_domain_name == 'busy') {
++ return polkit.Result.YES;
++ } else {
++ return polkit.Result.NO;
++ }
++ }
++});
++ </pre>
++ </body>
++</html>
+diff --git a/docs/auth.html.in b/docs/auth.html.in
+index e5703c7..37f2978 100644
+--- a/docs/auth.html.in
++++ b/docs/auth.html.in
+@@ -2,12 +2,14 @@
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+- <h1 >Authentication & access control</h1>
++ <h1>Connection authentication</h1>
+ <p>
+ When connecting to libvirt, some connections may require client
+ authentication before allowing use of the APIs. The set of possible
+ authentication mechanisms is administrator controlled, independent
+- of applications using libvirt.
++ of applications using libvirt. Once authenticated, libvirt can apply
++ fine grained <a href="acl.html">access control</a> to the operations
++ performed by a client.
+ </p>
+
+ <ul id="toc"></ul>
+diff --git a/docs/genaclperms.pl b/docs/genaclperms.pl
+new file mode 100755
+index 0000000..244a68e
+--- /dev/null
++++ b/docs/genaclperms.pl
+@@ -0,0 +1,124 @@
++#!/usr/bin/perl
++#
++# Copyright (C) 2013 Red Hat, Inc.
++#
++# This library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++#
++# This library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with this library. If not, see
++# <http://www.gnu.org/licenses/>.
++#
++
++use strict;
++use warnings;
++
++my @objects = (
++ "CONNECT", "DOMAIN", "INTERFACE",
++ "NETWORK","NODE_DEVICE", "NWFILTER",
++ "SECRET", "STORAGE_POOL", "STORAGE_VOL",
++ );
++
++my %class;
++
++foreach my $object (@objects) {
++ my $class = lc $object;
++
++ $class =~ s/(^\w|_\w)/uc $1/eg;
++ $class =~ s/_//g;
++ $class =~ s/Nwfilter/NWFilter/;
++ $class = "vir" . $class . "Ptr";
++
++ $class{$object} = $class;
++}
++
++my $objects = join ("|", @objects);
++
++my %opts;
++my $in_opts = 0;
++
++my %perms;
++
++while (<>) {
++ if ($in_opts) {
++ if (m,\*/,) {
++ $in_opts = 0;
++ } elsif (/\*\s*\@(\w+):\s*(.*?)\s*$/) {
++ $opts{$1} = $2;
++ }
++ } elsif (m,/\*\*,) {
++ $in_opts = 1;
++ } elsif (/VIR_ACCESS_PERM_($objects)_((?:\w|_)+),/) {
++ my $object = $1;
++ my $perm = lc $2;
++ next if $perm eq "last";
++
++ $perm =~ s/_/-/g;
++
++ $perms{$object} = {} unless exists $perms{$object};
++ $perms{$object}->{$perm} = {
++ desc => $opts{desc},
++ message => $opts{message},
++ anonymous => $opts{anonymous}
++ };
++ %opts = ();
++ }
++}
++
++print <<EOF;
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns="http://www.w3.org/1999/xhtml">
++ <body>
++EOF
++
++foreach my $object (sort { $a cmp $b } keys %perms) {
++ my $class = $class{$object};
++ my $olink = lc "object_" . $object;
++ print <<EOF;
++<h3><a name="$olink">$class</a></h3>
++<table class="acl">
++ <thead>
++ <tr>
++ <th>Permission</th>
++ <th>Description</th>
++ </tr>
++ </thead>
++ <tbody>
++EOF
++
++ foreach my $perm (sort { $a cmp $b } keys %{$perms{$object}}) {
++ my $description = $perms{$object}->{$perm}->{desc};
++
++ die "missing description for $object.$perm" unless
++ defined $description;
++
++ my $plink = lc "perm_" . $object . "_" . $perm;
++ $plink =~ s/-/_/g;
++
++ print <<EOF;
++ <tr>
++ <td><a name="$plink">$perm</a></td>
++ <td>$description</td>
++ </tr>
++EOF
++
++ }
++
++ print <<EOF;
++ </tbody>
++</table>
++EOF
++}
++
++print <<EOF;
++ </body>
++</html>
++EOF
+diff --git a/docs/newapi.xsl b/docs/newapi.xsl
+index 58f12eb..606d244 100644
+--- a/docs/newapi.xsl
++++ b/docs/newapi.xsl
+@@ -71,8 +71,8 @@
+
+ <xsl:template match="check" mode="acl">
+ <tr>
+- <td><xsl:value-of select="@object"/></td>
+- <td><xsl:value-of select="@perm"/></td>
++ <td><a href="../acl.html#object_{@object}"><xsl:value-of select="@object"/></a></td>
++ <td><a href="../acl.html#perm_{@object}_{@perm}"><xsl:value-of select="@perm"/></a></td>
+ <xsl:choose>
+ <xsl:when test="@flags">
+ <td><xsl:value-of select="@flags"/></td>
+diff --git a/docs/page.xsl b/docs/page.xsl
+index 7da34ff..a2da854 100644
+--- a/docs/page.xsl
++++ b/docs/page.xsl
+@@ -26,6 +26,10 @@
+ <xsl:call-template name="toc"/>
+ </xsl:template>
+
++ <xsl:template match="html:div[@id='include']" mode="content">
++ <xsl:call-template name="include"/>
++ </xsl:template>
++
+ <!-- This processes the sitemap to form a context sensitive
+ navigation menu for the current page -->
+ <xsl:template match="html:ul" mode="menu">
+@@ -174,4 +178,11 @@
+ </html>
+ </xsl:template>
+
++ <xsl:template name="include">
++ <xsl:variable name="inchtml">
++ <xsl:copy-of select="document(@filename)"/>
++ </xsl:variable>
++
++ <xsl:apply-templates select="exsl:node-set($inchtml)/html:html/html:body/*" mode="content"/>
++ </xsl:template>
+ </xsl:stylesheet>
+diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
+index fd10caf..a8d2177 100644
+--- a/docs/sitemap.html.in
++++ b/docs/sitemap.html.in
+@@ -69,6 +69,16 @@
+ <span>Configure authentication for the libvirt daemon</span>
+ </li>
+ <li>
++ <a href="acl.html">Access control</a>
++ <span>Configure access control libvirt APIs</span>
++ <ul>
++ <li>
++ <a href="aclpolkit.html">Polkit access control</a>
++ <span>Using polkit for API access control</span>
++ </li>
++ </ul>
++ </li>
++ <li>
+ <a href="migration.html">Migration</a>
+ <span>Migrating guests between machines</span>
+ </li>
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 8c6f068..b049895 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1654,7 +1654,7 @@ test_libvirt_lockd.aug: locking/test_libvirt_lockd.aug.in \
+
+ test_virtlockd.aug: locking/test_virtlockd.aug.in \
+ locking/virtlockd.conf $(AUG_GENTEST)
+- $(AM_V_GEN)$(AUG_GENTEST) locking/virtlockd.conf $< $@
++ $(AM_V_GEN)$(AUG_GENTEST) $(srcdir)/locking/virtlockd.conf $< $@
+
+ check-augeas-lockd: test_libvirt_lockd.aug
+ $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
+--
+1.8.3.2
+
--- /dev/null
+From ffe48a81783cc07e2f12e158e5b3985d1f313c9b Mon Sep 17 00:00:00 2001
+Message-Id: <ffe48a81783cc07e2f12e158e5b3985d1f313c9b.1383321464.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:41 +0000
+Subject: [PATCH] Add helpers for getting env vars in a setuid environment
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+Care must be taken accessing env variables when running
+setuid. Introduce a virGetEnvAllowSUID for env vars which
+are safe to use in a setuid environment, and another
+virGetEnvBlockSUID for vars which are not safe. Also add
+a virIsSUID helper method for any other non-env var code
+to use.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit ae53e5d10e434e07079d7e3ba11ec654ba6a256e)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ bootstrap.conf | 1 +
+ src/libvirt_private.syms | 3 +++
+ src/util/virutil.c | 39 +++++++++++++++++++++++++++++++++++++++
+ src/util/virutil.h | 4 ++++
+ 4 files changed, 47 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index f96f126..374a332 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2046,6 +2046,8 @@ virFindFCHostCapableVport;
+ virFormatIntDecimal;
+ virGetDeviceID;
+ virGetDeviceUnprivSGIO;
++virGetEnvAllowSUID;
++virGetEnvBlockSUID;
+ virGetFCHostNameByWWN;
+ virGetGroupID;
+ virGetGroupList;
+@@ -2064,6 +2066,7 @@ virIndexToDiskName;
+ virIsCapableFCHost;
+ virIsCapableVport;
+ virIsDevMapperDevice;
++virIsSUID;
+ virManageVport;
+ virParseNumber;
+ virParseOwnershipIds;
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index 3abcd53..a41117e 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -2096,3 +2096,42 @@ cleanup:
+
+ return rc;
+ }
++
++
++/**
++ * virGetEnvBlockSUID:
++ * @name: the environment variable name
++ *
++ * Obtain an environment variable which is unsafe to
++ * use when running setuid. If running setuid, a NULL
++ * value will be returned
++ */
++const char *virGetEnvBlockSUID(const char *name)
++{
++ return secure_getenv(name);
++}
++
++
++/**
++ * virGetEnvBlockSUID:
++ * @name: the environment variable name
++ *
++ * Obtain an environment variable which is safe to
++ * use when running setuid. The value will be returned
++ * even when running setuid
++ */
++const char *virGetEnvAllowSUID(const char *name)
++{
++ return getenv(name);
++}
++
++
++/**
++ * virIsSUID:
++ * Return a true value if running setuid. Does not
++ * check for elevated capabilities bits.
++ */
++bool virIsSUID(void)
++{
++ return getuid() != geteuid();
++}
+diff --git a/src/util/virutil.h b/src/util/virutil.h
+index 4b06992..8739e4e 100644
+--- a/src/util/virutil.h
++++ b/src/util/virutil.h
+@@ -172,4 +172,8 @@ int virCompareLimitUlong(unsigned long long a, unsigned long b);
+
+ int virParseOwnershipIds(const char *label, uid_t *uidPtr, gid_t *gidPtr);
+
++const char *virGetEnvBlockSUID(const char *name);
++const char *virGetEnvAllowSUID(const char *name);
++bool virIsSUID(void);
++
+ #endif /* __VIR_UTIL_H__ */
+--
+1.8.4.2
+
--- /dev/null
+From 87ab326e99c0c6b556bfff54a6e4e9bd09faa495 Mon Sep 17 00:00:00 2001
+Message-Id: <87ab326e99c0c6b556bfff54a6e4e9bd09faa495.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:38:26 +0100
+Subject: [PATCH] Add info about access control checks into API reference
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+So that app developers / admins know what access control checks
+are performed for each API, this patch extends the API docs
+generator to include details of the ACLs for each.
+
+The gendispatch.pl script is extended so that it generates
+a simple XML describing ACL rules, eg.
+
+ <aclinfo>
+ ...
+ <api name='virConnectNumOfDomains'>
+ <check object='connect' perm='search_domains'/>
+ <filter object='domain' perm='getattr'/>
+ </api>
+ <api name='virDomainAttachDeviceFlags'>
+ <check object='domain' perm='write'/>
+ <check object='domain' perm='save' flags='!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE'/>
+ <check object='domain' perm='save' flags='VIR_DOMAIN_AFFECT_CONFIG'/>
+ </api>
+ ...
+ </aclinfo>
+
+The newapi.xsl template loads the XML files containing the ACL
+rules and generates a short block of HTML for each API describing
+the parameter checks and return value filters (if any).
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 664ab2801dfcb8e72fc4408cc50c279bf74e47a2)
+---
+ .gitignore | 3 +++
+ docs/libvirt.css | 14 +++++++++++
+ docs/newapi.xsl | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/Makefile.am | 22 ++++++++++++++--
+ src/rpc/gendispatch.pl | 59 ++++++++++++++++++++++++++++++++++++++++---
+ 5 files changed, 160 insertions(+), 6 deletions(-)
+
+diff --git a/docs/libvirt.css b/docs/libvirt.css
+index 8a00d12..ed67b2f 100644
+--- a/docs/libvirt.css
++++ b/docs/libvirt.css
+@@ -477,3 +477,17 @@ dl.variablelist > dt {
+ dl.variablelist > dt:after {
+ content: ": ";
+ }
++
++table.acl {
++ margin: 1em;
++ border-spacing: 0px;
++ border: 1px solid #ccc;
++}
++
++table.acl tr, table.acl td {
++ padding: 0.3em;
++}
++
++table.acl thead {
++ background: #ddd;
++}
+diff --git a/docs/newapi.xsl b/docs/newapi.xsl
+index d5b210e..58f12eb 100644
+--- a/docs/newapi.xsl
++++ b/docs/newapi.xsl
+@@ -29,6 +29,69 @@
+ <xsl:variable name="htmldir">html</xsl:variable>
+ <xsl:variable name="href_base">../</xsl:variable>
+
++ <xsl:variable name="acls">
++ <xsl:copy-of select="document('../src/libvirt_access.xml')/aclinfo/api"/>
++ </xsl:variable>
++ <xsl:variable name="qemuacls">
++ <xsl:copy-of select="document('../src/libvirt_access_qemu.xml')/aclinfo/api"/>
++ </xsl:variable>
++ <xsl:variable name="lxcacls">
++ <xsl:copy-of select="document('../src/libvirt_access_lxc.xml')/aclinfo/api"/>
++ </xsl:variable>
++
++ <xsl:template name="aclinfo">
++ <xsl:param name="api"/>
++
++ <xsl:if test="count(exsl:node-set($acls)/api[@name=$api]/check) > 0">
++ <h5>Access control parameter checks</h5>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Object</th>
++ <th>Permission</th>
++ <th>Condition</th>
++ </tr>
++ </thead>
++ <xsl:apply-templates select="exsl:node-set($acls)/api[@name=$api]/check" mode="acl"/>
++ </table>
++ </xsl:if>
++ <xsl:if test="count(exsl:node-set($acls)/api[@name=$api]/filter) > 0">
++ <h5>Access control return value filters</h5>
++ <table class="acl">
++ <thead>
++ <tr>
++ <th>Object</th>
++ <th>Permission</th>
++ </tr>
++ </thead>
++ <xsl:apply-templates select="exsl:node-set($acls)/api[@name=$api]/filter" mode="acl"/>
++ </table>
++ </xsl:if>
++ </xsl:template>
++
++ <xsl:template match="check" mode="acl">
++ <tr>
++ <td><xsl:value-of select="@object"/></td>
++ <td><xsl:value-of select="@perm"/></td>
++ <xsl:choose>
++ <xsl:when test="@flags">
++ <td><xsl:value-of select="@flags"/></td>
++ </xsl:when>
++ <xsl:otherwise>
++ <td>-</td>
++ </xsl:otherwise>
++ </xsl:choose>
++ </tr>
++ </xsl:template>
++
++ <xsl:template match="filter" mode="acl">
++ <tr>
++ <td><xsl:value-of select="@object"/></td>
++ <td><xsl:value-of select="@perm"/></td>
++ </tr>
++ </xsl:template>
++
++
+ <xsl:template name="navbar">
+ <xsl:variable name="previous" select="preceding-sibling::file[1]"/>
+ <xsl:variable name="next" select="following-sibling::file[1]"/>
+@@ -553,6 +616,11 @@
+ </xsl:if>
+ </dl>
+ </xsl:if>
++ <div class="acl">
++ <xsl:call-template name="aclinfo">
++ <xsl:with-param name="api" select="$name"/>
++ </xsl:call-template>
++ </div>
+ </xsl:template>
+
+ <xsl:template match="exports" mode="toc">
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 12ca204..8c6f068 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -826,6 +826,11 @@ ACCESS_DRIVER_SYM_FILES = \
+ libvirt_access_qemu.syms \
+ libvirt_access_lxc.syms
+
++ACCESS_DRIVER_API_FILES = \
++ libvirt_access.xml \
++ libvirt_access_qemu.xml \
++ libvirt_access_lxc.xml
++
+ ACCESS_DRIVER_SOURCES = \
+ access/viraccessperm.h access/viraccessperm.c \
+ access/viraccessmanager.h access/viraccessmanager.c \
+@@ -1492,8 +1497,8 @@ EXTRA_DIST += $(ACCESS_DRIVER_POLKIT_SOURCES)
+ endif
+
+
+-BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED)
+-CLEANFILES += $(ACCESS_DRIVER_GENERATED)
++BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES)
++CLEANFILES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES)
+
+ libvirt_access.syms: $(srcdir)/rpc/gendispatch.pl \
+ $(REMOTE_PROTOCOL) Makefile.am
+@@ -1508,6 +1513,19 @@ libvirt_access_lxc.syms: $(srcdir)/rpc/gendispatch.pl \
+ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \
+ lxc LXC $(LXC_PROTOCOL) > $@
+
++libvirt_access.xml: $(srcdir)/rpc/gendispatch.pl \
++ $(REMOTE_PROTOCOL) Makefile.am
++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
++ remote REMOTE $(REMOTE_PROTOCOL) > $@
++libvirt_access_qemu.xml: $(srcdir)/rpc/gendispatch.pl \
++ $(QEMU_PROTOCOL) Makefile.am
++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
++ qemu QEMU $(QEMU_PROTOCOL) > $@
++libvirt_access_lxc.xml: $(srcdir)/rpc/gendispatch.pl \
++ $(LXC_PROTOCOL) Makefile.am
++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
++ lxc LXC $(LXC_PROTOCOL) > $@
++
+ $(srcdir)/access/viraccessapicheck.h: $(srcdir)/rpc/gendispatch.pl \
+ $(REMOTE_PROTOCOL) Makefile.am
+ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \
+diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
+index 8f41771..ac0c7ab 100755
+--- a/src/rpc/gendispatch.pl
++++ b/src/rpc/gendispatch.pl
+@@ -41,8 +41,8 @@ my $res = GetOptions("mode=s" => \$mode);
+ die "cannot parse command line options" unless $res;
+
+ die "unknown mode '$mode', expecting 'client', 'server', " .
+- "'aclheader', 'aclbody', 'aclsym' or 'debug'"
+- unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|debug)$/;
++ "'aclheader', 'aclbody', 'aclsym', 'aclapi' or 'debug'"
++ unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|aclapi|debug)$/;
+
+ my $structprefix = shift or die "missing struct prefix argument";
+ my $procprefix = shift or die "missing procedure prefix argument";
+@@ -351,6 +351,13 @@ if ($mode eq "aclsym") {
+ # Automatically generated by gendispatch.pl.
+ # Do not edit this file. Any changes you make will be lost.
+ __EOF__
++} elsif ($mode eq "aclapi") {
++ print <<__EOF__;
++<!--
++ - Automatically generated by gendispatch.pl.
++ - Do not edit this file. Any changes you make will be lost.
++ -->
++__EOF__
+ } else {
+ print <<__EOF__;
+ /* Automatically generated by gendispatch.pl.
+@@ -1641,7 +1648,8 @@ elsif ($mode eq "client") {
+ }
+ } elsif ($mode eq "aclheader" ||
+ $mode eq "aclbody" ||
+- $mode eq "aclsym") {
++ $mode eq "aclsym" ||
++ $mode eq "aclapi") {
+ my %generate = map { $_ => 1 } @autogen;
+ my @keys = keys %calls;
+
+@@ -1667,6 +1675,7 @@ elsif ($mode eq "client") {
+ foreach my $hdr (@headers) {
+ print "#include \"$hdr\"\n";
+ }
++ print "\n";
+ } elsif ($mode eq "aclbody") {
+ my $header = shift;
+ print "#include <config.h>\n";
+@@ -1676,8 +1685,12 @@ elsif ($mode eq "client") {
+ print "#include \"virerror.h\"\n";
+ print "\n";
+ print "#define VIR_FROM_THIS VIR_FROM_ACCESS\n";
++ print "\n";
++ } elsif ($mode eq "aclapi") {
++ print "<aclinfo>\n";
++ } else {
++ print "\n";
+ }
+- print "\n";
+
+ foreach (@keys) {
+ my $call = $calls{$_};
+@@ -1699,6 +1712,8 @@ elsif ($mode eq "client") {
+ print $apiname . "CheckACL;\n";
+ }
+ print $apiname . "EnsureACL;\n";
++ } elsif ($mode eq "aclapi") {
++ &generate_aclapi($call);
+ } else {
+ &generate_acl($call, $call->{acl}, "Ensure");
+ if (defined $call->{aclfilter}) {
+@@ -1835,5 +1850,41 @@ elsif ($mode eq "client") {
+ print "}\n\n";
+ }
+ }
++
++ sub generate_aclapi {
++ my $call = shift;
++
++ my $apiname = "vir" . $call->{ProcName};
++ if ($structprefix eq "qemu") {
++ $apiname =~ s/virDomain/virDomainQemu/;
++ } elsif ($structprefix eq "lxc") {
++ $apiname =~ s/virDomain/virDomainLxc/;
++ }
++
++ print " <api name='$apiname'>\n";
++
++ my $acl = $call->{acl};
++ foreach (@{$acl}) {
++ my @bits = split /:/;
++ print " <check object='$bits[0]' perm='$bits[1]'";
++ if (defined $bits[2]) {
++ print " flags='$bits[2]'";
++ }
++ print "/>\n";
++ }
++
++ my $aclfilter = $call->{aclfilter};
++ foreach (@{$aclfilter}) {
++ my @bits = split /:/;
++ print " <filter object='$bits[0]' perm='$bits[1]'/>\n";
++ }
++
++ print " </api>\n";
++ }
++
++ }
++
++ if ($mode eq "aclapi") {
++ print "</aclinfo>\n";
+ }
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 9e8eabdfdefe2d31282b7994d01c28dc8cd818e0 Mon Sep 17 00:00:00 2001
+Message-Id: <9e8eabdfdefe2d31282b7994d01c28dc8cd818e0.1378475168.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Thu, 5 Sep 2013 14:25:28 +0200
+Subject: [PATCH] Add '<nat>' element to '<forward>' network schemas
+
+Commits 905629f4 and 1716e7a6 have added support for specifying
+an IPv4 range and a port range to be used by NAT:
+<forward mode='nat'>
+ <nat>
+ <address start='10.20.30.40' end='10.20.30.44'/>
+ <port start='60000' end='65432'/>
+ </nat>
+</forward>
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1004364
+(cherry picked from commit 437b7944a81b648a15c657fef184f3bcd2427dac)
+
+Conflicts:
+ tests/networkxml2xmltest.c:
+ 4f595ba not backported (dns forwardPlainNames)
+
+A few spaces were needed in
+networkxml2xmlout/nat-network-forward-nat-address.xml
+because d8bd24a which removed them is not backported either.
+---
+ docs/schemas/network.rng | 26 +++++++++++++++++++++
+ docs/schemas/networkcommon.rng | 7 ++++++
+ .../nat-network-forward-nat-address.xml | 26 +++++++++++++++++++++
+ .../nat-network-forward-nat-address.xml | 27 ++++++++++++++++++++++
+ tests/networkxml2xmltest.c | 1 +
+ 5 files changed, 87 insertions(+)
+ create mode 100644 tests/networkxml2xmlin/nat-network-forward-nat-address.xml
+ create mode 100644 tests/networkxml2xmlout/nat-network-forward-nat-address.xml
+
+diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
+index ded8580..11adbac 100644
+--- a/docs/schemas/network.rng
++++ b/docs/schemas/network.rng
+@@ -160,6 +160,32 @@
+ <empty/>
+ </element>
+ </optional>
++ <optional>
++ <element name='nat'>
++ <interleave>
++ <optional>
++ <element name='address'>
++ <attribute name='start'>
++ <ref name='ipv4Addr'/>
++ </attribute>
++ <attribute name='end'>
++ <ref name='ipv4Addr'/>
++ </attribute>
++ </element>
++ </optional>
++ <optional>
++ <element name='port'>
++ <attribute name='start'>
++ <ref name='port'/>
++ </attribute>
++ <attribute name='end'>
++ <ref name='port'/>
++ </attribute>
++ </element>
++ </optional>
++ </interleave>
++ </element>
++ </optional>
+ </interleave>
+ </element>
+ </optional>
+diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng
+index e60f1fc..e26b7f3 100644
+--- a/docs/schemas/networkcommon.rng
++++ b/docs/schemas/networkcommon.rng
+@@ -217,4 +217,11 @@
+ </oneOrMore>
+ </element>
+ </define>
++
++ <define name='port'>
++ <data type='integer'>
++ <param name='minInclusive'>1</param>
++ <param name='maxInclusive'>65535</param>
++ </data>
++ </define>
+ </grammar>
+diff --git a/tests/networkxml2xmlin/nat-network-forward-nat-address.xml b/tests/networkxml2xmlin/nat-network-forward-nat-address.xml
+new file mode 100644
+index 0000000..403d058
+--- /dev/null
++++ b/tests/networkxml2xmlin/nat-network-forward-nat-address.xml
+@@ -0,0 +1,26 @@
++<network>
++ <name>default</name>
++ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
++ <bridge name="virbr0"/>
++ <forward mode="nat" dev="eth1">
++ <nat>
++ <address start='10.20.30.40' end='10.20.30.44'/>
++ <port start='60000' end='65432'/>
++ </nat>
++ </forward>
++ <ip address="192.168.122.1" netmask="255.255.255.0">
++ <dhcp>
++ <range start="192.168.122.2" end="192.168.122.254"/>
++ <host mac="00:16:3e:77:e2:ed" name="a.example.com" ip="192.168.122.10"/>
++ <host mac="00:16:3e:3e:a9:1a" name="b.example.com" ip="192.168.122.11"/>
++ </dhcp>
++ </ip>
++ <ip family="ipv4" address="192.168.123.1" netmask="255.255.255.0">
++ </ip>
++ <ip family="ipv6" address="2001:db8:ac10:fe01::1" prefix="64">
++ </ip>
++ <ip family="ipv6" address="2001:db8:ac10:fd01::1" prefix="64">
++ </ip>
++ <ip family="ipv4" address="10.24.10.1">
++ </ip>
++</network>
+diff --git a/tests/networkxml2xmlout/nat-network-forward-nat-address.xml b/tests/networkxml2xmlout/nat-network-forward-nat-address.xml
+new file mode 100644
+index 0000000..796220d
+--- /dev/null
++++ b/tests/networkxml2xmlout/nat-network-forward-nat-address.xml
+@@ -0,0 +1,27 @@
++<network>
++ <name>default</name>
++ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
++ <forward dev='eth1' mode='nat'>
++ <nat>
++ <address start='10.20.30.40' end='10.20.30.44'/>
++ <port start='60000' end='65432'/>
++ </nat>
++ <interface dev='eth1'/>
++ </forward>
++ <bridge name='virbr0' stp='on' delay='0' />
++ <ip address='192.168.122.1' netmask='255.255.255.0'>
++ <dhcp>
++ <range start='192.168.122.2' end='192.168.122.254' />
++ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
++ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
++ </dhcp>
++ </ip>
++ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
++ </ip>
++ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
++ </ip>
++ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
++ </ip>
++ <ip family='ipv4' address='10.24.10.1'>
++ </ip>
++</network>
+diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
+index 0dfed16..b48eed2 100644
+--- a/tests/networkxml2xmltest.c
++++ b/tests/networkxml2xmltest.c
+@@ -104,6 +104,7 @@ mymain(void)
+ DO_TEST("netboot-proxy-network");
+ DO_TEST("nat-network-dns-txt-record");
+ DO_TEST("nat-network-dns-hosts");
++ DO_TEST("nat-network-forward-nat-address");
+ DO_TEST("8021Qbh-net");
+ DO_TEST("direct-net");
+ DO_TEST("host-bridge-net");
+--
+1.8.3.2
+
--- /dev/null
+From 0a0b9b0e2553d2bc26e88dc07859029124562ce2 Mon Sep 17 00:00:00 2001
+Message-Id: <0a0b9b0e2553d2bc26e88dc07859029124562ce2.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:55 +0000
+Subject: [PATCH] Add stub getegid impl for platforms lacking it
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+We already have stubs for getuid, geteuid, getgid but
+not for getegid. Something in gnulib already does a
+check for it during configure, so we already have the
+HAVE_GETEGID macro defined.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit c566fa1ad007a280bdf5132f7f91010459036ff6)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virutil.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/util/virutil.h b/src/util/virutil.h
+index 8739e4e..2c8b0ec 100644
+--- a/src/util/virutil.h
++++ b/src/util/virutil.h
+@@ -108,6 +108,10 @@ static inline int geteuid (void) { return 0; }
+ static inline int getgid (void) { return 0; }
+ # endif
+
++# ifndef HAVE_GETEGID
++static inline int getegid (void) { return 0; }
++# endif
++
+ char *virGetHostname(void);
+
+ char *virGetUserDirectory(void);
+--
+1.8.4.2
+
--- /dev/null
+From d6a370721e1eb2bab9b5a7d66c6e4e935c69f30b Mon Sep 17 00:00:00 2001
+Message-Id: <d6a370721e1eb2bab9b5a7d66c6e4e935c69f30b.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 31 Jul 2013 19:48:18 +0100
+Subject: [PATCH] Add support for systemd cgroup mount
+
+https://bugzilla.redhat.com/show_bug.cgi?id=980929
+
+Systemd uses a named cgroup mount for tracking processes. Add
+it as another type of controller, albeit one which we have to
+special case in a number of places. In particular we must
+never create/delete directories there, nor add tasks. Essentially
+the systemd mount is to be considered read-only for libvirt.
+
+With this change both the virCgroupDetectPlacement and
+virCgroupCopyPlacement methods must be invoked. The copy
+placement method will copy setup for resource controllers
+only. The detect placement method will probe for any
+named controllers, or resource controllers not already
+setup.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+
+(cherry picked from commit aedd46e7e32956b4f360ba631b47064c2bafcbff)
+---
+ src/util/vircgroup.c | 68 +++++++++++++++++++++++++++++++++++++++------------
+ src/util/vircgroup.h | 1 +
+ tests/vircgrouptest.c | 9 +++++++
+ 3 files changed, 63 insertions(+), 15 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index f9007e3..0e8bb79 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -57,7 +57,8 @@
+
+ VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST,
+ "cpu", "cpuacct", "cpuset", "memory", "devices",
+- "freezer", "blkio", "net_cls", "perf_event");
++ "freezer", "blkio", "net_cls", "perf_event",
++ "name=systemd");
+
+ typedef enum {
+ VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */
+@@ -117,6 +118,9 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ char *tmp;
+
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++ continue;
++
+ if (!group->controllers[i].placement)
+ continue;
+
+@@ -331,6 +335,9 @@ static int virCgroupCopyPlacement(virCgroupPtr group,
+ if (!group->controllers[i].mountPoint)
+ continue;
+
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++ continue;
++
+ if (path[0] == '/') {
+ if (VIR_STRDUP(group->controllers[i].placement, path) < 0)
+ return -1;
+@@ -386,6 +393,8 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
+ int ret = -1;
+ char *procfile;
+
++ VIR_DEBUG("Detecting placement for pid %lld path %s",
++ (unsigned long long)pid, path);
+ if (pid == -1) {
+ if (VIR_STRDUP(procfile, "/proc/self/cgroup") < 0)
+ goto cleanup;
+@@ -422,6 +431,7 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
+ const char *typestr = virCgroupControllerTypeToString(i);
+ int typelen = strlen(typestr);
+ char *tmp = controllers;
++
+ while (tmp) {
+ char *next = strchr(tmp, ',');
+ int len;
+@@ -438,13 +448,20 @@ static int virCgroupDetectPlacement(virCgroupPtr group,
+ * selfpath=="/libvirt.service" + path="foo" -> "/libvirt.service/foo"
+ */
+ if (typelen == len && STREQLEN(typestr, tmp, len) &&
+- group->controllers[i].mountPoint != NULL) {
+- if (virAsprintf(&group->controllers[i].placement,
+- "%s%s%s", selfpath,
+- (STREQ(selfpath, "/") ||
+- STREQ(path, "") ? "" : "/"),
+- path) < 0)
+- goto cleanup;
++ group->controllers[i].mountPoint != NULL &&
++ group->controllers[i].placement == NULL) {
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
++ if (VIR_STRDUP(group->controllers[i].placement,
++ selfpath) < 0)
++ goto cleanup;
++ } else {
++ if (virAsprintf(&group->controllers[i].placement,
++ "%s%s%s", selfpath,
++ (STREQ(selfpath, "/") ||
++ STREQ(path, "") ? "" : "/"),
++ path) < 0)
++ goto cleanup;
++ }
+ }
+
+ tmp = next;
+@@ -535,13 +552,16 @@ static int virCgroupDetect(virCgroupPtr group,
+ return -1;
+ }
+
+- if (parent || path[0] == '/') {
+- if (virCgroupCopyPlacement(group, path, parent) < 0)
+- return -1;
+- } else {
+- if (virCgroupDetectPlacement(group, pid, path) < 0)
+- return -1;
+- }
++ /* In some cases we can copy part of the placement info
++ * based on the parent cgroup...
++ */
++ if ((parent || path[0] == '/') &&
++ virCgroupCopyPlacement(group, path, parent) < 0)
++ return -1;
++
++ /* ... but use /proc/cgroups to fill in the rest */
++ if (virCgroupDetectPlacement(group, pid, path) < 0)
++ return -1;
+
+ /* Check that for every mounted controller, we found our placement */
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+@@ -833,6 +853,12 @@ static int virCgroupMakeGroup(virCgroupPtr parent,
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ char *path = NULL;
+
++ /* We must never mkdir() in systemd's hierarchy */
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
++ VIR_DEBUG("Not creating systemd controller group");
++ continue;
++ }
++
+ /* Skip over controllers that aren't mounted */
+ if (!group->controllers[i].mountPoint) {
+ VIR_DEBUG("Skipping unmounted controller %s",
+@@ -1037,6 +1063,10 @@ int virCgroupRemove(virCgroupPtr group)
+ if (!group->controllers[i].mountPoint)
+ continue;
+
++ /* We must never rmdir() in systemd's hierarchy */
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++ continue;
++
+ /* Don't delete the root group, if we accidentally
+ ended up in it for some reason */
+ if (STREQ(group->controllers[i].placement, "/"))
+@@ -1076,6 +1106,10 @@ int virCgroupAddTask(virCgroupPtr group, pid_t pid)
+ if (!group->controllers[i].mountPoint)
+ continue;
+
++ /* We must never add tasks in systemd's hierarchy */
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++ continue;
++
+ if (virCgroupSetValueU64(group, i, "tasks", (unsigned long long)pid) < 0)
+ goto cleanup;
+ }
+@@ -1177,6 +1211,10 @@ int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr dest_group)
+ !dest_group->controllers[i].mountPoint)
+ continue;
+
++ /* We must never move tasks in systemd's hierarchy */
++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++ continue;
++
+ /* New threads are created in the same group as their parent;
+ * but if a thread is created after we first read we aren't
+ * aware that it needs to move. Therefore, we must iterate
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index 3aaf081..e579f41 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -40,6 +40,7 @@ enum {
+ VIR_CGROUP_CONTROLLER_BLKIO,
+ VIR_CGROUP_CONTROLLER_NET_CLS,
+ VIR_CGROUP_CONTROLLER_PERF_EVENT,
++ VIR_CGROUP_CONTROLLER_SYSTEMD,
+
+ VIR_CGROUP_CONTROLLER_LAST
+ };
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 20ac494..4bdd4c9 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -87,6 +87,7 @@ const char *mountsSmall[VIR_CGROUP_CONTROLLER_LAST] = {
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
+ [VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL,
+ };
+ const char *mountsFull[VIR_CGROUP_CONTROLLER_LAST] = {
+ [VIR_CGROUP_CONTROLLER_CPU] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
+@@ -96,6 +97,7 @@ const char *mountsFull[VIR_CGROUP_CONTROLLER_LAST] = {
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/not/really/sys/fs/cgroup/freezer",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/not/really/sys/fs/cgroup/blkio",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/not/really/sys/fs/cgroup/systemd",
+ };
+
+ const char *links[VIR_CGROUP_CONTROLLER_LAST] = {
+@@ -121,6 +123,7 @@ static int testCgroupNewForSelf(const void *args ATTRIBUTE_UNUSED)
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if (virCgroupNewSelf(&cgroup) < 0) {
+@@ -161,6 +164,7 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED)
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
+ [VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL,
+ };
+ const char *placementFull[VIR_CGROUP_CONTROLLER_LAST] = {
+ [VIR_CGROUP_CONTROLLER_CPU] = "/virtualmachines.partition",
+@@ -170,6 +174,7 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED)
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/virtualmachines.partition",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/virtualmachines.partition",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if ((rv = virCgroupNewPartition("/virtualmachines", false, -1, &cgroup)) != -1) {
+@@ -233,6 +238,7 @@ static int testCgroupNewForPartitionNested(const void *args ATTRIBUTE_UNUSED)
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/deployment.partition/production.partition",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/deployment.partition/production.partition",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if ((rv = virCgroupNewPartition("/deployment/production", false, -1, &cgroup)) != -1) {
+@@ -281,6 +287,7 @@ static int testCgroupNewForPartitionNestedDeep(const void *args ATTRIBUTE_UNUSED
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/user/berrange.user/production.partition",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/user/berrange.user/production.partition",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if ((rv = virCgroupNewPartition("/user/berrange.user/production", false, -1, &cgroup)) != -1) {
+@@ -336,6 +343,7 @@ static int testCgroupNewForPartitionDomain(const void *args ATTRIBUTE_UNUSED)
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/production.partition/foo.libvirt-lxc",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/production.partition/foo.libvirt-lxc",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if ((rv = virCgroupNewPartition("/production", true, -1, &partitioncgroup)) != 0) {
+@@ -372,6 +380,7 @@ static int testCgroupNewForPartitionDomainEscaped(const void *args ATTRIBUTE_UNU
+ [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+ [VIR_CGROUP_CONTROLLER_FREEZER] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
+ [VIR_CGROUP_CONTROLLER_BLKIO] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123",
+ };
+
+ if ((rv = virCgroupNewPartition("/cgroup.evil", true, -1, &partitioncgroup1)) != 0) {
+--
+1.8.3.2
+
--- /dev/null
+From 13572b2c50e079c5618870af7ae64bf3a73154d7 Mon Sep 17 00:00:00 2001
+Message-Id: <13572b2c50e079c5618870af7ae64bf3a73154d7.1379597659.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 28 Aug 2013 15:25:40 +0100
+Subject: [PATCH] Add support for using 3-arg pkcheck syntax for process
+
+CVE-2013-4311
+
+With the existing pkcheck (pid, start time) tuple for identifying
+the process, there is a race condition, where a process can make
+a libvirt RPC call and in another thread exec a setuid application,
+causing it to change to effective UID 0. This in turn causes polkit
+to do its permission check based on the wrong UID.
+
+To address this, libvirt must get the UID the caller had at time
+of connect() (from SO_PEERCRED) and pass a (pid, start time, uid)
+triple to the pkcheck program.
+
+This fix requires that libvirt is re-built against a version of
+polkit that has the fix for its CVE-2013-4288, so that libvirt
+can see 'pkg-config --variable pkcheck_supports_uid polkit-gobject-1'
+
+Signed-off-by: Colin Walters <walters@redhat.com>
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 922b7fda77b094dbf022d625238262ea05335666)
+---
+ configure.ac | 8 ++++++++
+ daemon/remote.c | 22 ++++++++++++++++++---
+ libvirt.spec.in | 7 ++++---
+ src/access/viraccessdriverpolkit.c | 40 +++++++++++++++++++++++++++++++++-----
+ 4 files changed, 66 insertions(+), 11 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 917db6a..7dd6ca3 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1166,6 +1166,14 @@ if test "x$with_polkit" = "xyes" || test "x$with_polkit" = "xcheck"; then
+ AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH])
+ if test "x$PKCHECK_PATH" != "x" ; then
+ AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program])
++ AC_MSG_CHECKING([whether pkcheck supports uid value])
++ pkcheck_supports_uid=`$PKG_CONFIG --variable pkcheck_supports_uid polkit-gobject-1`
++ if test "x$pkcheck_supports_uid" = "xtrue"; then
++ AC_MSG_RESULT([yes])
++ AC_DEFINE_UNQUOTED([PKCHECK_SUPPORTS_UID], 1, [Pass uid to pkcheck])
++ else
++ AC_MSG_RESULT([no])
++ fi
+ AC_DEFINE_UNQUOTED([WITH_POLKIT], 1,
+ [use PolicyKit for UNIX socket access checks])
+ AC_DEFINE_UNQUOTED([WITH_POLKIT1], 1,
+diff --git a/daemon/remote.c b/daemon/remote.c
+index 6ace7af..b5395dd 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -2738,10 +2738,12 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED,
+ int status = -1;
+ char *ident = NULL;
+ bool authdismissed = 0;
++ bool supportsuid = false;
+ char *pkout = NULL;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+ virCommandPtr cmd = NULL;
++ static bool polkitInsecureWarned;
+
+ virMutexLock(&priv->lock);
+ action = virNetServerClientGetReadonly(client) ?
+@@ -2763,14 +2765,28 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED,
+ goto authfail;
+ }
+
++ if (timestamp == 0) {
++ VIR_WARN("Failing polkit auth due to missing client (pid=%lld) start time",
++ (long long)callerPid);
++ goto authfail;
++ }
++
+ VIR_INFO("Checking PID %lld running as %d",
+ (long long) callerPid, callerUid);
+
+ virCommandAddArg(cmd, "--process");
+- if (timestamp != 0) {
+- virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp);
++# ifdef PKCHECK_SUPPORTS_UID
++ supportsuid = true;
++# endif
++ if (supportsuid) {
++ virCommandAddArgFormat(cmd, "%lld,%llu,%lu",
++ (long long) callerPid, timestamp, (unsigned long) callerUid);
+ } else {
+- virCommandAddArgFormat(cmd, "%lld", (long long) callerPid);
++ if (!polkitInsecureWarned) {
++ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure.");
++ polkitInsecureWarned = true;
++ }
++ virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp);
+ }
+ virCommandAddArg(cmd, "--allow-user-interaction");
+
+diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c
+index b472bc3..ff82583 100644
+--- a/src/access/viraccessdriverpolkit.c
++++ b/src/access/viraccessdriverpolkit.c
+@@ -72,8 +72,12 @@ static char *
+ virAccessDriverPolkitFormatProcess(const char *actionid)
+ {
+ virIdentityPtr identity = virIdentityGetCurrent();
+- const char *process = NULL;
++ const char *callerPid = NULL;
++ const char *callerTime = NULL;
++ const char *callerUid = NULL;
+ char *ret = NULL;
++ bool supportsuid = false;
++ static bool polkitInsecureWarned;
+
+ if (!identity) {
+ virAccessError(VIR_ERR_ACCESS_DENIED,
+@@ -81,17 +85,43 @@ virAccessDriverPolkitFormatProcess(const char *actionid)
+ actionid);
+ return NULL;
+ }
+- if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &process) < 0)
++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &callerPid) < 0)
++ goto cleanup;
++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, &callerTime) < 0)
++ goto cleanup;
++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_USER_ID, &callerUid) < 0)
+ goto cleanup;
+
+- if (!process) {
++ if (!callerPid) {
+ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No UNIX process ID available"));
+ goto cleanup;
+ }
+-
+- if (VIR_STRDUP(ret, process) < 0)
++ if (!callerTime) {
++ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("No UNIX process start time available"));
++ goto cleanup;
++ }
++ if (!callerUid) {
++ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("No UNIX caller UID available"));
+ goto cleanup;
++ }
++
++#ifdef PKCHECK_SUPPORTS_UID
++ supportsuid = true;
++#endif
++ if (supportsuid) {
++ if (virAsprintf(&ret, "%s,%s,%s", callerPid, callerTime, callerUid) < 0)
++ goto cleanup;
++ } else {
++ if (!polkitInsecureWarned) {
++ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure.");
++ polkitInsecureWarned = true;
++ }
++ if (virAsprintf(&ret, "%s,%s", callerPid, callerTime) < 0)
++ goto cleanup;
++ }
+
+ cleanup:
+ virObjectUnref(identity);
+--
+1.8.3.2
+
--- /dev/null
+From fe2d3ff5afa8c3c25a55a03690ebe844344d4636 Mon Sep 17 00:00:00 2001
+Message-Id: <fe2d3ff5afa8c3c25a55a03690ebe844344d4636.1379193141.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Thu, 12 Sep 2013 11:05:22 +0200
+Subject: [PATCH] Add test for the nodemask double free crash
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006722
+
+Commit ef5d51d fixed a crash for numatune with auto placement and
+nodeset specified:
+<numatune>
+ <memory mode='preferred' placement='auto' nodeset='0'/>
+</numatune>
+(cherry picked from commit fd72440a356bcfc205afcf5ab988e774610b2499)
+
+Commit a216e64 qemu: Set QEMU_AUDIO_DRV=none with -nographic
+is not backported.
+---
+ ...qemuxml2argv-numatune-auto-nodeset-invalid.args | 4 +++
+ .../qemuxml2argv-numatune-auto-nodeset-invalid.xml | 31 ++++++++++++++++++++++
+ tests/qemuxml2argvtest.c | 1 +
+ 3 files changed, 36 insertions(+)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml
+
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args
+new file mode 100644
+index 0000000..11db342
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args
+@@ -0,0 +1,4 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
++/usr/bin/qemu -S -M pc -m 214 -smp 2 -nographic \
++-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
++-hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml
+new file mode 100644
+index 0000000..d2315b4
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml
+@@ -0,0 +1,31 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219136</memory>
++ <currentMemory unit='KiB'>219136</currentMemory>
++ <vcpu placement='static' cpuset='0-1'>2</vcpu>
++ <numatune>
++ <memory mode='preferred' placement='auto' nodeset="0-5,^4"/>
++ </numatune>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <cpu>
++ <topology sockets='2' cores='1' threads='1'/>
++ </cpu>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</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='ide' index='0'/>
++ <memballoon model='virtio'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 3a3c304..ca72947 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -902,6 +902,7 @@ mymain(void)
+ DO_TEST("blkiotune-device", QEMU_CAPS_NAME);
+ DO_TEST("cputune", QEMU_CAPS_NAME);
+ DO_TEST("numatune-memory", NONE);
++ DO_TEST("numatune-auto-nodeset-invalid", NONE);
+ DO_TEST("numad", NONE);
+ DO_TEST("numad-auto-vcpu-static-numatune", NONE);
+ DO_TEST("numad-auto-memory-vcpu-cpuset", NONE);
+--
+1.8.3.2
+
--- /dev/null
+From b76dda6c153e1251de6aa935b85942bb53213470 Mon Sep 17 00:00:00 2001
+Message-Id: <b76dda6c153e1251de6aa935b85942bb53213470.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 15:20:43 +0100
+Subject: [PATCH] Address missed feedback from review of virt-login-shell
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=988491
+
+Address a number of code, style and docs issues identified
+in review of virt-login-shell after it was merged.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit a396473494dd099c2a0e6e03af9a9c7406a86108)
+---
+ tools/Makefile.am | 1 -
+ tools/virt-login-shell.c | 58 ++++++++++++++++++++++++++++++----------------
+ tools/virt-login-shell.pod | 30 ++++++++++++++++++------
+ 3 files changed, 61 insertions(+), 28 deletions(-)
+
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index 00c582a..d48883c 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -134,7 +134,6 @@ virt_host_validate_CFLAGS = \
+ $(NULL)
+
+ virt_login_shell_SOURCES = \
+- virt-login-shell.conf \
+ virt-login-shell.c
+
+ virt_login_shell_LDFLAGS = $(COVERAGE_LDFLAGS)
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+index b27e44f..1157cd0 100644
+--- a/tools/virt-login-shell.c
++++ b/tools/virt-login-shell.c
+@@ -41,11 +41,11 @@
+ #include "vircommand.h"
+ #define VIR_FROM_THIS VIR_FROM_NONE
+
+-static ssize_t nfdlist = 0;
+-static int *fdlist = NULL;
++static ssize_t nfdlist;
++static int *fdlist;
+ static const char *conf_file = SYSCONFDIR "/libvirt/virt-login-shell.conf";
+
+-static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom)
++static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom)
+ {
+ size_t i;
+
+@@ -105,7 +105,7 @@ static int virLoginShellAllowedUser(virConfPtr conf,
+ }
+ }
+ }
+- virReportSystemError(EPERM, _("%s not listed as an allowed_users in %s"), name, conf_file);
++ virReportSystemError(EPERM, _("%s not matched against 'allowed_users' in %s"), name, conf_file);
+ cleanup:
+ VIR_FREE(gname);
+ return ret;
+@@ -121,7 +121,7 @@ static char **virLoginShellGetShellArgv(virConfPtr conf)
+ if (!p)
+ return virStringSplit("/bin/sh -l", " ", 3);
+
+- if (p && p->type == VIR_CONF_LIST) {
++ if (p->type == VIR_CONF_LIST) {
+ size_t len;
+ virConfValuePtr pp;
+
+@@ -139,7 +139,6 @@ static char **virLoginShellGetShellArgv(virConfPtr conf)
+ if (VIR_STRDUP(shargv[i], pp->str) < 0)
+ goto error;
+ }
+- shargv[len] = NULL;
+ }
+ return shargv;
+ error:
+@@ -155,16 +154,27 @@ static char *progname;
+ static void
+ usage(void)
+ {
+- fprintf(stdout, _("\n"
+- "%s is a privileged program that allows non root users \n"
+- "specified in %s to join a Linux container \n"
+- "with a matching user name and launch a shell. \n"
+- "\n%s [options]\n\n"
+- " options:\n"
+- " -h | --help this help:\n\n"), progname, conf_file, progname);
++ fprintf(stdout,
++ _("\n"
++ "Usage:\n"
++ " %s [options]\n\n"
++ "Options:\n"
++ " -h | --help Display program help:\n"
++ " -V | --version Display program version:\n"
++ "\n"
++ "libvirt login shell\n"),
++ progname);
+ return;
+ }
+
++/* Display version information. */
++static void
++show_version(void)
++{
++ printf("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
++}
++
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -190,6 +200,7 @@ main(int argc, char **argv)
+
+ struct option opt[] = {
+ {"help", no_argument, NULL, 'h'},
++ {"version", optional_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+ if (virInitialize() < 0) {
+@@ -214,20 +225,25 @@ main(int argc, char **argv)
+ return ret;
+ }
+
+- /* The only option we support is help
+- */
+- while ((arg = getopt_long(argc, argv, "h", opt, &longindex)) != -1) {
++ while ((arg = getopt_long(argc, argv, "hV", opt, &longindex)) != -1) {
+ switch (arg) {
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+- break;
++
++ case 'V':
++ show_version();
++ exit(EXIT_SUCCESS);
++
++ case '?':
++ default:
++ usage();
++ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (argc > optind) {
+ virReportSystemError(EINVAL, _("%s takes no options"), progname);
+- errno = EINVAL;
+ goto cleanup;
+ }
+
+@@ -268,7 +284,9 @@ main(int argc, char **argv)
+ virErrorPtr last_error;
+ last_error = virGetLastError();
+ if (last_error->code != VIR_ERR_OPERATION_INVALID) {
+- virReportSystemError(last_error->code,_("Can't create %s container: %s"), name, virGetLastErrorMessage());
++ virReportSystemError(last_error->code,
++ _("Can't create %s container: %s"),
++ name, last_error->message);
+ goto cleanup;
+ }
+ }
+@@ -327,7 +345,7 @@ main(int argc, char **argv)
+ }
+ if (execv(shargv[0], (char *const*) shargv) < 0) {
+ virReportSystemError(errno, _("Unable exec shell %s"), shargv[0]);
+- return -errno;
++ return EXIT_FAILURE;
+ }
+ }
+ return virProcessWait(ccpid, &status2);
+diff --git a/tools/virt-login-shell.pod b/tools/virt-login-shell.pod
+index 0cd35cf..e27d500 100644
+--- a/tools/virt-login-shell.pod
++++ b/tools/virt-login-shell.pod
+@@ -8,26 +8,42 @@ B<virt-login-shell>
+
+ =head1 DESCRIPTION
+
+-The B<virt-login-shell> program is setuid shell that is used to join
+-an LXC container that matches the users name. If the container is not
+-running virt-login-shell will attempt to start the container.
++The B<virt-login-shell> program is a setuid shell that is used to join
++an LXC container that matches the user's name. If the container is not
++running, virt-login-shell will attempt to start the container.
+ virt-sandbox-shell is not allowed to be run by root. Normal users will get
+-added to a container that matches their username, if it exists. And they are
++added to a container that matches their username, if it exists, and they are
+ configured in /etc/libvirt/virt-login-shell.conf.
+
+ The basic structure of most virt-login-shell usage is:
+
+ virt-login-shell
+
++=head1 OPTIONS
++
++=over
++
++=item B<-h, --help>
++
++Display command line help usage then exit.
++
++=item B<-V, --version>
++
++Display version information then exit.
++
++=back
++
+ =head1 CONFIG
+
+ By default, virt-login-shell will execute the /bin/sh program for the user.
+-You can modify this behaviour by defining the shell variable in /etc/libvirt/virt-login-shell.conf.
++You can modify this behaviour by defining the shell variable in
++/etc/libvirt/virt-login-shell.conf.
+
+ eg. shell = [ "/bin/ksh", "--login"]
+
+-By default no users are allowed to user virt-login-shell, if you want to allow
+-certain users to use virt-login-shell, you need to modify the allowed_users variable in /etc/libvirt/virt-login-shell.conf.
++By default no users are allowed to use virt-login-shell, if you want to allow
++certain users to use virt-login-shell, you need to modify the allowed_users
++variable in /etc/libvirt/virt-login-shell.conf.
+
+ eg. allowed_users = [ "tom", "dick", "harry" ]
+
+--
+1.8.3.2
+
--- /dev/null
+From 68d414af5fc764e92cc3beadc700964fdb348b1b Mon Sep 17 00:00:00 2001
+Message-Id: <68d414af5fc764e92cc3beadc700964fdb348b1b.1382534060.git.jdenemar@redhat.com>
+From: Claudio Bley <cbley@av-test.de>
+Date: Wed, 16 Oct 2013 23:12:56 +0800
+Subject: [PATCH] Adjust legacy max payload size to account for header
+ information
+
+https://bugzilla.redhat.com/show_bug.cgi?id=950416
+
+Commit 27e81517a87 set the payload size to 256 KB, which is
+actually the max packet size, including the size of the header.
+
+Reduce this by VIR_NET_MESSAGE_HEADER_MAX (24) and set
+VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX to 262120, which was the original
+value before increasing the limit in commit eb635de1fed.
+(cherry picked from commit 609eb987c6cef9082486e66b666f7b9351b783ed)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/rpc/virnetprotocol.x | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x
+index 1eae7cb..7b6f753 100644
+--- a/src/rpc/virnetprotocol.x
++++ b/src/rpc/virnetprotocol.x
+@@ -55,7 +55,7 @@ const VIR_NET_MESSAGE_INITIAL = 65536;
+ * payload size. We need to remember this for compat with
+ * old clients.
+ */
+-const VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX = 262144;
++const VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX = 262120;
+
+ /* Maximum total message size (serialised). */
+ const VIR_NET_MESSAGE_MAX = 16777216;
+--
+1.8.4
+
--- /dev/null
+From 88c5f4f82ea78857962ff3bd601aaa25dcb7d8bf Mon Sep 17 00:00:00 2001
+Message-Id: <88c5f4f82ea78857962ff3bd601aaa25dcb7d8bf.1383922565.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Thu, 7 Nov 2013 18:55:21 +0100
+Subject: [PATCH] Allow root directory in filesystem source dir schema
+
+Use absDirPath instead of absFilePath.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1028107
+(cherry picked from commit eab51940bd9d3b5f8b73f52c50ba6d00648f0909)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/schemas/domaincommon.rng | 4 ++--
+ tests/lxcxml2xmldata/lxc-filesystem-ram.xml | 4 ++++
+ tests/lxcxml2xmldata/lxc-filesystem-root.xml | 25 +++++++++++++++++++++++++
+ tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml | 4 ++++
+ tests/lxcxml2xmltest.c | 1 +
+ 5 files changed, 36 insertions(+), 2 deletions(-)
+ create mode 100644 tests/lxcxml2xmldata/lxc-filesystem-root.xml
+
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 5540745..c7eaf00 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -1628,7 +1628,7 @@
+ <interleave>
+ <element name="source">
+ <attribute name="dir">
+- <ref name="absFilePath"/>
++ <ref name="absDirPath"/>
+ </attribute>
+ <empty/>
+ </element>
+@@ -1646,7 +1646,7 @@
+ <interleave>
+ <element name="source">
+ <attribute name="dir">
+- <ref name="absFilePath"/>
++ <ref name="absDirPath"/>
+ </attribute>
+ <empty/>
+ </element>
+diff --git a/tests/lxcxml2xmldata/lxc-filesystem-ram.xml b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml
+index 002fde6..58ae344 100644
+--- a/tests/lxcxml2xmldata/lxc-filesystem-ram.xml
++++ b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml
+@@ -14,6 +14,10 @@
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/libexec/libvirt_lxc</emulator>
++ <filesystem type='bind'>
++ <source dir='/'/>
++ <target dir='/'/>
++ </filesystem>
+ <filesystem type='ram'>
+ <source usage='1048576'/>
+ <target dir='/mnt/mississippi'/>
+diff --git a/tests/lxcxml2xmldata/lxc-filesystem-root.xml b/tests/lxcxml2xmldata/lxc-filesystem-root.xml
+new file mode 100644
+index 0000000..1ce2b32
+--- /dev/null
++++ b/tests/lxcxml2xmldata/lxc-filesystem-root.xml
+@@ -0,0 +1,25 @@
++<domain type='lxc'>
++ <name>demo</name>
++ <uuid>8369f1ac-7e46-e869-4ca5-759d51478066</uuid>
++ <memory unit='KiB'>500000</memory>
++ <currentMemory unit='KiB'>500000</currentMemory>
++ <vcpu placement='static'>1</vcpu>
++ <os>
++ <type arch='x86_64'>exe</type>
++ <init>/bin/sh</init>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/libvirt_lxc</emulator>
++ <filesystem type='mount' accessmode='passthrough'>
++ <source dir='/'/>
++ <target dir='/'/>
++ </filesystem>
++ <console type='pty'>
++ <target type='lxc' port='0'/>
++ </console>
++ </devices>
++</domain>
+diff --git a/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
+index d2369a2..93162b3 100644
+--- a/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
++++ b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
+@@ -14,6 +14,10 @@
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/libexec/libvirt_lxc</emulator>
++ <filesystem type='bind' accessmode='passthrough'>
++ <source dir='/'/>
++ <target dir='/'/>
++ </filesystem>
+ <filesystem type='ram' accessmode='passthrough'>
+ <source usage='1048576' units='KiB'/>
+ <target dir='/mnt/mississippi'/>
+diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
+index f8b5959..8f66f82 100644
+--- a/tests/lxcxml2xmltest.c
++++ b/tests/lxcxml2xmltest.c
+@@ -132,6 +132,7 @@ mymain(void)
+ DO_TEST("hostdev");
+ DO_TEST("disk-formats");
+ DO_TEST_DIFFERENT("filesystem-ram");
++ DO_TEST("filesystem-root");
+
+ virObjectUnref(caps);
+ virObjectUnref(xmlopt);
+--
+1.8.4.2
+
--- /dev/null
+From 00c107bc1ef5a9ab3ad04f15d87fa529c17efefb Mon Sep 17 00:00:00 2001
+Message-Id: <00c107bc1ef5a9ab3ad04f15d87fa529c17efefb.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:17 +0100
+Subject: [PATCH] Allow use of a private dbus bus connection
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=998365
+
+The dbus_bus_get() function returns a shared bus connection that
+all libraries in a process can use. You are forbidden from calling
+close on this connection though, since you can never know if any
+other code might be using it.
+
+Add an option to use private dbus bus connections, if the app
+wants to be able to close the connection.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 0cb774f051a3549dd3968e6f48b36e6f93ac79fc)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 1 +
+ src/util/virdbus.c | 16 +++++++++++++++-
+ src/util/virdbus.h | 2 ++
+ 3 files changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index d9561b8..c91a9f9 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1298,6 +1298,7 @@ virDBusHasSystemBus;
+ virDBusMessageDecode;
+ virDBusMessageEncode;
+ virDBusMessageRead;
++virDBusSetSharedBus;
+
+
+ # util/virdnsmasq.h
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index a2c4b4e..bcc5b1c 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -32,6 +32,7 @@
+
+ #ifdef WITH_DBUS
+
++static bool sharedBus = true;
+ static DBusConnection *systembus = NULL;
+ static DBusConnection *sessionbus = NULL;
+ static virOnceControl systemonce = VIR_ONCE_CONTROL_INITIALIZER;
+@@ -43,6 +44,11 @@ static dbus_bool_t virDBusAddWatch(DBusWatch *watch, void *data);
+ static void virDBusRemoveWatch(DBusWatch *watch, void *data);
+ static void virDBusToggleWatch(DBusWatch *watch, void *data);
+
++void virDBusSetSharedBus(bool shared)
++{
++ sharedBus = shared;
++}
++
+ static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr)
+ {
+ DBusConnection *bus;
+@@ -52,7 +58,10 @@ static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr)
+ dbus_threads_init_default();
+
+ dbus_error_init(dbuserr);
+- if (!(bus = dbus_bus_get(type, dbuserr)))
++ bus = sharedBus ?
++ dbus_bus_get(type, dbuserr) :
++ dbus_bus_get_private(type, dbuserr);
++ if (!bus)
+ return NULL;
+
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+@@ -1264,6 +1273,11 @@ int virDBusIsServiceEnabled(const char *name)
+
+
+ #else /* ! WITH_DBUS */
++void virDBusSetSharedBus(bool shared ATTRIBUTE_UNUSED)
++{
++ /* nothing */
++}
++
+ DBusConnection *virDBusGetSystemBus(void)
+ {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+diff --git a/src/util/virdbus.h b/src/util/virdbus.h
+index 194a01a..125a405 100644
+--- a/src/util/virdbus.h
++++ b/src/util/virdbus.h
+@@ -31,6 +31,8 @@
+ # endif
+ # include "internal.h"
+
++void virDBusSetSharedBus(bool shared);
++
+ DBusConnection *virDBusGetSystemBus(void);
+ bool virDBusHasSystemBus(void);
+ DBusConnection *virDBusGetSessionBus(void);
+--
+1.8.3.2
+
--- /dev/null
+From 0401b6b48f3743fb819cfe494d1b23ecb8796198 Mon Sep 17 00:00:00 2001
+Message-Id: <0401b6b48f3743fb819cfe494d1b23ecb8796198.1379597659.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 22 Aug 2013 16:00:01 +0100
+Subject: [PATCH] Also store user & group ID values in virIdentity
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006272
+
+Future improvements to the polkit code will require access to
+the numeric user ID, not merely user name.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit db7a5688c05f3fd60d9d2b74c72427eb9ee9c176)
+---
+ src/rpc/virnetserverclient.c | 18 ++++++++++++++++++
+ src/util/viridentity.c | 23 +++++++++++++++++++----
+ src/util/viridentity.h | 2 ++
+ 3 files changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
+index 83d5cf1..19c4100 100644
+--- a/src/rpc/virnetserverclient.c
++++ b/src/rpc/virnetserverclient.c
+@@ -652,7 +652,9 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
+ char *processid = NULL;
+ char *processtime = NULL;
+ char *username = NULL;
++ char *userid = NULL;
+ char *groupname = NULL;
++ char *groupid = NULL;
+ #if WITH_SASL
+ char *saslname = NULL;
+ #endif
+@@ -672,8 +674,12 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
+
+ if (!(username = virGetUserName(uid)))
+ goto cleanup;
++ if (virAsprintf(&userid, "%d", (int)uid) < 0)
++ goto cleanup;
+ if (!(groupname = virGetGroupName(gid)))
+ goto cleanup;
++ if (virAsprintf(&userid, "%d", (int)gid) < 0)
++ goto cleanup;
+ if (virAsprintf(&processid, "%llu",
+ (unsigned long long)pid) < 0)
+ goto cleanup;
+@@ -710,11 +716,21 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
+ VIR_IDENTITY_ATTR_UNIX_USER_NAME,
+ username) < 0)
+ goto error;
++ if (userid &&
++ virIdentitySetAttr(ret,
++ VIR_IDENTITY_ATTR_UNIX_USER_ID,
++ userid) < 0)
++ goto error;
+ if (groupname &&
+ virIdentitySetAttr(ret,
+ VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
+ groupname) < 0)
+ goto error;
++ if (groupid &&
++ virIdentitySetAttr(ret,
++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID,
++ groupid) < 0)
++ goto error;
+ if (processid &&
+ virIdentitySetAttr(ret,
+ VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
+@@ -745,7 +761,9 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
+
+ cleanup:
+ VIR_FREE(username);
++ VIR_FREE(userid);
+ VIR_FREE(groupname);
++ VIR_FREE(groupid);
+ VIR_FREE(processid);
+ VIR_FREE(processtime);
+ VIR_FREE(seccontext);
+diff --git a/src/util/viridentity.c b/src/util/viridentity.c
+index 781f660..03c375b 100644
+--- a/src/util/viridentity.c
++++ b/src/util/viridentity.c
+@@ -133,7 +133,9 @@ int virIdentitySetCurrent(virIdentityPtr ident)
+ virIdentityPtr virIdentityGetSystem(void)
+ {
+ char *username = NULL;
++ char *userid = NULL;
+ char *groupname = NULL;
++ char *groupid = NULL;
+ char *seccontext = NULL;
+ virIdentityPtr ret = NULL;
+ #if WITH_SELINUX
+@@ -147,8 +149,13 @@ virIdentityPtr virIdentityGetSystem(void)
+
+ if (!(username = virGetUserName(getuid())))
+ goto cleanup;
++ if (virAsprintf(&userid, "%d", (int)getuid()) < 0)
++ goto cleanup;
++
+ if (!(groupname = virGetGroupName(getgid())))
+ goto cleanup;
++ if (virAsprintf(&groupid, "%d", (int)getgid()) < 0)
++ goto cleanup;
+
+ #if WITH_SELINUX
+ if (getcon(&con) < 0) {
+@@ -166,16 +173,22 @@ virIdentityPtr virIdentityGetSystem(void)
+ if (!(ret = virIdentityNew()))
+ goto cleanup;
+
+- if (username &&
+- virIdentitySetAttr(ret,
++ if (virIdentitySetAttr(ret,
+ VIR_IDENTITY_ATTR_UNIX_USER_NAME,
+ username) < 0)
+ goto error;
+- if (groupname &&
+- virIdentitySetAttr(ret,
++ if (virIdentitySetAttr(ret,
++ VIR_IDENTITY_ATTR_UNIX_USER_ID,
++ userid) < 0)
++ goto error;
++ if (virIdentitySetAttr(ret,
+ VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
+ groupname) < 0)
+ goto error;
++ if (virIdentitySetAttr(ret,
++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID,
++ groupid) < 0)
++ goto error;
+ if (seccontext &&
+ virIdentitySetAttr(ret,
+ VIR_IDENTITY_ATTR_SELINUX_CONTEXT,
+@@ -188,7 +201,9 @@ virIdentityPtr virIdentityGetSystem(void)
+
+ cleanup:
+ VIR_FREE(username);
++ VIR_FREE(userid);
+ VIR_FREE(groupname);
++ VIR_FREE(groupid);
+ VIR_FREE(seccontext);
+ VIR_FREE(processid);
+ return ret;
+diff --git a/src/util/viridentity.h b/src/util/viridentity.h
+index 4bae8d6..a240c2d 100644
+--- a/src/util/viridentity.h
++++ b/src/util/viridentity.h
+@@ -29,7 +29,9 @@ typedef virIdentity *virIdentityPtr;
+
+ typedef enum {
+ VIR_IDENTITY_ATTR_UNIX_USER_NAME,
++ VIR_IDENTITY_ATTR_UNIX_USER_ID,
+ VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID,
+ VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
+ VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME,
+ VIR_IDENTITY_ATTR_SASL_USER_NAME,
+--
+1.8.3.2
+
--- /dev/null
+From d86f8ca314a4209b19d2ea425c2447b006afc84e Mon Sep 17 00:00:00 2001
+Message-Id: <d86f8ca314a4209b19d2ea425c2447b006afc84e.1378475168.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 4 Sep 2013 12:46:10 +0200
+Subject: [PATCH] Always specify qcow2 compat level on qemu-img command line
+
+qemu-img is going to switch the default for QCOW2
+to QCOW2v3 (compat=1.1) [1]
+
+Extend the probing for qemu-img command line options to check
+if -o compat is supported. If the volume definition specifies
+the qcow2 format but no compat level and -o compat is supported,
+specify -o compat=0.10 to create a QCOW2v2 image.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=997977
+(cherry picked from commit bab2eda6ada1bf832decdc64cc5062e54eb105df)
+---
+ src/storage/storage_backend.c | 47 +++++++++++++++++++---
+ tests/storagevolxml2argvdata/qcow2-compat.argv | 3 ++
+ .../qcow2-from-logical-compat.argv | 3 ++
+ .../qcow2-nobacking-convert-prealloc-compat.argv | 3 ++
+ .../qcow2-nobacking-prealloc-compat.argv | 3 ++
+ tests/storagevolxml2argvtest.c | 26 ++++++++++++
+ 6 files changed, 79 insertions(+), 6 deletions(-)
+ create mode 100644 tests/storagevolxml2argvdata/qcow2-compat.argv
+ create mode 100644 tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
+ create mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv
+ create mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv
+
+diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
+index 8d5880e..4ebe11b 100644
+--- a/src/storage/storage_backend.c
++++ b/src/storage/storage_backend.c
+@@ -581,8 +581,34 @@ enum {
+ QEMU_IMG_BACKING_FORMAT_NONE = 0,
+ QEMU_IMG_BACKING_FORMAT_FLAG,
+ QEMU_IMG_BACKING_FORMAT_OPTIONS,
++ QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT,
+ };
+
++static bool
++virStorageBackendQemuImgSupportsCompat(const char *qemuimg)
++{
++ bool ret = false;
++ char *output;
++ virCommandPtr cmd = NULL;
++
++ cmd = virCommandNewArgList(qemuimg, "create", "-o", "?", "-f", "qcow2",
++ "/dev/null", NULL);
++
++ virCommandAddEnvString(cmd, "LC_ALL=C");
++ virCommandSetOutputBuffer(cmd, &output);
++
++ if (virCommandRun(cmd, NULL) < 0)
++ goto cleanup;
++
++ if (strstr(output, "\ncompat "))
++ ret = true;
++
++cleanup:
++ virCommandFree(cmd);
++ VIR_FREE(output);
++ return ret;
++}
++
+ static int
+ virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
+ {
+@@ -612,12 +638,16 @@ virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
+ goto cleanup;
+ }
+ if (((tmp = strstr(start, "-F fmt")) && tmp < end) ||
+- ((tmp = strstr(start, "-F backing_fmt")) && tmp < end))
++ ((tmp = strstr(start, "-F backing_fmt")) && tmp < end)) {
+ ret = QEMU_IMG_BACKING_FORMAT_FLAG;
+- else if ((tmp = strstr(start, "[-o options]")) && tmp < end)
+- ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
+- else
++ } else if ((tmp = strstr(start, "[-o options]")) && tmp < end) {
++ if (virStorageBackendQemuImgSupportsCompat(qemuimg))
++ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT;
++ else
++ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
++ } else {
+ ret = QEMU_IMG_BACKING_FORMAT_NONE;
++ }
+
+ cleanup:
+ virCommandFree(cmd);
+@@ -705,6 +735,7 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn,
+ const char *backingType = NULL;
+ const char *inputPath = NULL;
+ const char *inputType = NULL;
++ const char *compat = vol->target.compat;
+ char *opts = NULL;
+ bool convert = false;
+ bool backing = false;
+@@ -854,12 +885,16 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn,
+ if (backing)
+ virCommandAddArgList(cmd, "-b", vol->backingStore.path, NULL);
+
+- if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS) {
++ if (imgformat >= QEMU_IMG_BACKING_FORMAT_OPTIONS) {
++ if (vol->target.format == VIR_STORAGE_FILE_QCOW2 && !compat &&
++ imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT)
++ compat = "0.10";
++
+ if (virStorageBackendCreateQemuImgOpts(&opts,
+ backing ? backingType : NULL,
+ do_encryption, preallocate,
+ vol->target.format,
+- vol->target.compat,
++ compat,
+ vol->target.features) < 0) {
+ virCommandFree(cmd);
+ return NULL;
+diff --git a/tests/storagevolxml2argvdata/qcow2-compat.argv b/tests/storagevolxml2argvdata/qcow2-compat.argv
+new file mode 100644
+index 0000000..37ad2c0
+--- /dev/null
++++ b/tests/storagevolxml2argvdata/qcow2-compat.argv
+@@ -0,0 +1,3 @@
++qemu-img create -f qcow2 -b /dev/null \
++-o backing_fmt=raw,encryption=on,compat=0.10 \
++/var/lib/libvirt/images/OtherDemo.img 5242880K
+diff --git a/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv b/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
+new file mode 100644
+index 0000000..5f365b1
+--- /dev/null
++++ b/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv
+@@ -0,0 +1,3 @@
++qemu-img convert -f raw -O qcow2 \
++-o encryption=on,compat=0.10 \
++/dev/HostVG/Swap /var/lib/libvirt/images/OtherDemo.img
+diff --git a/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv
+new file mode 100644
+index 0000000..3d93ec8
+--- /dev/null
++++ b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv
+@@ -0,0 +1,3 @@
++qemu-img convert -f raw -O qcow2 \
++-o encryption=on,preallocation=metadata,compat=0.10 \
++/var/lib/libvirt/images/sparse.img /var/lib/libvirt/images/OtherDemo.img
+diff --git a/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv b/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv
+new file mode 100644
+index 0000000..903c94e
+--- /dev/null
++++ b/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv
+@@ -0,0 +1,3 @@
++qemu-img create -f qcow2 \
++-o encryption=on,preallocation=metadata,compat=0.10 \
++/var/lib/libvirt/images/OtherDemo.img 5242880K
+diff --git a/tests/storagevolxml2argvtest.c b/tests/storagevolxml2argvtest.c
+index b1cf09f..cafcaad 100644
+--- a/tests/storagevolxml2argvtest.c
++++ b/tests/storagevolxml2argvtest.c
+@@ -195,6 +195,7 @@ enum {
+ FMT_NONE = 0,
+ FMT_FLAG,
+ FMT_OPTIONS,
++ FMT_COMPAT,
+ };
+
+
+@@ -271,6 +272,31 @@ mymain(void)
+ "pool-dir", "vol-qcow2-nobacking",
+ "logical-from-qcow2", 0, FMT_OPTIONS);
+
++ DO_TEST("pool-dir", "vol-qcow2",
++ NULL, NULL,
++ "qcow2-compat", 0, FMT_COMPAT);
++ DO_TEST("pool-dir", "vol-qcow2-nobacking",
++ NULL, NULL,
++ "qcow2-nobacking-prealloc-compat", flags, FMT_COMPAT);
++ DO_TEST("pool-dir", "vol-qcow2-nobacking",
++ "pool-dir", "vol-file",
++ "qcow2-nobacking-convert-prealloc-compat", flags, FMT_COMPAT);
++ DO_TEST("pool-dir", "vol-qcow2-lazy",
++ NULL, NULL,
++ "qcow2-lazy", 0, FMT_COMPAT);
++ DO_TEST("pool-dir", "vol-qcow2-1.1",
++ NULL, NULL,
++ "qcow2-1.1", 0, FMT_COMPAT);
++ DO_TEST_FAIL("pool-dir", "vol-qcow2-0.10-lazy",
++ NULL, NULL,
++ "qcow2-0.10-lazy", 0, FMT_COMPAT);
++ DO_TEST("pool-dir", "vol-qcow2-nobacking",
++ "pool-logical", "vol-logical",
++ "qcow2-from-logical-compat", 0, FMT_COMPAT);
++ DO_TEST("pool-logical", "vol-logical",
++ "pool-dir", "vol-qcow2-nobacking",
++ "logical-from-qcow2", 0, FMT_COMPAT);
++
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From df25234304fb6ec02e20df31956946df53a3d941 Mon Sep 17 00:00:00 2001
+Message-Id: <df25234304fb6ec02e20df31956946df53a3d941.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 2 Aug 2013 12:15:57 +0100
+Subject: [PATCH] Avoid crash if NULL is passed for filename/funcname in
+ logging
+
+https://bugzilla.redhat.com/show_bug.cgi?id=991348
+
+The journald code would crash if a NULL was passed for the
+filename / funcname in the logging code. This shouldn't
+happen in general, but it is better to be safe, since there
+have been bugs triggering this.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit b4ca2999020ab4adf7a73ccbff1de2b40a097874)
+---
+ src/util/virlog.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/virlog.c b/src/util/virlog.c
+index d1fb0b3..047a131 100644
+--- a/src/util/virlog.c
++++ b/src/util/virlog.c
+@@ -1181,9 +1181,11 @@ virLogOutputToJournald(virLogSource source,
+ journalAddInt(&state, "PRIORITY", priority);
+ journalAddString(&state, "LIBVIRT_SOURCE",
+ virLogSourceTypeToString(source));
+- journalAddString(&state, "CODE_FILE", filename);
++ if (filename)
++ journalAddString(&state, "CODE_FILE", filename);
+ journalAddInt(&state, "CODE_LINE", linenr);
+- journalAddString(&state, "CODE_FUNC", funcname);
++ if (funcname)
++ journalAddString(&state, "CODE_FUNC", funcname);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sun_family = AF_UNIX;
+--
+1.8.3.2
+
--- /dev/null
+From d6fe3f01e405113c9ff5ada2d75e62530608d353 Mon Sep 17 00:00:00 2001
+Message-Id: <d6fe3f01e405113c9ff5ada2d75e62530608d353.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 17:17:29 +0100
+Subject: [PATCH] Avoid deleting NULL veth device name
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+If veth device allocation has a fatal error, the veths
+array may contain NULL device names. Avoid calling the
+virNetDevVethDelete function on such names.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 8766e9b5a56109155b5c952af91d384d7e0555ec)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_process.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index bc9bdfb..47e6dd7 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -1280,7 +1280,7 @@ cleanup:
+ rc = -1;
+ }
+ for (i = 0; i < nveths; i++) {
+- if (rc != 0)
++ if (rc != 0 && veths[i])
+ ignore_value(virNetDevVethDelete(veths[i]));
+ VIR_FREE(veths[i]);
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 1f5e6cb8df70b658f48d5b562b5b483778dd911e Mon Sep 17 00:00:00 2001
+Message-Id: <1f5e6cb8df70b658f48d5b562b5b483778dd911e.1377873637.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:46 +0100
+Subject: [PATCH] Avoid re-generating certs every time
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+Currently every test case in the TLS test suite generates the
+certs fresh. This is a waste of time, since its parameters
+don't change across test cases. Create certs once in main
+method.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 90811c5987870f348ebc545b5a6d127cc2076723)
+---
+ tests/virnettlscontexttest.c | 670 +++++++++++++++++++++++--------------------
+ tests/virnettlshelpers.c | 9 +-
+ tests/virnettlshelpers.h | 4 +-
+ tests/virnettlssessiontest.c | 152 +++++-----
+ 4 files changed, 445 insertions(+), 390 deletions(-)
+
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 0a0d31a..4211a74 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -62,10 +62,6 @@ static int testTLSContextInit(const void *opaque)
+ virNetTLSContextPtr ctxt = NULL;
+ int ret = -1;
+
+- testTLSGenerateCert(&data->careq);
+- data->certreq.cacrt = data->careq.crt;
+- testTLSGenerateCert(&data->certreq);
+-
+ if (data->isServer) {
+ ctxt = virNetTLSContextNewServer(data->careq.filename,
+ NULL,
+@@ -103,8 +99,6 @@ static int testTLSContextInit(const void *opaque)
+
+ cleanup:
+ virObjectUnref(ctxt);
+- testTLSDiscardCert(&data->careq);
+- testTLSDiscardCert(&data->certreq);
+ return ret;
+ }
+
+@@ -124,38 +118,54 @@ mymain(void)
+ data.careq = _caReq; \
+ data.certreq = _certReq; \
+ data.expectFail = _expectFail; \
+- if (virtTestRun("TLS Context", 1, testTLSContextInit, &data) < 0) \
++ if (virtTestRun("TLS Context " #_caReq " + " #_certReq, 1, \
++ testTLSContextInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
++# define TLS_CERT_REQ(varname, cavarname, \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
++ static struct testTLSCertReq varname = { \
++ NULL, #varname ".pem", \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \
++ }; \
++ testTLSGenerateCert(&varname, cavarname.crt)
++
++# define TLS_ROOT_REQ(varname, \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
++ static struct testTLSCertReq varname = { \
++ NULL, #varname ".pem", \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \
++ }; \
++ testTLSGenerateCert(&varname, NULL)
++
++
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+- static struct testTLSCertReq cacertreq = {
+- NULL, NULL, "cacert.pem", "UK",
+- "libvirt CA", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
+- static struct testTLSCertReq servercertreq = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
+- static struct testTLSCertReq clientcertreq = {
+- NULL, NULL, "clientcert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, 0,
+- };
+-
++ TLS_ROOT_REQ(cacertreq,
++ "UK", "libvirt CA", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++
++ TLS_CERT_REQ(servercertreq, cacertreq,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(clientcertreq, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
+
+ DO_CTX_TEST(true, cacertreq, servercertreq, false);
+ DO_CTX_TEST(false, cacertreq, clientcertreq, false);
+@@ -164,249 +174,241 @@ mymain(void)
+ /* Some other CAs which are good */
+
+ /* Basic:CA:critical */
+- static struct testTLSCertReq cacert1req = {
+- NULL, NULL, "cacert1.pem", "UK",
+- "libvirt CA 1", NULL, NULL, NULL, NULL,
+- true, true, true,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacert1req,
++ "UK", "libvirt CA 1", NULL, NULL, NULL, NULL,
++ true, true, true,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert1req, cacert1req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++
+ /* Basic:CA:not-critical */
+- static struct testTLSCertReq cacert2req = {
+- NULL, NULL, "cacert2.pem", "UK",
+- "libvirt CA 2", NULL, NULL, NULL, NULL,
+- true, false, true,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacert2req,
++ "UK", "libvirt CA 2", NULL, NULL, NULL, NULL,
++ true, false, true,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert2req, cacert2req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++
+ /* Key usage:cert-sign:critical */
+- static struct testTLSCertReq cacert3req = {
+- NULL, NULL, "cacert3.pem", "UK",
+- "libvirt CA 3", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
+-
+- DO_CTX_TEST(true, cacert1req, servercertreq, false);
+- DO_CTX_TEST(true, cacert2req, servercertreq, false);
+- DO_CTX_TEST(true, cacert3req, servercertreq, false);
++ TLS_ROOT_REQ(cacert3req,
++ "UK", "libvirt CA 3", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert3req, cacert3req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++
++ DO_CTX_TEST(true, cacert1req, servercert1req, false);
++ DO_CTX_TEST(true, cacert2req, servercert2req, false);
++ DO_CTX_TEST(true, cacert3req, servercert3req, false);
+
+ /* Now some bad certs */
+
+ /* Key usage:dig-sig:not-critical */
+- static struct testTLSCertReq cacert4req = {
+- NULL, NULL, "cacert4.pem", "UK",
+- "libvirt CA 4", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, false, GNUTLS_KEY_DIGITAL_SIGNATURE,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacert4req,
++ "UK", "libvirt CA 4", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, false, GNUTLS_KEY_DIGITAL_SIGNATURE,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert4req, cacert4req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* no-basic */
+- static struct testTLSCertReq cacert5req = {
+- NULL, NULL, "cacert5.pem", "UK",
+- "libvirt CA 5", NULL, NULL, NULL, NULL,
+- false, false, false,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacert5req,
++ "UK", "libvirt CA 5", NULL, NULL, NULL, NULL,
++ false, false, false,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert5req, cacert5req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* Key usage:dig-sig:critical */
+- static struct testTLSCertReq cacert6req = {
+- NULL, NULL, "cacert6.pem", "UK",
+- "libvirt CA 6", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacert6req,
++ "UK", "libvirt CA 6", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercert6req, cacert6req,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+
+ /* Technically a CA cert with basic constraints
+ * key purpose == key signing + non-critical should
+ * be rejected. GNUTLS < 3 does not reject it and
+ * we don't anticipate them changing this behaviour
+ */
+- DO_CTX_TEST(true, cacert4req, servercertreq, GNUTLS_VERSION_MAJOR >= 3);
+- DO_CTX_TEST(true, cacert5req, servercertreq, true);
+- DO_CTX_TEST(true, cacert6req, servercertreq, true);
++ DO_CTX_TEST(true, cacert4req, servercert4req, GNUTLS_VERSION_MAJOR >= 3);
++ DO_CTX_TEST(true, cacert5req, servercert5req, true);
++ DO_CTX_TEST(true, cacert6req, servercert6req, true);
+
+
+ /* Various good servers */
+ /* no usage or purpose */
+- static struct testTLSCertReq servercert1req = {
+- NULL, NULL, "servercert1.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert7req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* usage:cert-sign+dig-sig+encipher:critical */
+- static struct testTLSCertReq servercert2req = {
+- NULL, NULL, "servercert2.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert8req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* usage:cert-sign:not-critical */
+- static struct testTLSCertReq servercert3req = {
+- NULL, NULL, "servercert3.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, false, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert9req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, false, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* purpose:server:critical */
+- static struct testTLSCertReq servercert4req = {
+- NULL, NULL, "servercert4.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert10req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* purpose:server:not-critical */
+- static struct testTLSCertReq servercert5req = {
+- NULL, NULL, "servercert5.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert11req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* purpose:client+server:critical */
+- static struct testTLSCertReq servercert6req = {
+- NULL, NULL, "servercert6.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert12req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
++ 0, 0);
+ /* purpose:client+server:not-critical */
+- static struct testTLSCertReq servercert7req = {
+- NULL, NULL, "servercert7.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+- 0, 0,
+- };
+-
+- DO_CTX_TEST(true, cacertreq, servercert1req, false);
+- DO_CTX_TEST(true, cacertreq, servercert2req, false);
+- DO_CTX_TEST(true, cacertreq, servercert3req, false);
+- DO_CTX_TEST(true, cacertreq, servercert4req, false);
+- DO_CTX_TEST(true, cacertreq, servercert5req, false);
+- DO_CTX_TEST(true, cacertreq, servercert6req, false);
++ TLS_CERT_REQ(servercert13req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
++ 0, 0);
++
+ DO_CTX_TEST(true, cacertreq, servercert7req, false);
++ DO_CTX_TEST(true, cacertreq, servercert8req, false);
++ DO_CTX_TEST(true, cacertreq, servercert9req, false);
++ DO_CTX_TEST(true, cacertreq, servercert10req, false);
++ DO_CTX_TEST(true, cacertreq, servercert11req, false);
++ DO_CTX_TEST(true, cacertreq, servercert12req, false);
++ DO_CTX_TEST(true, cacertreq, servercert13req, false);
+ /* Bad servers */
+
+ /* usage:cert-sign:critical */
+- static struct testTLSCertReq servercert8req = {
+- NULL, NULL, "servercert8.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert14req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* purpose:client:critical */
+- static struct testTLSCertReq servercert9req = {
+- NULL, NULL, "servercert9.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert15req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
+ /* usage: none:critical */
+- static struct testTLSCertReq servercert10req = {
+- NULL, NULL, "servercert10.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercert16req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, 0,
++ false, false, NULL, NULL,
++ 0, 0);
+
+- DO_CTX_TEST(true, cacertreq, servercert8req, true);
+- DO_CTX_TEST(true, cacertreq, servercert9req, true);
+- DO_CTX_TEST(true, cacertreq, servercert10req, true);
++ DO_CTX_TEST(true, cacertreq, servercert14req, true);
++ DO_CTX_TEST(true, cacertreq, servercert15req, true);
++ DO_CTX_TEST(true, cacertreq, servercert16req, true);
+
+
+
+ /* Various good clients */
+ /* no usage or purpose */
+- static struct testTLSCertReq clientcert1req = {
+- NULL, NULL, "clientcert1.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert1req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* usage:cert-sign+dig-sig+encipher:critical */
+- static struct testTLSCertReq clientcert2req = {
+- NULL, NULL, "clientcert2.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert2req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* usage:cert-sign:not-critical */
+- static struct testTLSCertReq clientcert3req = {
+- NULL, NULL, "clientcert3.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, false, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert3req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, false, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* purpose:client:critical */
+- static struct testTLSCertReq clientcert4req = {
+- NULL, NULL, "clientcert4.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert4req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
+ /* purpose:client:not-critical */
+- static struct testTLSCertReq clientcert5req = {
+- NULL, NULL, "clientcert5.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert5req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
+ /* purpose:client+client:critical */
+- static struct testTLSCertReq clientcert6req = {
+- NULL, NULL, "clientcert6.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert6req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
++ 0, 0);
+ /* purpose:client+client:not-critical */
+- static struct testTLSCertReq clientcert7req = {
+- NULL, NULL, "clientcert7.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert7req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
++ 0, 0);
+
+ DO_CTX_TEST(false, cacertreq, clientcert1req, false);
+ DO_CTX_TEST(false, cacertreq, clientcert2req, false);
+@@ -418,32 +420,26 @@ mymain(void)
+ /* Bad clients */
+
+ /* usage:cert-sign:critical */
+- static struct testTLSCertReq clientcert8req = {
+- NULL, NULL, "clientcert8.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert8req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
+ /* purpose:client:critical */
+- static struct testTLSCertReq clientcert9req = {
+- NULL, NULL, "clientcert9.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- false, false, 0,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert9req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ false, false, 0,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* usage: none:critical */
+- static struct testTLSCertReq clientcert10req = {
+- NULL, NULL, "clientcert10.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(clientcert10req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, 0,
++ false, false, NULL, NULL,
++ 0, 0);
+
+ DO_CTX_TEST(false, cacertreq, clientcert8req, true);
+ DO_CTX_TEST(false, cacertreq, clientcert9req, true);
+@@ -453,66 +449,114 @@ mymain(void)
+
+ /* Expired stuff */
+
+- static struct testTLSCertReq cacertexpreq = {
+- NULL, NULL, "cacert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, -1,
+- };
+- static struct testTLSCertReq servercertexpreq = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, -1,
+- };
+- static struct testTLSCertReq clientcertexpreq = {
+- NULL, NULL, "clientcert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, -1,
+- };
+-
+- DO_CTX_TEST(true, cacertexpreq, servercertreq, true);
+- DO_CTX_TEST(true, cacertreq, servercertexpreq, true);
+- DO_CTX_TEST(false, cacertreq, clientcertexpreq, true);
++ TLS_ROOT_REQ(cacertexpreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, -1);
++ TLS_CERT_REQ(servercertexpreq, cacertexpreq,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercertexp1req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, -1);
++ TLS_CERT_REQ(clientcertexp1req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, -1);
++
++ DO_CTX_TEST(true, cacertexpreq, servercertexpreq, true);
++ DO_CTX_TEST(true, cacertreq, servercertexp1req, true);
++ DO_CTX_TEST(false, cacertreq, clientcertexp1req, true);
+
+
+ /* Not activated stuff */
+
+- static struct testTLSCertReq cacertnewreq = {
+- NULL, NULL, "cacert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 1, 2,
+- };
+- static struct testTLSCertReq servercertnewreq = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 1, 2,
+- };
+- static struct testTLSCertReq clientcertnewreq = {
+- NULL, NULL, "clientcert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 1, 2,
+- };
+-
+- DO_CTX_TEST(true, cacertnewreq, servercertreq, true);
+- DO_CTX_TEST(true, cacertreq, servercertnewreq, true);
+- DO_CTX_TEST(false, cacertreq, clientcertnewreq, true);
++ TLS_ROOT_REQ(cacertnewreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 1, 2);
++ TLS_CERT_REQ(servercertnewreq, cacertnewreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercertnew1req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 1, 2);
++ TLS_CERT_REQ(clientcertnew1req, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 1, 2);
++
++ DO_CTX_TEST(true, cacertnewreq, servercertnewreq, true);
++ DO_CTX_TEST(true, cacertreq, servercertnew1req, true);
++ DO_CTX_TEST(false, cacertreq, clientcertnew1req, true);
++
++ testTLSDiscardCert(&cacertreq);
++ testTLSDiscardCert(&cacert1req);
++ testTLSDiscardCert(&cacert2req);
++ testTLSDiscardCert(&cacert3req);
++ testTLSDiscardCert(&cacert4req);
++ testTLSDiscardCert(&cacert5req);
++ testTLSDiscardCert(&cacert6req);
++
++ testTLSDiscardCert(&servercertreq);
++ testTLSDiscardCert(&servercert1req);
++ testTLSDiscardCert(&servercert2req);
++ testTLSDiscardCert(&servercert3req);
++ testTLSDiscardCert(&servercert4req);
++ testTLSDiscardCert(&servercert5req);
++ testTLSDiscardCert(&servercert6req);
++ testTLSDiscardCert(&servercert7req);
++ testTLSDiscardCert(&servercert8req);
++ testTLSDiscardCert(&servercert9req);
++ testTLSDiscardCert(&servercert10req);
++ testTLSDiscardCert(&servercert11req);
++ testTLSDiscardCert(&servercert12req);
++ testTLSDiscardCert(&servercert13req);
++ testTLSDiscardCert(&servercert14req);
++ testTLSDiscardCert(&servercert15req);
++ testTLSDiscardCert(&servercert16req);
++
++ testTLSDiscardCert(&clientcertreq);
++ testTLSDiscardCert(&clientcert1req);
++ testTLSDiscardCert(&clientcert2req);
++ testTLSDiscardCert(&clientcert3req);
++ testTLSDiscardCert(&clientcert4req);
++ testTLSDiscardCert(&clientcert5req);
++ testTLSDiscardCert(&clientcert6req);
++ testTLSDiscardCert(&clientcert7req);
++ testTLSDiscardCert(&clientcert8req);
++ testTLSDiscardCert(&clientcert9req);
++ testTLSDiscardCert(&clientcert10req);
++
++ testTLSDiscardCert(&cacertexpreq);
++ testTLSDiscardCert(&servercertexpreq);
++ testTLSDiscardCert(&servercertexp1req);
++ testTLSDiscardCert(&clientcertexp1req);
++
++ testTLSDiscardCert(&cacertnewreq);
++ testTLSDiscardCert(&servercertnewreq);
++ testTLSDiscardCert(&servercertnew1req);
++ testTLSDiscardCert(&clientcertnew1req);
+
+ testTLSCleanup();
+
+diff --git a/tests/virnettlshelpers.c b/tests/virnettlshelpers.c
+index 96b2f6e..8236e82 100644
+--- a/tests/virnettlshelpers.c
++++ b/tests/virnettlshelpers.c
+@@ -152,7 +152,8 @@ static void testTLSDerEncode(ASN1_TYPE src,
+ * TLS certificate code
+ */
+ void
+-testTLSGenerateCert(struct testTLSCertReq *req)
++testTLSGenerateCert(struct testTLSCertReq *req,
++ gnutls_x509_crt_t ca)
+ {
+ gnutls_x509_crt_t crt;
+ int err;
+@@ -379,10 +380,10 @@ testTLSGenerateCert(struct testTLSCertReq *req)
+
+
+ /*
+- * If no 'cart' is set then we are self signing
+- * the cert. This is done for CA certs
++ * If no 'ca' is set then we are self signing
++ * the cert. This is done for the root CA certs
+ */
+- if ((err = gnutls_x509_crt_sign(crt, req->cacrt ? req->cacrt : crt, privkey) < 0)) {
++ if ((err = gnutls_x509_crt_sign(crt, ca ? ca : crt, privkey) < 0)) {
+ VIR_WARN("Failed to sign certificate %s", gnutls_strerror(err));
+ abort();
+ }
+diff --git a/tests/virnettlshelpers.h b/tests/virnettlshelpers.h
+index 3ea9978..50a4ba1 100644
+--- a/tests/virnettlshelpers.h
++++ b/tests/virnettlshelpers.h
+@@ -36,7 +36,6 @@ extern const char *keyfile;
+ */
+ struct testTLSCertReq {
+ gnutls_x509_crt_t crt;
+- gnutls_x509_crt_t cacrt; /* If not set, then the cert will be self-signed */
+
+ const char *filename;
+
+@@ -70,7 +69,8 @@ struct testTLSCertReq {
+ int expire_offset;
+ };
+
+-void testTLSGenerateCert(struct testTLSCertReq *req);
++void testTLSGenerateCert(struct testTLSCertReq *req,
++ gnutls_x509_crt_t ca);
+ void testTLSDiscardCert(struct testTLSCertReq *req);
+
+ void testTLSInit(void);
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+index 9c5b3ca..370ba52 100644
+--- a/tests/virnettlssessiontest.c
++++ b/tests/virnettlssessiontest.c
+@@ -100,20 +100,6 @@ static int testTLSSessionInit(const void *opaque)
+ ignore_value(virSetNonBlock(channel[1]));
+
+
+- /* Generate all the certs we need for this test */
+- testTLSGenerateCert(&data->careq);
+- data->serverreq.cacrt = data->careq.crt;
+- testTLSGenerateCert(&data->serverreq);
+-
+- if (data->othercareq.filename) {
+- testTLSGenerateCert(&data->othercareq);
+- data->clientreq.cacrt = data->othercareq.crt;
+- } else {
+- data->clientreq.cacrt = data->careq.crt;
+- }
+- testTLSGenerateCert(&data->clientreq);
+-
+-
+ /* We skip initial sanity checks here because we
+ * want to make sure that problems are being
+ * detected at the TLS session validation stage
+@@ -243,12 +229,6 @@ cleanup:
+ virObjectUnref(serverSess);
+ virObjectUnref(clientSess);
+
+- testTLSDiscardCert(&data->careq);
+- if (data->othercareq.filename)
+- testTLSDiscardCert(&data->othercareq);
+- testTLSDiscardCert(&data->clientreq);
+- testTLSDiscardCert(&data->serverreq);
+-
+ VIR_FORCE_CLOSE(channel[0]);
+ VIR_FORCE_CLOSE(channel[1]);
+ return ret;
+@@ -275,7 +255,8 @@ mymain(void)
+ data.expectClientFail = _expectClientFail; \
+ data.hostname = _hostname; \
+ data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
++ if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \
++ 1, testTLSSessionInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
+@@ -292,68 +273,87 @@ mymain(void)
+ data.expectClientFail = _expectClientFail; \
+ data.hostname = _hostname; \
+ data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
++ if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \
++ 1, testTLSSessionInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
++# define TLS_CERT_REQ(varname, cavarname, \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
++ static struct testTLSCertReq varname = { \
++ NULL, #varname ".pem", \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \
++ }; \
++ testTLSGenerateCert(&varname, cavarname.crt)
++
++# define TLS_ROOT_REQ(varname, \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
++ static struct testTLSCertReq varname = { \
++ NULL, #varname ".pem", \
++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \
++ }; \
++ testTLSGenerateCert(&varname, NULL)
++
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+- static struct testTLSCertReq cacertreq = {
+- NULL, NULL, "cacert.pem", "UK",
+- "libvirt CA", NULL, NULL, NULL, NULL,
+- true, true, true,
+- true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
+- static struct testTLSCertReq cacert1req = {
+- NULL, NULL, "cacert1.pem", "UK",
+- "libvirt CA 1", NULL, NULL, NULL, NULL,
+- true, true, true,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
+- static struct testTLSCertReq servercertreq = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
+- static struct testTLSCertReq clientcertreq = {
+- NULL, NULL, "clientcert.pem", "UK",
+- "libvirt", NULL, NULL, NULL, NULL,
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+- 0, 0,
+- };
++ TLS_ROOT_REQ(cacertreq,
++ "UK", "libvirt CA", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++
++ TLS_ROOT_REQ(altcacertreq,
++ "UK", "libvirt CA 1", NULL, NULL, NULL, NULL,
++ true, true, true,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0);
++
++ TLS_CERT_REQ(servercertreq, cacertreq,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(clientcertreq, cacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
++
++ TLS_CERT_REQ(clientcertaltreq, altcacertreq,
++ "UK", "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
+
+ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL);
+- DO_SESS_TEST_EXT(cacertreq, cacert1req, servercertreq, clientcertreq, true, true, "libvirt.org", NULL);
++ DO_SESS_TEST_EXT(cacertreq, altcacertreq, servercertreq, clientcertaltreq, true, true, "libvirt.org", NULL);
++
+
+ /* When an altname is set, the CN is ignored, so it must be duplicated
+ * as an altname for it to match */
+- static struct testTLSCertReq servercertalt1req = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf",
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercertalt1req, cacertreq,
++ "UK", "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf",
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+ /* This intentionally doesn't replicate */
+- static struct testTLSCertReq servercertalt2req = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf",
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
++ TLS_CERT_REQ(servercertalt2req, cacertreq,
++ "UK", "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf",
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
+
+ DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL);
+ DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL);
+@@ -396,6 +396,16 @@ mymain(void)
+ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5);
+ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6);
+
++ testTLSDiscardCert(&clientcertreq);
++ testTLSDiscardCert(&clientcertaltreq);
++
++ testTLSDiscardCert(&servercertreq);
++ testTLSDiscardCert(&servercertalt1req);
++ testTLSDiscardCert(&servercertalt2req);
++
++ testTLSDiscardCert(&cacertreq);
++ testTLSDiscardCert(&altcacertreq);
++
+ testTLSCleanup();
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+--
+1.8.3.2
+
--- /dev/null
+From 97edaf4f3dc5af717f88e41577a1cda77982f4c1 Mon Sep 17 00:00:00 2001
+Message-Id: <97edaf4f3dc5af717f88e41577a1cda77982f4c1.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 17:17:28 +0100
+Subject: [PATCH] Avoid reporting an error if veth device is already deleted
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+The kernel automatically destroys veth devices when cleaning
+up the container network namespace. During normal shutdown, it
+is thus likely that the attempt to run 'ip link del vethN'
+will fail. If it fails, check if the device exists, and avoid
+reporting an error if it has gone. This switches to use the
+virCommand APIs instead of virRun too.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 10caf94ddc568d36561d89ca28fe0c58154a50f9)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ po/POTFILES.in | 1 +
+ src/util/virnetdevveth.c | 17 ++++++++++++++---
+ 2 files changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 884b70a..8afd015 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -168,6 +168,7 @@ src/util/virnetdevbridge.c
+ src/util/virnetdevmacvlan.c
+ src/util/virnetdevopenvswitch.c
+ src/util/virnetdevtap.c
++src/util/virnetdevveth.c
+ src/util/virnetdevvportprofile.c
+ src/util/virnetlink.c
+ src/util/virnodesuspend.c
+diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
+index 039767f..c0d32c4 100644
+--- a/src/util/virnetdevveth.c
++++ b/src/util/virnetdevveth.c
+@@ -161,9 +161,20 @@ cleanup:
+ */
+ int virNetDevVethDelete(const char *veth)
+ {
+- const char *argv[] = {"ip", "link", "del", veth, NULL};
++ virCommandPtr cmd = virCommandNewArgList("ip", "link", "del", veth, NULL);
++ int status;
+
+- VIR_DEBUG("veth: %s", veth);
++ if (virCommandRun(cmd, &status) < 0)
++ return -1;
+
+- return virRun(argv, NULL);
++ if (status != 0) {
++ if (!virNetDevExists(veth)) {
++ VIR_DEBUG("Device %s already deleted (by kernel namespace cleanup)", veth);
++ return 0;
++ }
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Failed to delete veth device %s"), veth);
++ return -1;
++ }
++ return 0;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From a8692d25ea7457443ad49dc9187ca54d7a8faa55 Mon Sep 17 00:00:00 2001
+Message-Id: <a8692d25ea7457443ad49dc9187ca54d7a8faa55.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:52 +0000
+Subject: [PATCH] Block all use of getenv with syntax-check
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+The use of getenv is typically insecure, and we want people
+to use our wrappers, to force them to think about setuid
+needs.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 71b21f12bece1127b28b404f11f57b4c2d48983a)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ cfg.mk | 8 ++++++++
+ src/util/virutil.c | 4 ++--
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/cfg.mk b/cfg.mk
+index aa2e1a1..f2cd411 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -836,6 +836,11 @@ sc_prohibit_unbounded_arrays_in_rpc:
+ halt='Arrays in XDR must have a upper limit set for <NNN>' \
+ $(_sc_search_regexp)
+
++sc_prohibit_getenv:
++ @prohibit='\b(secure_)?getenv *\(' \
++ exclude='exempt from syntax-check' \
++ halt='Use virGetEnv{Allow,Block}SUID instead of getenv' \
++ $(_sc_search_regexp)
+
+ # We don't use this feature of maint.mk.
+ prev_version_file = /dev/null
+@@ -1005,3 +1010,6 @@ exclude_file_name_regexp--sc_prohibit_include_public_headers_brackets = \
+
+ exclude_file_name_regexp--sc_prohibit_int_ijk = \
+ ^(src/remote_protocol-structs|src/remote/remote_protocol.x|cfg.mk|include/)$
++
++exclude_file_name_regexp--sc_prohibit_getenv = \
++ ^tests/.*\.[ch]$$
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index 2b3cbeb..21827f2 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -2108,7 +2108,7 @@ cleanup:
+ */
+ const char *virGetEnvBlockSUID(const char *name)
+ {
+- return secure_getenv(name);
++ return secure_getenv(name); /* exempt from syntax-check-rules */
+ }
+
+
+@@ -2122,7 +2122,7 @@ const char *virGetEnvBlockSUID(const char *name)
+ */
+ const char *virGetEnvAllowSUID(const char *name)
+ {
+- return getenv(name);
++ return getenv(name); /* exempt from syntax-check-rules */
+ }
+
+
+--
+1.8.4.2
+
--- /dev/null
+From b019d146357887bcf45b85b251f568d54e1bafb1 Mon Sep 17 00:00:00 2001
+Message-Id: <b019d146357887bcf45b85b251f568d54e1bafb1.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:57 +0000
+Subject: [PATCH] Block all use of libvirt.so in setuid programs
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+Avoid people introducing security flaws in their apps by
+forbidding the use of libvirt.so in setuid programs, with
+a check in virInitialize.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 9cd6a57db6ea6762fbf85c59c379a27fa6e7fd2e)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 54c90ec..e008368 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -409,6 +409,14 @@ virGlobalInit(void)
+ virErrorInitialize() < 0)
+ goto error;
+
++#ifndef IN_VIRT_LOGIN_SHELL
++ if (virIsSUID()) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("libvirt.so is not safe to use from setuid programs"));
++ goto error;
++ }
++#endif
++
+ #ifdef WITH_GNUTLS_GCRYPT
+ /*
+ * This sequence of API calls it copied exactly from
+--
+1.8.4.2
+
--- /dev/null
+From 252f0445c26644a711dc2c41ee2fcebe42eac742 Mon Sep 17 00:00:00 2001
+Message-Id: <252f0445c26644a711dc2c41ee2fcebe42eac742.1377873637.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:47 +0100
+Subject: [PATCH] Change data passed into TLS test cases
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+Currently a 'struct testTLSCertReq' instance is passed into
+the TLS test cases. This is not flexible enough to cope with
+certificate chains, where one file now corresponds to multiple
+certificates. Change the test cases so that we pass in filenames
+instead.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit b93bd78ed36570c1afe594182df927d94ea6ebaa)
+---
+ tests/virnettlscontexttest.c | 96 +++++++++++++++++++++---------------------
+ tests/virnettlssessiontest.c | 99 ++++++++++++++++++++++++--------------------
+ 2 files changed, 102 insertions(+), 93 deletions(-)
+
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 4211a74..3012c4a 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -42,8 +42,8 @@
+
+ struct testTLSContextData {
+ bool isServer;
+- struct testTLSCertReq careq;
+- struct testTLSCertReq certreq;
++ const char *cacrt;
++ const char *crt;
+ bool expectFail;
+ };
+
+@@ -63,17 +63,17 @@ static int testTLSContextInit(const void *opaque)
+ int ret = -1;
+
+ if (data->isServer) {
+- ctxt = virNetTLSContextNewServer(data->careq.filename,
++ ctxt = virNetTLSContextNewServer(data->cacrt,
+ NULL,
+- data->certreq.filename,
++ data->crt,
+ keyfile,
+ NULL,
+ true,
+ true);
+ } else {
+- ctxt = virNetTLSContextNewClient(data->careq.filename,
++ ctxt = virNetTLSContextNewClient(data->cacrt,
+ NULL,
+- data->certreq.filename,
++ data->crt,
+ keyfile,
+ true,
+ true);
+@@ -82,14 +82,14 @@ static int testTLSContextInit(const void *opaque)
+ if (ctxt) {
+ if (data->expectFail) {
+ VIR_WARN("Expected failure %s against %s",
+- data->careq.filename, data->certreq.filename);
++ data->cacrt, data->crt);
+ goto cleanup;
+ }
+ } else {
+ virErrorPtr err = virGetLastError();
+ if (!data->expectFail) {
+ VIR_WARN("Unexpected failure %s against %s",
+- data->careq.filename, data->certreq.filename);
++ data->cacrt, data->crt);
+ goto cleanup;
+ }
+ VIR_DEBUG("Got error %s", err ? err->message : "<unknown>");
+@@ -111,14 +111,14 @@ mymain(void)
+
+ testTLSInit();
+
+-# define DO_CTX_TEST(_isServer, _caReq, _certReq, _expectFail) \
++# define DO_CTX_TEST(_isServer, _caCrt, _crt, _expectFail) \
+ do { \
+ static struct testTLSContextData data; \
+ data.isServer = _isServer; \
+- data.careq = _caReq; \
+- data.certreq = _certReq; \
++ data.cacrt = _caCrt; \
++ data.crt = _crt; \
+ data.expectFail = _expectFail; \
+- if (virtTestRun("TLS Context " #_caReq " + " #_certReq, 1, \
++ if (virtTestRun("TLS Context " #_caCrt " + " #_crt, 1, \
+ testTLSContextInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+@@ -127,7 +127,7 @@ mymain(void)
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
+ static struct testTLSCertReq varname = { \
+- NULL, #varname ".pem", \
++ NULL, #varname "-ctx.pem", \
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \
+ }; \
+@@ -137,7 +137,7 @@ mymain(void)
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
+ static struct testTLSCertReq varname = { \
+- NULL, #varname ".pem", \
++ NULL, #varname "-ctx.pem", \
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \
+ }; \
+@@ -167,8 +167,8 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+- DO_CTX_TEST(true, cacertreq, servercertreq, false);
+- DO_CTX_TEST(false, cacertreq, clientcertreq, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercertreq.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcertreq.filename, false);
+
+
+ /* Some other CAs which are good */
+@@ -215,9 +215,9 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+- DO_CTX_TEST(true, cacert1req, servercert1req, false);
+- DO_CTX_TEST(true, cacert2req, servercert2req, false);
+- DO_CTX_TEST(true, cacert3req, servercert3req, false);
++ DO_CTX_TEST(true, cacert1req.filename, servercert1req.filename, false);
++ DO_CTX_TEST(true, cacert2req.filename, servercert2req.filename, false);
++ DO_CTX_TEST(true, cacert3req.filename, servercert3req.filename, false);
+
+ /* Now some bad certs */
+
+@@ -266,9 +266,9 @@ mymain(void)
+ * be rejected. GNUTLS < 3 does not reject it and
+ * we don't anticipate them changing this behaviour
+ */
+- DO_CTX_TEST(true, cacert4req, servercert4req, GNUTLS_VERSION_MAJOR >= 3);
+- DO_CTX_TEST(true, cacert5req, servercert5req, true);
+- DO_CTX_TEST(true, cacert6req, servercert6req, true);
++ DO_CTX_TEST(true, cacert4req.filename, servercert4req.filename, GNUTLS_VERSION_MAJOR >= 3);
++ DO_CTX_TEST(true, cacert5req.filename, servercert5req.filename, true);
++ DO_CTX_TEST(true, cacert6req.filename, servercert6req.filename, true);
+
+
+ /* Various good servers */
+@@ -322,13 +322,13 @@ mymain(void)
+ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+
+- DO_CTX_TEST(true, cacertreq, servercert7req, false);
+- DO_CTX_TEST(true, cacertreq, servercert8req, false);
+- DO_CTX_TEST(true, cacertreq, servercert9req, false);
+- DO_CTX_TEST(true, cacertreq, servercert10req, false);
+- DO_CTX_TEST(true, cacertreq, servercert11req, false);
+- DO_CTX_TEST(true, cacertreq, servercert12req, false);
+- DO_CTX_TEST(true, cacertreq, servercert13req, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert7req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert8req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert9req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert10req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert11req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert12req.filename, false);
++ DO_CTX_TEST(true, cacertreq.filename, servercert13req.filename, false);
+ /* Bad servers */
+
+ /* usage:cert-sign:critical */
+@@ -353,9 +353,9 @@ mymain(void)
+ false, false, NULL, NULL,
+ 0, 0);
+
+- DO_CTX_TEST(true, cacertreq, servercert14req, true);
+- DO_CTX_TEST(true, cacertreq, servercert15req, true);
+- DO_CTX_TEST(true, cacertreq, servercert16req, true);
++ DO_CTX_TEST(true, cacertreq.filename, servercert14req.filename, true);
++ DO_CTX_TEST(true, cacertreq.filename, servercert15req.filename, true);
++ DO_CTX_TEST(true, cacertreq.filename, servercert16req.filename, true);
+
+
+
+@@ -410,13 +410,13 @@ mymain(void)
+ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+
+- DO_CTX_TEST(false, cacertreq, clientcert1req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert2req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert3req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert4req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert5req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert6req, false);
+- DO_CTX_TEST(false, cacertreq, clientcert7req, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert1req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert2req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert3req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert4req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert5req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert6req.filename, false);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert7req.filename, false);
+ /* Bad clients */
+
+ /* usage:cert-sign:critical */
+@@ -441,9 +441,9 @@ mymain(void)
+ false, false, NULL, NULL,
+ 0, 0);
+
+- DO_CTX_TEST(false, cacertreq, clientcert8req, true);
+- DO_CTX_TEST(false, cacertreq, clientcert9req, true);
+- DO_CTX_TEST(false, cacertreq, clientcert10req, true);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert8req.filename, true);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert9req.filename, true);
++ DO_CTX_TEST(false, cacertreq.filename, clientcert10req.filename, true);
+
+
+
+@@ -474,9 +474,9 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, -1);
+
+- DO_CTX_TEST(true, cacertexpreq, servercertexpreq, true);
+- DO_CTX_TEST(true, cacertreq, servercertexp1req, true);
+- DO_CTX_TEST(false, cacertreq, clientcertexp1req, true);
++ DO_CTX_TEST(true, cacertexpreq.filename, servercertexpreq.filename, true);
++ DO_CTX_TEST(true, cacertreq.filename, servercertexp1req.filename, true);
++ DO_CTX_TEST(false, cacertreq.filename, clientcertexp1req.filename, true);
+
+
+ /* Not activated stuff */
+@@ -506,9 +506,9 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 1, 2);
+
+- DO_CTX_TEST(true, cacertnewreq, servercertnewreq, true);
+- DO_CTX_TEST(true, cacertreq, servercertnew1req, true);
+- DO_CTX_TEST(false, cacertreq, clientcertnew1req, true);
++ DO_CTX_TEST(true, cacertnewreq.filename, servercertnewreq.filename, true);
++ DO_CTX_TEST(true, cacertreq.filename, servercertnew1req.filename, true);
++ DO_CTX_TEST(false, cacertreq.filename, clientcertnew1req.filename, true);
+
+ testTLSDiscardCert(&cacertreq);
+ testTLSDiscardCert(&cacert1req);
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+index 370ba52..8636fc8 100644
+--- a/tests/virnettlssessiontest.c
++++ b/tests/virnettlssessiontest.c
+@@ -39,10 +39,10 @@
+ # define VIR_FROM_THIS VIR_FROM_RPC
+
+ struct testTLSSessionData {
+- struct testTLSCertReq careq;
+- struct testTLSCertReq othercareq;
+- struct testTLSCertReq serverreq;
+- struct testTLSCertReq clientreq;
++ const char *servercacrt;
++ const char *clientcacrt;
++ const char *servercrt;
++ const char *clientcrt;
+ bool expectServerFail;
+ bool expectClientFail;
+ const char *hostname;
+@@ -104,32 +104,29 @@ static int testTLSSessionInit(const void *opaque)
+ * want to make sure that problems are being
+ * detected at the TLS session validation stage
+ */
+- serverCtxt = virNetTLSContextNewServer(data->careq.filename,
++ serverCtxt = virNetTLSContextNewServer(data->servercacrt,
+ NULL,
+- data->serverreq.filename,
++ data->servercrt,
+ keyfile,
+ data->wildcards,
+ false,
+ true);
+
+- clientCtxt = virNetTLSContextNewClient(data->othercareq.filename ?
+- data->othercareq.filename :
+- data->careq.filename,
++ clientCtxt = virNetTLSContextNewClient(data->clientcacrt,
+ NULL,
+- data->clientreq.filename,
++ data->clientcrt,
+ keyfile,
+ false,
+ true);
+
+ if (!serverCtxt) {
+ VIR_WARN("Unexpected failure loading %s against %s",
+- data->careq.filename, data->serverreq.filename);
++ data->servercacrt, data->servercrt);
+ goto cleanup;
+ }
+ if (!clientCtxt) {
+ VIR_WARN("Unexpected failure loading %s against %s",
+- data->othercareq.filename ? data->othercareq.filename :
+- data->careq.filename, data->clientreq.filename);
++ data->clientcacrt, data->clientcrt);
+ goto cleanup;
+ }
+
+@@ -140,13 +137,12 @@ static int testTLSSessionInit(const void *opaque)
+
+ if (!serverSess) {
+ VIR_WARN("Unexpected failure using %s against %s",
+- data->careq.filename, data->serverreq.filename);
++ data->servercacrt, data->servercrt);
+ goto cleanup;
+ }
+ if (!clientSess) {
+ VIR_WARN("Unexpected failure using %s against %s",
+- data->othercareq.filename ? data->othercareq.filename :
+- data->careq.filename, data->clientreq.filename);
++ data->clientcacrt, data->clientcrt);
+ goto cleanup;
+ }
+
+@@ -242,38 +238,37 @@ mymain(void)
+
+ testTLSInit();
+
+-# define DO_SESS_TEST(_caReq, _serverReq, _clientReq, _expectServerFail,\
++# define DO_SESS_TEST(_caCrt, _serverCrt, _clientCrt, _expectServerFail, \
+ _expectClientFail, _hostname, _wildcards) \
+ do { \
+ static struct testTLSSessionData data; \
+- static struct testTLSCertReq other; \
+- data.careq = _caReq; \
+- data.othercareq = other; \
+- data.serverreq = _serverReq; \
+- data.clientreq = _clientReq; \
++ data.servercacrt = _caCrt; \
++ data.clientcacrt = _caCrt; \
++ data.servercrt = _serverCrt; \
++ data.clientcrt = _clientCrt; \
+ data.expectServerFail = _expectServerFail; \
+ data.expectClientFail = _expectClientFail; \
+ data.hostname = _hostname; \
+ data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \
++ if (virtTestRun("TLS Session " #_serverCrt " + " #_clientCrt, \
+ 1, testTLSSessionInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
+-# define DO_SESS_TEST_EXT(_caReq, _othercaReq, _serverReq, _clientReq, \
++# define DO_SESS_TEST_EXT(_serverCaCrt, _clientCaCrt, _serverCrt, _clientCrt, \
+ _expectServerFail, _expectClientFail, \
+ _hostname, _wildcards) \
+ do { \
+ static struct testTLSSessionData data; \
+- data.careq = _caReq; \
+- data.othercareq = _othercaReq; \
+- data.serverreq = _serverReq; \
+- data.clientreq = _clientReq; \
++ data.servercacrt = _serverCaCrt; \
++ data.clientcacrt = _clientCaCrt; \
++ data.servercrt = _serverCrt; \
++ data.clientcrt = _clientCrt; \
+ data.expectServerFail = _expectServerFail; \
+ data.expectClientFail = _expectClientFail; \
+ data.hostname = _hostname; \
+ data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \
++ if (virtTestRun("TLS Session " #_serverCrt " + " #_clientCrt, \
+ 1, testTLSSessionInit, &data) < 0) \
+ ret = -1; \
+ } while (0)
+@@ -282,7 +277,7 @@ mymain(void)
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
+ static struct testTLSCertReq varname = { \
+- NULL, #varname ".pem", \
++ NULL, #varname "-sess.pem", \
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \
+ }; \
+@@ -292,7 +287,7 @@ mymain(void)
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \
+ static struct testTLSCertReq varname = { \
+- NULL, #varname ".pem", \
++ NULL, #varname "-sess.pem", \
+ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \
+ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \
+ }; \
+@@ -335,8 +330,10 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL);
+- DO_SESS_TEST_EXT(cacertreq, altcacertreq, servercertreq, clientcertaltreq, true, true, "libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ false, false, "libvirt.org", NULL);
++ DO_SESS_TEST_EXT(cacertreq.filename, altcacertreq.filename, servercertreq.filename,
++ clientcertaltreq.filename, true, true, "libvirt.org", NULL);
+
+
+ /* When an altname is set, the CN is ignored, so it must be duplicated
+@@ -355,13 +352,19 @@ mymain(void)
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, true, "wiki.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename,
++ false, false, "libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename,
++ false, false, "www.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename,
++ false, true, "wiki.libvirt.org", NULL);
+
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, true, "libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "www.libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "wiki.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename,
++ false, true, "libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename,
++ false, false, "www.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename,
++ false, false, "wiki.libvirt.org", NULL);
+
+ const char *const wildcards1[] = {
+ "C=UK,CN=dogfood",
+@@ -389,12 +392,18 @@ mymain(void)
+ NULL,
+ };
+
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards1);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards2);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards3);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards4);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ true, false, "libvirt.org", wildcards1);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ false, false, "libvirt.org", wildcards2);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ false, false, "libvirt.org", wildcards3);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ true, false, "libvirt.org", wildcards4);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ false, false, "libvirt.org", wildcards5);
++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
++ false, false, "libvirt.org", wildcards6);
+
+ testTLSDiscardCert(&clientcertreq);
+ testTLSDiscardCert(&clientcertaltreq);
+--
+1.8.3.2
+
--- /dev/null
+From 47e18ab1d1b8a343e7d29f1f3884a040a18147c6 Mon Sep 17 00:00:00 2001
+Message-Id: <47e18ab1d1b8a343e7d29f1f3884a040a18147c6.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:14 +0100
+Subject: [PATCH] Change way we fake dbus method calls
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+Ubuntu libdbus.so links with -Bsymbolic-functions, which means
+that we can only LD_PRELOAD functions that we directly call.
+Functions which libdbus.so calls internally can not be replaced.
+Thus we cannot use dbus_message_new_error or dbus_message_new_method_return
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit dbd2bc8c8bdd927f3e9132afc8579dbaa1de91de)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/virsystemdmock.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/tests/virsystemdmock.c b/tests/virsystemdmock.c
+index ded52d2..5dbd33f 100644
+--- a/tests/virsystemdmock.c
++++ b/tests/virsystemdmock.c
+@@ -65,22 +65,32 @@ dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message ATTRIBUTE_UNUSED,
+ }
+
+ DBusMessage *dbus_connection_send_with_reply_and_block(DBusConnection *connection ATTRIBUTE_UNUSED,
+- DBusMessage *message,
++ DBusMessage *message ATTRIBUTE_UNUSED,
+ int timeout_milliseconds ATTRIBUTE_UNUSED,
+ DBusError *error)
+ {
+ DBusMessage *reply = NULL;
+
+- if (getenv("FAIL_BAD_SERVICE"))
+- reply = dbus_message_new_error(message,
+- "org.freedesktop.systemd.badthing",
+- "Something went wrong creating the machine");
+- else if (getenv("FAIL_NO_SERVICE"))
++ if (getenv("FAIL_BAD_SERVICE")) {
++ DBusMessageIter iter;
++ const char *error_message = "Something went wrong creating the machine";
++ if (!(reply = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR)))
++ return NULL;
++ dbus_message_set_error_name(reply, "org.freedesktop.systemd.badthing");
++ dbus_message_iter_init_append(reply, &iter);
++ if (!dbus_message_iter_append_basic(&iter,
++ DBUS_TYPE_STRING,
++ &error_message)) {
++ dbus_message_unref(reply);
++ return NULL;
++ }
++ } else if (getenv("FAIL_NO_SERVICE")) {
+ dbus_set_error(error,
+ "org.freedesktop.DBus.Error.ServiceUnknown",
+ "%s", "The name org.freedesktop.machine1 was not provided by any .service files");
+- else
+- reply = dbus_message_new_method_return(message);
++ } else {
++ reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
++ }
+
+ return reply;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From e93e8db21dfe3d62aa3f4684c3729de51b729feb Mon Sep 17 00:00:00 2001
+Message-Id: <e93e8db21dfe3d62aa3f4684c3729de51b729feb.1383321464.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:43 +0000
+Subject: [PATCH] Close all non-stdio FDs in virt-login-shell
+
+CVE-2013-4400
+
+We don't want to inherit any FDs in the new namespace
+except for the stdio FDs. Explicitly close them all,
+just in case some do not have the close-on-exec flag
+set.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit b7fcc799ad5d8f3e55b89b94e599903e3c092467)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tools/virt-login-shell.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+index 1157cd0..c2c9947 100644
+--- a/tools/virt-login-shell.c
++++ b/tools/virt-login-shell.c
+@@ -308,6 +308,18 @@ main(int argc, char **argv)
+ if (cpid == 0) {
+ pid_t ccpid;
+
++ int openmax = sysconf(_SC_OPEN_MAX);
++ int fd;
++ if (openmax < 0) {
++ virReportSystemError(errno, "%s",
++ _("sysconf(_SC_OPEN_MAX) failed"));
++ return EXIT_FAILURE;
++ }
++ for (fd = 3; fd < openmax; fd++) {
++ int tmpfd = fd;
++ VIR_MASS_CLOSE(tmpfd);
++ }
++
+ /* Fork once because we don't want to affect
+ * virt-login-shell's namespace itself
+ */
+--
+1.8.4.2
+
--- /dev/null
+From 8604ebe89c5267f34ee414fa62b69c5a5af3f62d Mon Sep 17 00:00:00 2001
+Message-Id: <8604ebe89c5267f34ee414fa62b69c5a5af3f62d.1381871413.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Tue, 15 Oct 2013 12:36:38 +0200
+Subject: [PATCH] Convert uuid to a string before printing it
+
+Introduced by 1fa7946.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1019023
+(cherry picked from commit 15fac93b951eb67553ca64443c740c1b975696a9)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 6 ++++--
+ src/storage/storage_backend_iscsi.c | 8 ++++++--
+ src/storage/storage_backend_rbd.c | 4 ++--
+ 3 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index dcce432..d455847 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -3113,11 +3113,13 @@ qemuGetSecretString(virConnectPtr conn,
+ size_t secret_size;
+ virSecretPtr sec = NULL;
+ char *secret = NULL;
++ char uuidStr[VIR_UUID_STRING_BUFLEN];
+
+ /* look up secret */
+ switch (diskSecretType) {
+ case VIR_DOMAIN_DISK_SECRET_TYPE_UUID:
+ sec = virSecretLookupByUUID(conn, uuid);
++ virUUIDFormat(uuid, uuidStr);
+ break;
+ case VIR_DOMAIN_DISK_SECRET_TYPE_USAGE:
+ sec = virSecretLookupByUsage(conn, secretUsageType, usage);
+@@ -3128,7 +3130,7 @@ qemuGetSecretString(virConnectPtr conn,
+ if (diskSecretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) {
+ virReportError(VIR_ERR_NO_SECRET,
+ _("%s no secret matches uuid '%s'"),
+- scheme, uuid);
++ scheme, uuidStr);
+ } else {
+ virReportError(VIR_ERR_NO_SECRET,
+ _("%s no secret matches usage value '%s'"),
+@@ -3144,7 +3146,7 @@ qemuGetSecretString(virConnectPtr conn,
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get value of the secret for "
+ "username '%s' using uuid '%s'"),
+- username, uuid);
++ username, uuidStr);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get value of the secret for "
+diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
+index e71ea46..556c2cc 100644
+--- a/src/storage/storage_backend_iscsi.c
++++ b/src/storage/storage_backend_iscsi.c
+@@ -44,6 +44,7 @@
+ #include "virobject.h"
+ #include "virrandom.h"
+ #include "virstring.h"
++#include "viruuid.h"
+
+ #define VIR_FROM_THIS VIR_FROM_STORAGE
+
+@@ -702,6 +703,7 @@ virStorageBackendISCSISetAuth(const char *portal,
+ unsigned char *secret_value = NULL;
+ virStoragePoolAuthChap chap;
+ int ret = -1;
++ char uuidStr[VIR_UUID_STRING_BUFLEN];
+
+ if (def->source.authType == VIR_STORAGE_POOL_AUTH_NONE)
+ return 0;
+@@ -733,10 +735,11 @@ virStorageBackendISCSISetAuth(const char *portal,
+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
+ if (!secret_value) {
+ if (chap.secret.uuidUsable) {
++ virUUIDFormat(chap.secret.uuid, uuidStr);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get the value of the secret "
+ "for username %s using uuid '%s'"),
+- chap.username, chap.secret.uuid);
++ chap.username, uuidStr);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get the value of the secret "
+@@ -747,9 +750,10 @@ virStorageBackendISCSISetAuth(const char *portal,
+ }
+ } else {
+ if (chap.secret.uuidUsable) {
++ virUUIDFormat(chap.secret.uuid, uuidStr);
+ virReportError(VIR_ERR_NO_SECRET,
+ _("no secret matches uuid '%s'"),
+- chap.secret.uuid);
++ uuidStr);
+ } else {
+ virReportError(VIR_ERR_NO_SECRET,
+ _("no secret matches usage value '%s'"),
+diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
+index d9e1789..60b48c2 100644
+--- a/src/storage/storage_backend_rbd.c
++++ b/src/storage/storage_backend_rbd.c
+@@ -94,7 +94,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
+ if (pool->def->source.auth.cephx.secret.uuidUsable) {
+ virReportError(VIR_ERR_NO_SECRET,
+ _("no secret matches uuid '%s'"),
+- pool->def->source.auth.cephx.secret.uuid);
++ secretUuid);
+ } else {
+ virReportError(VIR_ERR_NO_SECRET,
+ _("no secret matches usage value '%s'"),
+@@ -112,7 +112,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
+ _("could not get the value of the secret "
+ "for username '%s' using uuid '%s'"),
+ pool->def->source.auth.cephx.username,
+- pool->def->source.auth.cephx.secret.uuid);
++ secretUuid);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get the value of the secret "
+--
+1.8.3.2
+
--- /dev/null
+From 1e84e3165f8d37f8eebf862c6811f346cd8dbcca Mon Sep 17 00:00:00 2001
+Message-Id: <1e84e3165f8d37f8eebf862c6811f346cd8dbcca.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 31 Jul 2013 19:48:19 +0100
+Subject: [PATCH] Cope with races while killing processes
+
+https://bugzilla.redhat.com/show_bug.cgi?id=980929
+
+When systemd is involved in managing processes, it may start
+killing off & tearing down croups associated with the process
+while we're still doing virCgroupKillPainfully. We must
+explicitly check for ENOENT and treat it as if we had finished
+killing processes
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+
+(cherry picked from commit 75304eaa1a08b23e5206b352403de7d296fc069e)
+---
+ src/util/vircgroup.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 0e8bb79..a70bb98 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2550,6 +2550,12 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
+ while (!done) {
+ done = true;
+ if (!(fp = fopen(keypath, "r"))) {
++ if (errno == ENOENT) {
++ VIR_DEBUG("No file %s, assuming done", keypath);
++ killedAny = false;
++ goto done;
++ }
++
+ virReportSystemError(errno,
+ _("Failed to read %s"),
+ keypath);
+@@ -2589,6 +2595,7 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr
+ }
+ }
+
++ done:
+ ret = killedAny ? 1 : 0;
+
+ cleanup:
+@@ -2658,8 +2665,13 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
+ if (rc == 1)
+ killedAny = true;
+
+- VIR_DEBUG("Iterate over children of %s", keypath);
++ VIR_DEBUG("Iterate over children of %s (killedAny=%d)", keypath, killedAny);
+ if (!(dp = opendir(keypath))) {
++ if (errno == ENOENT) {
++ VIR_DEBUG("Path %s does not exist, assuming done", keypath);
++ killedAny = false;
++ goto done;
++ }
+ virReportSystemError(errno,
+ _("Cannot open %s"), keypath);
+ return -1;
+@@ -2689,6 +2701,7 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas
+ virCgroupFree(&subgroup);
+ }
+
++ done:
+ ret = killedAny ? 1 : 0;
+
+ cleanup:
+--
+1.8.3.2
+
--- /dev/null
+From 351d57a6576d6026ac0e3807030b07e877e5de07 Mon Sep 17 00:00:00 2001
+Message-Id: <351d57a6576d6026ac0e3807030b07e877e5de07.1381871412.git.jdenemar@redhat.com>
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Mon, 14 Oct 2013 16:45:13 +0100
+Subject: [PATCH] DBus: introduce virDBusIsServiceEnabled
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+This patch introduces virDBusIsServiceEnabled, we can use
+this method to get if the service is supported.
+
+In one case, if org.freedesktop.machine1 is unavailable on
+host, we should skip creating machine through systemd.
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+(cherry picked from commit 7ada155cdf2bbfac16ce08f64abb455a940e2cf7)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virdbus.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/util/virdbus.h | 1 +
+ src/util/virsystemd.c | 17 +++++---------
+ 3 files changed, 68 insertions(+), 11 deletions(-)
+
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index 62c31be..a2c4b4e 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -1207,6 +1207,61 @@ int virDBusMessageRead(DBusMessage *msg,
+ return ret;
+ }
+
++/**
++ * virDBusIsServiceEnabled:
++ * @name: service name
++ *
++ * Retruns 0 if service is available, -1 on fatal error, or -2 if service is not available
++ */
++int virDBusIsServiceEnabled(const char *name)
++{
++ DBusConnection *conn;
++ DBusMessage *reply = NULL;
++ DBusMessageIter iter, sub;
++ int ret = -1;
++
++ if (!virDBusHasSystemBus())
++ return -2;
++
++ conn = virDBusGetSystemBus();
++
++ if (virDBusCallMethod(conn,
++ &reply,
++ "org.freedesktop.DBus",
++ "/org/freedesktop/DBus",
++ "org.freedesktop.DBus",
++ "ListActivatableNames",
++ DBUS_TYPE_INVALID) < 0)
++ return ret;
++
++ if (!dbus_message_iter_init(reply, &iter) ||
++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Reply message incorrect"));
++ goto cleanup;
++ }
++
++ ret = -2;
++ dbus_message_iter_recurse(&iter, &sub);
++ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
++ const char *service = NULL;
++
++ dbus_message_iter_get_basic(&sub, &service);
++ dbus_message_iter_next(&sub);
++
++ if (STREQ(service, name)) {
++ ret = 0;
++ break;
++ }
++ }
++
++ VIR_DEBUG("Service %s is %s", name, ret ? "unavailable" : "available");
++
++ cleanup:
++ dbus_message_unref(reply);
++ return ret;
++}
++
+
+ #else /* ! WITH_DBUS */
+ DBusConnection *virDBusGetSystemBus(void)
+@@ -1271,4 +1326,10 @@ int virDBusMessageDecode(DBusMessage* msg ATTRIBUTE_UNUSED,
+ return -1;
+ }
+
++int virDBusIsServiceEnabled(const char *name ATTRIBUTE_UNUSED)
++{
++ VIR_DEBUG("DBus support not compiled into this binary");
++ return -2;
++}
++
+ #endif /* ! WITH_DBUS */
+diff --git a/src/util/virdbus.h b/src/util/virdbus.h
+index a5aab56..194a01a 100644
+--- a/src/util/virdbus.h
++++ b/src/util/virdbus.h
+@@ -45,4 +45,5 @@ int virDBusCallMethod(DBusConnection *conn,
+ int virDBusMessageRead(DBusMessage *msg,
+ const char *types, ...);
+
++int virDBusIsServiceEnabled(const char *name);
+ #endif /* __VIR_DBUS_H__ */
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index 13370b5..e72b7f0 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -138,18 +138,20 @@ int virSystemdCreateMachine(const char *name,
+ bool iscontainer,
+ const char *partition)
+ {
+- int ret = -1;
++ int ret;
+ DBusConnection *conn;
+ char *machinename = NULL;
+ char *creatorname = NULL;
+ char *username = NULL;
+ char *slicename = NULL;
+
+- if (!virDBusHasSystemBus())
+- return -2;
++ ret = virDBusIsServiceEnabled("org.freedesktop.machine1");
++ if (ret < 0)
++ return ret;
+
+ conn = virDBusGetSystemBus();
+
++ ret = -1;
+ if (privileged) {
+ if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0)
+ goto cleanup;
+@@ -228,15 +230,8 @@ int virSystemdCreateMachine(const char *name,
+ (unsigned int)pidleader,
+ rootdir ? rootdir : "",
+ 1, "Slice", "s",
+- slicename) < 0) {
+- virErrorPtr err = virGetLastError();
+- if (err->code == VIR_ERR_DBUS_SERVICE &&
+- STREQ(err->str2, "org.freedesktop.DBus.Error.ServiceUnknown")) {
+- virResetLastError();
+- ret = -2;
+- }
++ slicename) < 0)
+ goto cleanup;
+- }
+
+ ret = 0;
+
+--
+1.8.3.2
+
--- /dev/null
+From 79ca3c66fb28886ecaaf38220023d02efdddf66f Mon Sep 17 00:00:00 2001
+Message-Id: <79ca3c66fb28886ecaaf38220023d02efdddf66f.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 30 Jul 2013 11:24:22 +0100
+Subject: [PATCH] Delete obsolete / unused python test files
+
+https://bugzilla.redhat.com/show_bug.cgi?id=884103
+
+The python/tests directory contains a number of so called
+"tests" for the python API. These are all hardcoded to
+look for Xen and cannot be run in any automated fashion,
+and no one is ever manually running them. Given that they
+don't meaningully contribute to the test coverage, delete
+them.
+
+For some reason these tests were also copied into the
+filesystem as part of 'make install'. The change to the
+RPM in commit 3347a4203278ec93d7b0ceb88b5ed10e4f14765c
+caused a build failure, since it removed the code which
+deleted these installed tests.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 5bb2a245abbde4c0a407f631660e2f2c81bc4c02)
+---
+ configure.ac | 2 +-
+ python/Makefile.am | 2 -
+ python/tests/Makefile.am | 52 -----------------
+ python/tests/basic.py | 31 ----------
+ python/tests/create.py | 146 -----------------------------------------------
+ python/tests/error.py | 42 --------------
+ python/tests/node.py | 34 -----------
+ python/tests/uuid.py | 41 -------------
+ 8 files changed, 1 insertion(+), 349 deletions(-)
+ delete mode 100644 python/tests/Makefile.am
+ delete mode 100755 python/tests/basic.py
+ delete mode 100755 python/tests/create.py
+ delete mode 100755 python/tests/error.py
+ delete mode 100755 python/tests/node.py
+ delete mode 100755 python/tests/uuid.py
+
+diff --git a/configure.ac b/configure.ac
+index 35a5d76..084d864 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2447,7 +2447,7 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \
+ libvirt.pc libvirt.spec mingw-libvirt.spec \
+ po/Makefile.in \
+ include/libvirt/Makefile include/libvirt/libvirt.h \
+- python/Makefile python/tests/Makefile \
++ python/Makefile \
+ daemon/Makefile \
+ tools/Makefile \
+ tests/Makefile \
+diff --git a/python/Makefile.am b/python/Makefile.am
+index 7eb42c6..925e1f4 100644
+--- a/python/Makefile.am
++++ b/python/Makefile.am
+@@ -16,8 +16,6 @@
+ ## License along with this library. If not, see
+ ## <http://www.gnu.org/licenses/>.
+
+-SUBDIRS= . tests
+-
+ INCLUDES = \
+ $(PYTHON_INCLUDES) \
+ -I$(top_builddir)/gnulib/lib \
+diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
+deleted file mode 100644
+index 0fd3c78..0000000
+--- a/python/tests/Makefile.am
++++ /dev/null
+@@ -1,52 +0,0 @@
+-## Copyright (C) 2005-2011, 2013 Red Hat, Inc.
+-##
+-## This library is free software; you can redistribute it and/or
+-## modify it under the terms of the GNU Lesser General Public
+-## License as published by the Free Software Foundation; either
+-## version 2.1 of the License, or (at your option) any later version.
+-##
+-## This library is distributed in the hope that it will be useful,
+-## but WITHOUT ANY WARRANTY; without even the implied warranty of
+-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-## Lesser General Public License for more details.
+-##
+-## You should have received a copy of the GNU Lesser General Public
+-## License along with this library. If not, see
+-## <http://www.gnu.org/licenses/>.
+-
+-EXAMPLE_DIR = $(datadir)/doc/libvirt-python-$(VERSION)/examples
+-
+-PYTESTS= \
+- basic.py \
+- create.py \
+- uuid.py \
+- error.py \
+- node.py
+-
+-EXTRA_DIST = $(PYTESTS)
+-
+-if WITH_PYTHON
+-tests: $(PYTESTS)
+- @echo "## running Python regression tests"
+- -@(PYTHONPATH="..:../.libs:../src/.libs:$(srcdir)/../src:$$PYTHONPATH";\
+- export PYTHONPATH; \
+- LD_LIBRARY_PATH="$(top_builddir)/src/.libs:$$LD_LIBRARY_PATH" ; \
+- export LD_LIBRARY_PATH; \
+- for test in $(PYTESTS) ; \
+- do log=`$(PYTHON) $(srcdir)/$$test` ; \
+- if [ "`echo $$log | grep OK`" = "" ] ; then \
+- echo "-- $$test" ; echo "$$log" ; fi ; done)
+-else
+-tests:
+-endif
+-
+-clean:
+- rm -f *.pyc core
+-
+-install-data-local:
+- $(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR)
+- -(for test in $(PYTESTS); \
+- do $(INSTALL) -m 0644 $(srcdir)/$$test $(DESTDIR)$(EXAMPLE_DIR) ; done)
+-
+-uninstall-local:
+- for test in $(PYTESTS); do rm -f $(DESTDIR)$(EXAMPLE_DIR)/$$test; done
+diff --git a/python/tests/basic.py b/python/tests/basic.py
+deleted file mode 100755
+index c6dec81..0000000
+--- a/python/tests/basic.py
++++ /dev/null
+@@ -1,31 +0,0 @@
+-#!/usr/bin/python -u
+-import libvirt
+-import sys
+-import os
+-
+-if not os.access("/proc/xen", os.R_OK):
+- print 'System is not running a Xen kernel'
+- sys.exit(1)
+-
+-conn = libvirt.openReadOnly(None)
+-if conn == None:
+- print 'Failed to open connection to the hypervisor'
+- sys.exit(1)
+-
+-# print conn
+-
+-try:
+- dom0 = conn.lookupByName("Domain-0")
+-except:
+- print 'Failed to find the main domain'
+- sys.exit(1)
+-
+-# print dom0
+-
+-print "Domain 0: id %d running %s" % (dom0.ID(), dom0.OSType())
+-print dom0.info()
+-del dom0
+-del conn
+-print "OK"
+-
+-sys.exit(0)
+diff --git a/python/tests/create.py b/python/tests/create.py
+deleted file mode 100755
+index 815ccc4..0000000
+--- a/python/tests/create.py
++++ /dev/null
+@@ -1,146 +0,0 @@
+-#!/usr/bin/python -u
+-import libvirt
+-import sys
+-import os
+-import time
+-
+-if not os.access("/proc/xen", os.R_OK):
+- print 'System is not running a Xen kernel'
+- sys.exit(1)
+-
+-#
+-# Try to provide default OS images paths here, of course non standard
+-#
+-osroots = [
+- "/u/fc4-2.img",
+- "/u/fc4.img",
+- "/xen/fc4.img",
+-]
+-
+-okay = 1
+-
+-osroot = None
+-for root in osroots:
+- if os.access(root, os.R_OK):
+- osroot = root
+- break
+-
+-if osroot == None:
+- print "Could not find a guest OS root, edit to add the path in osroots"
+- sys.exit(1)
+-
+-kernel=open("/proc/version").read().split()
+-kernelOv = kernel[2]
+-
+-if kernelOv.find('hypervisor'):
+- kernelU = "/boot/vmlinuz-" + kernelOv.replace('hypervisor', 'guest')
+- initrdU = "/boot/initrd-" + kernelOv.replace('hypervisor', 'guest') + ".img"
+-elif kernelOv.find('xen0'):
+- kernelU = "/boot/vmlinuz-" + kernelOv.replace('xen0', 'xenU')
+- initrdU = "/boot/initrd-" + kernelOv.replace('xen0', 'xenU') + ".img"
+-
+-if not os.access(kernelU, os.R_OK):
+- print "Did not find the guest kernel %s" % (kernelU)
+- sys.exit(1)
+-
+-kernelU = "<kernel>" + kernelU + "</kernel>"
+-
+-if not os.access(initrdU, os.R_OK):
+- print "Did not find the guest initrd %s" % (initrdU)
+- initrdU = ""
+-else:
+- initrdU = "<initrd>" + initrdU + "</initrd>"
+-
+-
+-conn = libvirt.open(None)
+-if conn == None:
+- print 'Failed to open connection to the hypervisor'
+- sys.exit(1)
+-
+-xmldesc="""<domain type='xen'>
+- <name>test</name>
+- <os>
+- <type>linux</type>
+-""" + kernelU + initrdU + """
+- <cmdline> root=/dev/sda1 ro selinux=0 3</cmdline>
+- </os>
+- <memory>131072</memory>
+- <vcpu>1</vcpu>
+- <devices>
+- <disk type='file'>
+- <source file='%s'/>
+- <target dev='sda1'/>
+- </disk>
+- <interface type='bridge'>
+- <source bridge='xenbr0'/>
+- <mac address='aa:00:00:00:00:12'/>
+- <script path='/etc/xen/scripts/vif-bridge'/>
+- </interface>
+- </devices>
+-</domain>
+-""" % (osroot)
+-
+-dom = conn.createLinux(xmldesc, 0)
+-if dom == None:
+- print 'Failed to create a test domain'
+- sys.exit(1)
+-
+-# print dom
+-
+-print "Domain: id %d running %s" % (dom.ID(), dom.OSType())
+-
+-print "Suspending test domain for 5 seconds"
+-if dom.suspend() != 0:
+- print 'Failed to suspend domain test'
+- dom.destroy()
+- del dom
+- del conn
+- sys.exit(1)
+-
+-infos = dom.info()
+-time.sleep(5)
+-infos2 = dom.info()
+-if infos[4] != infos2[4]:
+- print 'Suspended domain test got CPU cycles'
+- okay = 0
+-
+-print "resuming test domain for 10 seconds"
+-if dom.resume() != 0:
+- print 'Failed to resume domain test'
+- dom.destroy()
+- del dom
+- del conn
+- sys.exit(1)
+-
+-time.sleep(10)
+-print "shutdown of test domain"
+-
+-if dom.shutdown() != 0:
+- okay = 0
+- print 'Failed to shutdown domain test'
+-
+-i = 0
+-while i < 30:
+- time.sleep(1)
+- i = i + 1
+- try:
+- t = dom.info()[4]
+- except:
+- okay = 0
+- t = -1
+- break
+-
+- if t == 0:
+- break
+-
+-if t != 0:
+- print 'Shutdown failed destroying domain test'
+- okay = 0
+- dom.destroy()
+-
+-del dom
+-del conn
+-if okay == 1:
+- print "OK"
+-
+-sys.exit(0)
+diff --git a/python/tests/error.py b/python/tests/error.py
+deleted file mode 100755
+index 295f9a7..0000000
+--- a/python/tests/error.py
++++ /dev/null
+@@ -1,42 +0,0 @@
+-#!/usr/bin/python -u
+-#
+-# Tests global error handlers at the python level.
+-#
+-import libvirt
+-import sys
+-import os
+-
+-errno = None
+-
+-def handler(ctxt, err):
+- global errno
+-
+- #print "handler(%s, %s)" % (ctxt, err)
+- errno = err
+-
+-libvirt.registerErrorHandler(handler, 'context')
+-
+-conn = libvirt.openReadOnly(None)
+-if conn == None:
+- print 'Failed to open connection to the hypervisor'
+- sys.exit(1)
+-
+-try:
+- dom0 = conn.lookupByName("Does_not_exist")
+- print 'strange found a Does_not_exist domain'
+- sys.exit(1)
+-except:
+- pass
+-
+-del conn
+-
+-if errno == None:
+- print 'failed to get an error'
+-elif errno[0] == libvirt.VIR_ERR_NO_CONNECT or \
+- errno[0] == libvirt.VIR_ERR_INVALID_DOMAIN or \
+- errno[0] == libvirt.VIR_ERR_GET_FAILED:
+- print "OK"
+-else:
+- print 'got unexpected error:', errno
+-
+-sys.exit(0)
+diff --git a/python/tests/node.py b/python/tests/node.py
+deleted file mode 100755
+index f199fc3..0000000
+--- a/python/tests/node.py
++++ /dev/null
+@@ -1,34 +0,0 @@
+-#!/usr/bin/python -u
+-import libvirt
+-import sys
+-import os
+-
+-if not os.access("/proc/xen", os.R_OK):
+- print 'System is not running a Xen kernel'
+- sys.exit(1)
+-
+-conn = libvirt.openReadOnly(None)
+-if conn == None:
+- print 'Failed to open connection to the hypervisor'
+- sys.exit(1)
+-
+-try:
+- (model, memory, cpus, mhz, nodes, socket, cores, threads) = conn.getInfo()
+-except:
+- print 'Failed to extract the current node information'
+- sys.exit(1)
+-
+-print "Xen running on %d %s processors at %d MHz, %d MBytes of memory" % (
+- cpus, model, mhz, memory)
+-
+-if cpus > nodes * socket * cores * threads:
+- print "Erroneous CPU information"
+- sys.exit(1)
+-
+-if cpus < nodes * socket * cores * threads:
+- print "Strange, running in degrated mode, some CPU are not available"
+-
+-del conn
+-print "OK"
+-
+-sys.exit(0)
+diff --git a/python/tests/uuid.py b/python/tests/uuid.py
+deleted file mode 100755
+index db48e80..0000000
+--- a/python/tests/uuid.py
++++ /dev/null
+@@ -1,41 +0,0 @@
+-#!/usr/bin/python -u
+-import libvirt
+-import sys
+-import os
+-
+-if not os.access("/proc/xen", os.R_OK):
+- print 'System is not running a Xen kernel'
+- sys.exit(1)
+-
+-conn = libvirt.openReadOnly(None)
+-if conn == None:
+- print 'Failed to open connection to the hypervisor'
+- sys.exit(1)
+-
+-ids = conn.listDomainsID()
+-if ids == None or len(ids) == 0:
+- print 'Failed to list running domains'
+- sys.exit(1)
+-
+-id = ids[-1]
+-
+-try:
+- dom = conn.lookupByID(id)
+-except:
+- print 'Failed to find the domain %d'
+- sys.exit(1)
+-
+-name0 = dom.name()
+-uuid = dom.UUID()
+-print "Using domain %s" % (name0)
+-try:
+- dom2 = conn.lookupByUUID(uuid)
+-except:
+- print 'Failed to lookup domain %d based on its UUID'
+- sys.exit(1)
+-if dom2.name() != name0:
+- print 'lookup of %s based on UUID brings a different domain %s' % (
+- name0, dom2.name())
+-
+-print "OK"
+-sys.exit(0)
+--
+1.8.3.2
+
--- /dev/null
+From d8290207c5743110e8504c8b449839f4eb638af6 Mon Sep 17 00:00:00 2001
+Message-Id: <d8290207c5743110e8504c8b449839f4eb638af6.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:54 +0000
+Subject: [PATCH] Don't allow remote driver daemon autostart when running
+ setuid
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+We don't want setuid programs automatically spawning libvirtd,
+so disable any use of autostart when setuid.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 171bb129115d49c567b643acaf20b363b124b8cf)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/remote/remote_driver.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index b6b629c..7688bf6 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -431,7 +431,7 @@ doRemoteOpen(virConnectPtr conn,
+ trans_tcp,
+ } transport;
+ #ifndef WIN32
+- const char *daemonPath;
++ const char *daemonPath = NULL;
+ #endif
+
+ /* We handle *ALL* URIs here. The caller has rejected any
+@@ -713,7 +713,8 @@ doRemoteOpen(virConnectPtr conn,
+ VIR_DEBUG("Proceeding with sockname %s", sockname);
+ }
+
+- if (!(daemonPath = remoteFindDaemonPath())) {
++ if ((flags & VIR_DRV_OPEN_REMOTE_AUTOSTART) &&
++ !(daemonPath = remoteFindDaemonPath())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to locate libvirtd daemon in %s "
+ "(to override, set $LIBVIRTD_PATH to the "
+@@ -997,8 +998,9 @@ remoteConnectOpen(virConnectPtr conn,
+ getuid() > 0) {
+ VIR_DEBUG("Auto-spawn user daemon instance");
+ rflags |= VIR_DRV_OPEN_REMOTE_USER;
+- if (!autostart ||
+- STRNEQ(autostart, "0"))
++ if (!virIsSUID() &&
++ (!autostart ||
++ STRNEQ(autostart, "0")))
+ rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
+ }
+
+@@ -1014,8 +1016,9 @@ remoteConnectOpen(virConnectPtr conn,
+ if (getuid() > 0) {
+ VIR_DEBUG("Auto-spawn user daemon instance");
+ rflags |= VIR_DRV_OPEN_REMOTE_USER;
+- if (!autostart ||
+- STRNEQ(autostart, "0"))
++ if (!virIsSUID() &&
++ (!autostart ||
++ STRNEQ(autostart, "0")))
+ rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
+ }
+ #endif
+--
+1.8.4.2
+
--- /dev/null
+From 040d07513c718a3473018ad1850469910cbe3cb2 Mon Sep 17 00:00:00 2001
+Message-Id: <040d07513c718a3473018ad1850469910cbe3cb2.1378475168.git.jdenemar@redhat.com>
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 2 Sep 2013 12:08:36 +0200
+Subject: [PATCH] Don't crash in qemuBuildDeviceAddressStr
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003526
+
+qemuDomainAttachVirtioDiskDevice passes NULL as domainDef which is later
+referenced in qemuDomainAttachVirtioDiskDevice:
+
+ Program terminated with signal 11, Segmentation fault.
+ #0 qemuBuildDeviceAddressStr (buf=buf@entry=0xb646de78, info=info@entry=0xb0a02360, qemuCaps=qemuCaps@entry=0xb8fdfdc8,
+ domainDef=<error reading variable: Unhandled dwarf expression opcode 0xfa>,
+ domainDef=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at qemu/qemu_command.c:2869
+ 2869 for (i = 0; i < domainDef->ncontrollers; i++) {
+ (gdb) bt
+ #0 qemuBuildDeviceAddressStr (buf=buf@entry=0xb646de78, info=info@entry=0xb0a02360, qemuCaps=qemuCaps@entry=0xb8fdfdc8,
+ domainDef=<error reading variable: Unhandled dwarf expression opcode 0xfa>,
+ domainDef=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at qemu/qemu_command.c:2869
+ #1 0xb18ad6f8 in qemuBuildDriveDevStr (def=def@entry=0x0, disk=disk@entry=0xb0a02288, bootindex=bootindex@entry=0, qemuCaps=0xb8fdfdc8)
+ at qemu/qemu_command.c:4316
+ #2 0xb18d097f in qemuDomainAttachVirtioDiskDevice (conn=conn@entry=0xb90129a8, driver=driver@entry=0xb8fe29b8, vm=vm@entry=0xb8fe0c40,
+ disk=disk@entry=0xb0a02288) at qemu/qemu_hotplug.c:278
+ #3 0xb193f7ba in qemuDomainAttachDeviceDiskLive (dev=0xb0a35308, vm=0xb8fe0c40, driver=0xb8fe29b8, conn=0xb90129a8) at qemu/qemu_driver.c:6356
+ #4 qemuDomainAttachDeviceLive (dev=0xb0a35308, vm=0xb8fe0c40, dom=<optimized out>) at qemu/qemu_driver.c:6418
+ #5 qemuDomainAttachDeviceFlags (dom=dom@entry=0xb0a020b8,
+ xml=xml@entry=0xb90953f0 "<disk type='file' device='disk'>\n <source file='/var/lib/jenkins/jobs/libvirt-tck-build/workspace/scratchdir/200-disk-hotplug/extra.img'/>\n <target dev='vdb' bus='virtio'/>\n</disk>\n", flags=3103664568, flags@entry=1) at qemu/qemu_driver.c:7079
+ #6 0xb193f9cb in qemuDomainAttachDevice (dom=0xb0a020b8,
+ xml=0xb90953f0 "<disk type='file' device='disk'>\n <source file='/var/lib/jenkins/jobs/libvirt-tck-build/workspace/scratchdir/200-disk-hotplug/extra.img'/>\n <target dev='vdb' bus='virtio'/>\n</disk>\n") at qemu/qemu_driver.c:7120
+ #7 0xb7244827 in virDomainAttachDevice (domain=domain@entry=0xb0a020b8,
+ xml=0xb90953f0 "<disk type='file' device='disk'>\n <source file='/var/lib/jenkins/jobs/libvirt-tck-build/workspace/scratchdir/200-disk-hotplug/extra.img'/>\n <target dev='vdb' bus='virtio'/>\n</disk>\n") at libvirt.c:10912
+ #8 0xb7765ddb in remoteDispatchDomainAttachDevice (args=0xb9094ef0, rerr=0xb646e1f0, client=<optimized out>, server=<optimized out>,
+ msg=<optimized out>) at remote_dispatch.h:2296
+ #9 remoteDispatchDomainAttachDeviceHelper (server=0xb8fba0e8, client=0xb0a00730, msg=0xb0a350b8, rerr=0xb646e1f0, args=0xb9094ef0, ret=0xb9094dc8)
+ at remote_dispatch.h:2274
+ #10 0xb72b1013 in virNetServerProgramDispatchCall (msg=0xb0a350b8, client=0xb0a00730, server=0xb8fba0e8, prog=0xb8fc21c8)
+ at rpc/virnetserverprogram.c:435
+ #11 virNetServerProgramDispatch (prog=0xb8fc21c8, server=server@entry=0xb8fba0e8, client=0xb0a00730, msg=0xb0a350b8) at rpc/virnetserverprogram.c:305
+ #12 0xb72aa167 in virNetServerProcessMsg (msg=<optimized out>, prog=<optimized out>, client=<optimized out>, srv=0xb8fba0e8)
+ at rpc/virnetserver.c:165
+ #13 virNetServerHandleJob (jobOpaque=0xb0a0a850, opaque=0xb8fba0e8) at rpc/virnetserver.c:186
+ #14 0xb7189108 in virThreadPoolWorker (opaque=opaque@entry=0xb8fa3250) at util/virthreadpool.c:144
+ #15 0xb71885e5 in virThreadHelper (data=0xb8fa32a8) at util/virthreadpthread.c:161
+ #16 0xb70d6954 in start_thread (arg=0xb646eb70) at pthread_create.c:304
+ #17 0xb704e95e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130
+
+This was found by libvirtt-tck:
+
+ http://honk.sigxcpu.org:8001/job/libvirt-tck-debian-wheezy-qemu-session/1311/console
+(cherry picked from commit bb97db2fb4315b7a7eb4403570d54c93992117de)
+---
+ src/qemu/qemu_hotplug.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 98b8ad1..83e193b 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -275,7 +275,7 @@ int qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
+ if (!(drivestr = qemuBuildDriveStr(conn, disk, false, priv->qemuCaps)))
+ goto error;
+
+- if (!(devstr = qemuBuildDriveDevStr(NULL, disk, 0, priv->qemuCaps)))
++ if (!(devstr = qemuBuildDriveDevStr(vm->def, disk, 0, priv->qemuCaps)))
+ goto error;
+ }
+
+@@ -616,7 +616,7 @@ int qemuDomainAttachUsbMassstorageDevice(virConnectPtr conn,
+ goto error;
+ if (!(drivestr = qemuBuildDriveStr(conn, disk, false, priv->qemuCaps)))
+ goto error;
+- if (!(devstr = qemuBuildDriveDevStr(NULL, disk, 0, priv->qemuCaps)))
++ if (!(devstr = qemuBuildDriveDevStr(vm->def, disk, 0, priv->qemuCaps)))
+ goto error;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From d49b62fca1ec33a7feed94ce6f44995164d83872 Mon Sep 17 00:00:00 2001
+Message-Id: <d49b62fca1ec33a7feed94ce6f44995164d83872.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Mon, 26 Aug 2013 16:01:43 +0200
+Subject: [PATCH] Don't free NULL network in cmdNetworkUpdate
+
+If the network has not been found, virNetworkFree(NULL)
+was called, resulting in an extra error:
+error: invalid network pointer in virNetworkFree
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001094
+
+(cherry picked from commit 784cca89c51fd13383064f248a6b375fb34e516f)
+---
+ tools/virsh-network.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/virsh-network.c b/tools/virsh-network.c
+index e1baf0b..06bf483 100644
+--- a/tools/virsh-network.c
++++ b/tools/virsh-network.c
+@@ -918,7 +918,7 @@ cmdNetworkUpdate(vshControl *ctl, const vshCmd *cmd)
+ const char *affected;
+
+ if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
+- goto cleanup;
++ return false;
+
+ if (vshCommandOptStringReq(ctl, cmd, "command", &commandStr) < 0)
+ goto cleanup;
+--
+1.8.3.2
+
--- /dev/null
+From 07efc2e98d4bd8796e4003f81baee53d3f83a06b Mon Sep 17 00:00:00 2001
+Message-Id: <07efc2e98d4bd8796e4003f81baee53d3f83a06b.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:24 +0100
+Subject: [PATCH] Don't ignore all dbus connection errors
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+Previous commit
+
+ commit 7ada155cdf2bbfac16ce08f64abb455a940e2cf7
+ Author: Gao feng <gaofeng@cn.fujitsu.com>
+ Date: Wed Sep 11 11:15:02 2013 +0800
+
+ DBus: introduce virDBusIsServiceEnabled
+
+Made the cgroups code fallback to non-systemd based setup
+when dbus is not running. It was too big a hammer though,
+as it did not check what error code was received when the
+dbus connection failed. Thus it silently ignored serious
+errors from dbus such as "too many client connections",
+which should always be treated as fatal.
+
+We only want to ignore errors if the dbus unix socket does
+not exist, or if nothing is listening on it.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 6bd886000100be2adce8650d0579a2303a7bf85b)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/nwfilter/nwfilter_driver.c | 5 +++--
+ src/util/virdbus.c | 22 +++++++++++++++++++---
+ src/util/virsystemd.c | 6 ++++--
+ 3 files changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
+index d25c6f2..6602d73 100644
+--- a/src/nwfilter/nwfilter_driver.c
++++ b/src/nwfilter/nwfilter_driver.c
+@@ -175,8 +175,9 @@ nwfilterStateInitialize(bool privileged,
+ DBusConnection *sysbus = NULL;
+
+ #if WITH_DBUS
+- if (virDBusHasSystemBus())
+- sysbus = virDBusGetSystemBus();
++ if (virDBusHasSystemBus() &&
++ !(sysbus = virDBusGetSystemBus()))
++ return -1;
+ #endif /* WITH_DBUS */
+
+ if (VIR_ALLOC(driverState) < 0)
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index da69430..94f3f47 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -111,14 +111,29 @@ virDBusGetSystemBus(void)
+ }
+
+
++/**
++ * virDBusHasSystemBus:
++ *
++ * Check if dbus system bus is running. This does not
++ * imply that we have a connection. DBus might be running
++ * and refusing connections due to its client limit. The
++ * latter must be treated as a fatal error.
++ *
++ * Return false if dbus is not available, true if probably available.
++ */
+ bool
+ virDBusHasSystemBus(void)
+ {
+ if (virDBusGetSystemBusInternal())
+ return true;
+
+- VIR_DEBUG("System DBus not available: %s", NULLSTR(systemdbuserr.message));
+- return false;
++ if (systemdbuserr.name &&
++ (STREQ(systemdbuserr.name, "org.freedesktop.DBus.Error.FileNotFound") ||
++ STREQ(systemdbuserr.name, "org.freedesktop.DBus.Error.NoServer"))) {
++ VIR_DEBUG("System DBus not available: %s", NULLSTR(systemdbuserr.message));
++ return false;
++ }
++ return true;
+ }
+
+
+@@ -1240,7 +1255,8 @@ int virDBusIsServiceEnabled(const char *name)
+ if (!virDBusHasSystemBus())
+ return -2;
+
+- conn = virDBusGetSystemBus();
++ if (!(conn = virDBusGetSystemBus()))
++ return -1;
+
+ if (virDBusCallMethod(conn,
+ &reply,
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index 1ba37cc..503fff7 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -169,7 +169,8 @@ int virSystemdCreateMachine(const char *name,
+ if (ret < 0)
+ return ret;
+
+- conn = virDBusGetSystemBus();
++ if (!(conn = virDBusGetSystemBus()))
++ return -1;
+
+ ret = -1;
+ if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged)))
+@@ -267,7 +268,8 @@ int virSystemdTerminateMachine(const char *name,
+ if (ret < 0)
+ return ret;
+
+- conn = virDBusGetSystemBus();
++ if (!(conn = virDBusGetSystemBus()))
++ return -1;
+
+ ret = -1;
+ if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged)))
+--
+1.8.3.2
+
--- /dev/null
+From 969db345161bd108c3d38eee0da68fbc66e79f08 Mon Sep 17 00:00:00 2001
+Message-Id: <969db345161bd108c3d38eee0da68fbc66e79f08.1383321464.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:44 +0000
+Subject: [PATCH] Don't link virt-login-shell against libvirt.so
+
+CVE-2013-4400
+
+The libvirt.so library has far too many library deps to allow
+linking against it from setuid programs. Those libraries can
+do stuff in __attribute__((constructor) functions which is
+not setuid safe.
+
+The virt-login-shell needs to link directly against individual
+files that it uses, with all library deps turned off except
+for libxml2 and libselinux.
+
+Create a libvirt-setuid-rpc-client.la library which is linked
+to by virt-login-shell. A config-post.h file allows this library
+to disable all external deps except libselinux and libxml2.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 3e2f27e13b94f7302ad948bcacb5e02c859a25fc)
+
+Conflicts:
+ tools/Makefile.am: Due to missing d9527b6d565f0561c7920db65b841b0e13041827
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ Makefile.am | 1 +
+ config-post.h | 44 ++++++++++++++++++
+ configure.ac | 1 +
+ daemon/Makefile.am | 1 +
+ examples/domain-events/events-c/Makefile.am | 3 +-
+ examples/hellolibvirt/Makefile.am | 2 +-
+ examples/openauth/Makefile.am | 2 +-
+ gnulib/lib/Makefile.am | 2 +-
+ python/Makefile.am | 1 +
+ src/Makefile.am | 72 +++++++++++++++++++++++++++++
+ src/libvirt.c | 36 +++++++++------
+ tools/Makefile.am | 9 +++-
+ 12 files changed, 153 insertions(+), 21 deletions(-)
+ create mode 100644 config-post.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 4e24ecf..15bd5bf 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -31,6 +31,7 @@ XML_EXAMPLES = \
+ test/*.xml storage/*.xml)))
+
+ EXTRA_DIST = \
++ config-post.h \
+ ChangeLog-old \
+ libvirt.spec libvirt.spec.in \
+ mingw-libvirt.spec.in \
+diff --git a/config-post.h b/config-post.h
+new file mode 100644
+index 0000000..d371e8c
+--- /dev/null
++++ b/config-post.h
+@@ -0,0 +1,44 @@
++/*
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * Since virt-login-shell will be setuid, we must do everything
++ * we can to avoid linking to other libraries. Many of them do
++ * unsafe things in functions marked __atttribute__((constructor)).
++ * The only way avoid to avoid such deps is to re-compile the
++ * functions with the code in question disabled, and for that we
++ * must override the main config.h rules. Hence this file :-(
++ */
++
++#ifdef LIBVIRT_SETUID_RPC_CLIENT
++# undef HAVE_LIBDEVMAPPER_H
++# undef HAVE_LIBNL
++# undef HAVE_LIBNL3
++# undef HAVE_LIBSASL2
++# undef WITH_CAPNG
++# undef WITH_CURL
++# undef WITH_DTRACE_PROBES
++# undef WITH_GNUTLS
++# undef WITH_MACVTAP
++# undef WITH_NUMACTL
++# undef WITH_SASL
++# undef WITH_SSH2
++# undef WITH_VIRTUALPORT
++# undef WITH_YAJL
++# undef WITH_YAJL2
++#endif
+diff --git a/configure.ac b/configure.ac
+index 7dd6ca3..cdb2969 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -20,6 +20,7 @@ AC_INIT([libvirt], [1.1.1], [libvir-list@redhat.com], [], [http://libvirt.org])
+ AC_CONFIG_SRCDIR([src/libvirt.c])
+ AC_CONFIG_AUX_DIR([build-aux])
+ AC_CONFIG_HEADERS([config.h])
++AH_BOTTOM([#include <config-post.h>])
+ AC_CONFIG_MACRO_DIR([m4])
+ dnl Make automake keep quiet about wildcards & other GNUmake-isms
+ AM_INIT_AUTOMAKE([-Wno-portability tar-ustar])
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index ad7544c..7dbfcec 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -18,6 +18,7 @@
+
+ INCLUDES = \
+ -I$(top_builddir)/gnulib/lib -I$(top_srcdir)/gnulib/lib \
++ -I$(top_srcdir) \
+ -I$(top_builddir)/include -I$(top_srcdir)/include \
+ -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+diff --git a/examples/domain-events/events-c/Makefile.am b/examples/domain-events/events-c/Makefile.am
+index 0646aee..86500a0 100644
+--- a/examples/domain-events/events-c/Makefile.am
++++ b/examples/domain-events/events-c/Makefile.am
+@@ -15,7 +15,8 @@
+ ## <http://www.gnu.org/licenses/>.
+
+ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
+- -I$(top_builddir)/gnulib/lib -I$(top_srcdir)/gnulib/lib
++ -I$(top_builddir)/gnulib/lib -I$(top_srcdir)/gnulib/lib \
++ -I$(top_srcdir)
+ noinst_PROGRAMS = event-test
+ event_test_CFLAGS = $(WARN_CFLAGS)
+ event_test_SOURCES = event-test.c
+diff --git a/examples/hellolibvirt/Makefile.am b/examples/hellolibvirt/Makefile.am
+index 060cc71..55ea972 100644
+--- a/examples/hellolibvirt/Makefile.am
++++ b/examples/hellolibvirt/Makefile.am
+@@ -14,7 +14,7 @@
+ ## License along with this library. If not, see
+ ## <http://www.gnu.org/licenses/>.
+
+-INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
++INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)
+ noinst_PROGRAMS = hellolibvirt
+ hellolibvirt_CFLAGS = $(WARN_CFLAGS)
+ hellolibvirt_SOURCES = hellolibvirt.c
+diff --git a/examples/openauth/Makefile.am b/examples/openauth/Makefile.am
+index 1eb23fc..7bb8604 100644
+--- a/examples/openauth/Makefile.am
++++ b/examples/openauth/Makefile.am
+@@ -14,7 +14,7 @@
+ ## License along with this library. If not, see
+ ## <http://www.gnu.org/licenses/>.
+
+-INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
++INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)
+ noinst_PROGRAMS = openauth
+ openauth_CFLAGS = $(WARN_CFLAGS)
+ openauth_SOURCES = openauth.c
+diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am
+index e27c658..f098e82 100644
+--- a/gnulib/lib/Makefile.am
++++ b/gnulib/lib/Makefile.am
+@@ -27,4 +27,4 @@ noinst_LTLIBRARIES =
+
+ include gnulib.mk
+
+-INCLUDES = $(GETTEXT_CPPFLAGS)
++INCLUDES = -I$(top_srcdir) $(GETTEXT_CPPFLAGS)
+diff --git a/python/Makefile.am b/python/Makefile.am
+index 925e1f4..5ef9f1c 100644
+--- a/python/Makefile.am
++++ b/python/Makefile.am
+@@ -20,6 +20,7 @@ INCLUDES = \
+ $(PYTHON_INCLUDES) \
+ -I$(top_builddir)/gnulib/lib \
+ -I$(top_srcdir)/gnulib/lib \
++ -I$(top_srcdir) \
+ -I$(top_builddir)/src \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 5976a68..969d09b 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -21,6 +21,7 @@
+ # that actually use them. Also keep GETTEXT_CPPFLAGS at the end.
+ INCLUDES = -I../gnulib/lib \
+ -I$(top_srcdir)/gnulib/lib \
++ -I$(top_srcdir) \
+ -I../include \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/util \
+@@ -1914,6 +1915,77 @@ libvirt_lxc_la_LDFLAGS = \
+ libvirt_lxc_la_CFLAGS = $(AM_CFLAGS)
+ libvirt_lxc_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
+
++# Since virt-login-shell will be setuid, we must do everything
++# we can to avoid linking to other libraries. Many of them do
++# unsafe things in functions marked __atttribute__((constructor)).
++# This library is built to include the bare minimum required to
++# have a RPC client for local UNIX socket access only. We use
++# the ../config-post.h header to disable all external deps that
++# we don't want
++if WITH_LXC
++noinst_LTLIBRARIES += libvirt-setuid-rpc-client.la
++
++libvirt_setuid_rpc_client_la_SOURCES = \
++ util/viralloc.c \
++ util/virbitmap.c \
++ util/virbuffer.c \
++ util/vircommand.c \
++ util/virconf.c \
++ util/virerror.c \
++ util/virevent.c \
++ util/vireventpoll.c \
++ util/virfile.c \
++ util/virhash.c \
++ util/virhashcode.c \
++ util/virjson.c \
++ util/virlog.c \
++ util/virobject.c \
++ util/virpidfile.c \
++ util/virprocess.c \
++ util/virrandom.c \
++ util/virsocketaddr.c \
++ util/virstoragefile.c \
++ util/virstring.c \
++ util/virtime.c \
++ util/virthread.c \
++ util/virtypedparam.c \
++ util/viruri.c \
++ util/virutil.c \
++ util/viruuid.c \
++ conf/domain_event.c \
++ rpc/virnetsocket.c \
++ rpc/virnetsocket.h \
++ rpc/virnetmessage.h \
++ rpc/virnetmessage.c \
++ rpc/virkeepalive.c \
++ rpc/virkeepalive.h \
++ rpc/virnetclient.c \
++ rpc/virnetclientprogram.c \
++ rpc/virnetclientstream.c \
++ rpc/virnetprotocol.c \
++ remote/remote_driver.c \
++ remote/remote_protocol.c \
++ remote/qemu_protocol.c \
++ remote/lxc_protocol.c \
++ datatypes.c \
++ libvirt.c \
++ libvirt-lxc.c \
++ $(NULL)
++
++libvirt_setuid_rpc_client_la_LDFLAGS = \
++ $(AM_LDFLAGS) \
++ $(LIBXML_LIBS) \
++ $(SELINUX_LIBS) \
++ $(NULL)
++libvirt_setuid_rpc_client_la_CFLAGS = \
++ -DLIBVIRT_SETUID_RPC_CLIENT \
++ -I$(top_srcdir)/src/conf \
++ -I$(top_srcdir)/src/rpc \
++ $(AM_CFLAGS) \
++ $(SELINUX_CFLAGS) \
++ $(NULL)
++endif WITH_LXC
++
+ lockdriverdir = $(libdir)/libvirt/lock-driver
+ lockdriver_LTLIBRARIES =
+
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 1a6c771..4c1992c 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -446,40 +446,46 @@ virGlobalInit(void)
+ goto error;
+
+ /*
++ * Note we must avoid everything except 'remote' driver
++ * for virt-login-shell usage
++ */
++#ifndef LIBVIRT_SETUID_RPC_CLIENT
++ /*
+ * Note that the order is important: the first ones have a higher
+ * priority when calling virConnectOpen.
+ */
+-#ifdef WITH_TEST
++# ifdef WITH_TEST
+ if (testRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_OPENVZ
++# endif
++# ifdef WITH_OPENVZ
+ if (openvzRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_VMWARE
++# endif
++# ifdef WITH_VMWARE
+ if (vmwareRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_PHYP
++# endif
++# ifdef WITH_PHYP
+ if (phypRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_ESX
++# endif
++# ifdef WITH_ESX
+ if (esxRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_HYPERV
++# endif
++# ifdef WITH_HYPERV
+ if (hypervRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_XENAPI
++# endif
++# ifdef WITH_XENAPI
+ if (xenapiRegister() == -1)
+ goto error;
+-#endif
+-#ifdef WITH_PARALLELS
++# endif
++# ifdef WITH_PARALLELS
+ if (parallelsRegister() == -1)
+ goto error;
++# endif
+ #endif
+ #ifdef WITH_REMOTE
+ if (remoteRegister() == -1)
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index d48883c..9ae4004 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -133,6 +133,11 @@ virt_host_validate_CFLAGS = \
+ $(COVERAGE_CFLAGS) \
+ $(NULL)
+
++# Since virt-login-shell will be setuid, we must do everything
++# we can to avoid linking to other libraries. Many of them do
++# unsafe things in functions marked __atttribute__((constructor)).
++# This we statically link to a library containing only the minimal
++# libvirt client code, not libvirt.so itself.
+ virt_login_shell_SOURCES = \
+ virt-login-shell.c
+
+@@ -141,11 +146,11 @@ virt_login_shell_LDADD = \
+ $(STATIC_BINARIES) \
+ $(PIE_LDFLAGS) \
+ $(RELRO_LDFLAGS) \
+- ../src/libvirt.la \
+- ../src/libvirt-lxc.la \
++ ../src/libvirt-setuid-rpc-client.la \
+ ../gnulib/lib/libgnu.la
+
+ virt_login_shell_CFLAGS = \
++ -DLIBVIRT_SETUID_RPC_CLIENT \
+ $(WARN_CFLAGS) \
+ $(PIE_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+--
+1.8.4.2
+
--- /dev/null
+From afca26500a5a66d5a833fe2c2be81db385c4971d Mon Sep 17 00:00:00 2001
+Message-Id: <afca26500a5a66d5a833fe2c2be81db385c4971d.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 16:43:11 +0100
+Subject: [PATCH] Don't pass virConnectPtr in nwfilter 'struct
+ domUpdateCBStruct'
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015108
+
+The nwfilter driver only needs a reference to its private
+state object, not a full virConnectPtr. Update the domUpdateCBStruct
+struct to have a 'void *opaque' field instead of a virConnectPtr.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit ebca369e3fe5ac999c261c2d44e60a1bac3cfe65)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/nwfilter_conf.c | 14 +++++++++++---
+ src/conf/nwfilter_conf.h | 4 ++--
+ src/nwfilter/nwfilter_dhcpsnoop.c | 12 ++++++------
+ src/nwfilter/nwfilter_driver.c | 5 +++--
+ src/nwfilter/nwfilter_gentech_driver.c | 32 ++++++++++++++++----------------
+ src/nwfilter/nwfilter_gentech_driver.h | 10 +++++-----
+ src/nwfilter/nwfilter_learnipaddr.c | 6 +++---
+ 7 files changed, 46 insertions(+), 37 deletions(-)
+
+diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
+index 54a492d..424c396 100644
+--- a/src/conf/nwfilter_conf.c
++++ b/src/conf/nwfilter_conf.c
+@@ -2849,6 +2849,7 @@ virNWFilterCallbackDriversUnlock(void)
+
+
+ static virDomainObjListIterator virNWFilterDomainFWUpdateCB;
++static void *virNWFilterDomainFWUpdateOpaque;
+
+ /**
+ * virNWFilterInstFiltersOnAllVMs:
+@@ -2860,7 +2861,7 @@ virNWFilterInstFiltersOnAllVMs(virConnectPtr conn)
+ {
+ size_t i;
+ struct domUpdateCBStruct cb = {
+- .conn = conn,
++ .opaque = virNWFilterDomainFWUpdateOpaque,
+ .step = STEP_APPLY_CURRENT,
+ .skipInterfaces = NULL, /* not needed */
+ };
+@@ -2879,7 +2880,7 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
+ size_t i;
+ int ret = 0;
+ struct domUpdateCBStruct cb = {
+- .conn = conn,
++ .opaque = virNWFilterDomainFWUpdateOpaque,
+ .step = STEP_APPLY_NEW,
+ .skipInterfaces = virHashCreate(0, NULL),
+ };
+@@ -3473,9 +3474,14 @@ char *virNWFilterConfigFile(const char *dir,
+ }
+
+
+-int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB)
++int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB,
++ void *opaque)
+ {
++ if (initialized)
++ return -1;
++
+ virNWFilterDomainFWUpdateCB = domUpdateCB;
++ virNWFilterDomainFWUpdateOpaque = opaque;
+
+ initialized = true;
+
+@@ -3494,6 +3500,8 @@ void virNWFilterConfLayerShutdown(void)
+ virMutexDestroy(&updateMutex);
+
+ initialized = false;
++ virNWFilterDomainFWUpdateOpaque = NULL;
++ virNWFilterDomainFWUpdateCB = NULL;
+ }
+
+
+diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
+index faa7527..e470615 100644
+--- a/src/conf/nwfilter_conf.h
++++ b/src/conf/nwfilter_conf.h
+@@ -586,7 +586,7 @@ enum UpdateStep {
+ };
+
+ struct domUpdateCBStruct {
+- virConnectPtr conn;
++ void *opaque;
+ enum UpdateStep step;
+ virHashTablePtr skipInterfaces;
+ };
+@@ -722,7 +722,7 @@ void virNWFilterObjUnlock(virNWFilterObjPtr obj);
+ void virNWFilterLockFilterUpdates(void);
+ void virNWFilterUnlockFilterUpdates(void);
+
+-int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB);
++int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB, void *opaque);
+ void virNWFilterConfLayerShutdown(void);
+
+ int virNWFilterInstFiltersOnAllVMs(virConnectPtr conn);
+diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
+index 3e9f046..2bc1686 100644
+--- a/src/nwfilter/nwfilter_dhcpsnoop.c
++++ b/src/nwfilter/nwfilter_dhcpsnoop.c
+@@ -481,15 +481,15 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl,
+ /* instantiate the filters */
+
+ if (req->ifname)
+- rc = virNWFilterInstantiateFilterLate(NULL,
++ rc = virNWFilterInstantiateFilterLate(req->driver,
++ NULL,
+ req->ifname,
+ req->ifindex,
+ req->linkdev,
+ req->nettype,
+ &req->macaddr,
+ req->filtername,
+- req->vars,
+- req->driver);
++ req->vars);
+
+ exit_snooprequnlock:
+ virNWFilterSnoopReqUnlock(req);
+@@ -867,15 +867,15 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req,
+ goto skip_instantiate;
+
+ if (ipAddrLeft) {
+- ret = virNWFilterInstantiateFilterLate(NULL,
++ ret = virNWFilterInstantiateFilterLate(req->driver,
++ NULL,
+ req->ifname,
+ req->ifindex,
+ req->linkdev,
+ req->nettype,
+ &req->macaddr,
+ req->filtername,
+- req->vars,
+- req->driver);
++ req->vars);
+ } else {
+ const virNWFilterVarValuePtr dhcpsrvrs =
+ virHashLookup(req->vars->hashTable, NWFILTER_VARNAME_DHCPSERVER);
+diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
+index 2cae0d0..0a515e7 100644
+--- a/src/nwfilter/nwfilter_driver.c
++++ b/src/nwfilter/nwfilter_driver.c
+@@ -201,7 +201,8 @@ nwfilterStateInitialize(bool privileged,
+
+ virNWFilterTechDriversInit(privileged);
+
+- if (virNWFilterConfLayerInit(virNWFilterDomainFWUpdateCB) < 0)
++ if (virNWFilterConfLayerInit(virNWFilterDomainFWUpdateCB,
++ driverState) < 0)
+ goto err_techdrivers_shutdown;
+
+ /*
+@@ -676,7 +677,7 @@ nwfilterInstantiateFilter(virConnectPtr conn,
+ const unsigned char *vmuuid,
+ virDomainNetDefPtr net)
+ {
+- return virNWFilterInstantiateFilter(conn, vmuuid, net);
++ return virNWFilterInstantiateFilter(conn->nwfilterPrivateData, vmuuid, net);
+ }
+
+
+diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
+index ee9195b..f517569 100644
+--- a/src/nwfilter/nwfilter_gentech_driver.c
++++ b/src/nwfilter/nwfilter_gentech_driver.c
+@@ -800,7 +800,8 @@ err_unresolvable_vars:
+ * Call this function while holding the NWFilter filter update lock
+ */
+ static int
+-__virNWFilterInstantiateFilter(const unsigned char *vmuuid,
++__virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver,
++ const unsigned char *vmuuid,
+ bool teardownOld,
+ const char *ifname,
+ int ifindex,
+@@ -810,7 +811,6 @@ __virNWFilterInstantiateFilter(const unsigned char *vmuuid,
+ const char *filtername,
+ virNWFilterHashTablePtr filterparams,
+ enum instCase useNewFilter,
+- virNWFilterDriverStatePtr driver,
+ bool forceWithPendingReq,
+ bool *foundNewFilter)
+ {
+@@ -921,7 +921,7 @@ err_exit:
+
+
+ static int
+-_virNWFilterInstantiateFilter(virConnectPtr conn,
++_virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver,
+ const unsigned char *vmuuid,
+ const virDomainNetDefPtr net,
+ bool teardownOld,
+@@ -948,7 +948,8 @@ _virNWFilterInstantiateFilter(virConnectPtr conn,
+ goto cleanup;
+ }
+
+- rc = __virNWFilterInstantiateFilter(vmuuid,
++ rc = __virNWFilterInstantiateFilter(driver,
++ vmuuid,
+ teardownOld,
+ net->ifname,
+ ifindex,
+@@ -958,7 +959,6 @@ _virNWFilterInstantiateFilter(virConnectPtr conn,
+ net->filter,
+ net->filterparams,
+ useNewFilter,
+- conn->nwfilterPrivateData,
+ false,
+ foundNewFilter);
+
+@@ -970,22 +970,23 @@ cleanup:
+
+
+ int
+-virNWFilterInstantiateFilterLate(const unsigned char *vmuuid,
++virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver,
++ const unsigned char *vmuuid,
+ const char *ifname,
+ int ifindex,
+ const char *linkdev,
+ enum virDomainNetType nettype,
+ const virMacAddrPtr macaddr,
+ const char *filtername,
+- virNWFilterHashTablePtr filterparams,
+- virNWFilterDriverStatePtr driver)
++ virNWFilterHashTablePtr filterparams)
+ {
+ int rc;
+ bool foundNewFilter = false;
+
+ virNWFilterLockFilterUpdates();
+
+- rc = __virNWFilterInstantiateFilter(vmuuid,
++ rc = __virNWFilterInstantiateFilter(driver,
++ vmuuid,
+ true,
+ ifname,
+ ifindex,
+@@ -995,7 +996,6 @@ virNWFilterInstantiateFilterLate(const unsigned char *vmuuid,
+ filtername,
+ filterparams,
+ INSTANTIATE_ALWAYS,
+- driver,
+ true,
+ &foundNewFilter);
+ if (rc < 0) {
+@@ -1015,13 +1015,13 @@ virNWFilterInstantiateFilterLate(const unsigned char *vmuuid,
+
+
+ int
+-virNWFilterInstantiateFilter(virConnectPtr conn,
++virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver,
+ const unsigned char *vmuuid,
+ const virDomainNetDefPtr net)
+ {
+ bool foundNewFilter = false;
+
+- return _virNWFilterInstantiateFilter(conn, vmuuid, net,
++ return _virNWFilterInstantiateFilter(driver, vmuuid, net,
+ 1,
+ INSTANTIATE_ALWAYS,
+ &foundNewFilter);
+@@ -1029,14 +1029,14 @@ virNWFilterInstantiateFilter(virConnectPtr conn,
+
+
+ int
+-virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
++virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver,
+ const unsigned char *vmuuid,
+ const virDomainNetDefPtr net,
+ bool *skipIface)
+ {
+ bool foundNewFilter = false;
+
+- int rc = _virNWFilterInstantiateFilter(conn, vmuuid, net,
++ int rc = _virNWFilterInstantiateFilter(driver, vmuuid, net,
+ 0,
+ INSTANTIATE_FOLLOW_NEWFILTER,
+ &foundNewFilter);
+@@ -1154,7 +1154,7 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj,
+ if ((net->filter) && (net->ifname)) {
+ switch (cb->step) {
+ case STEP_APPLY_NEW:
+- ret = virNWFilterUpdateInstantiateFilter(cb->conn,
++ ret = virNWFilterUpdateInstantiateFilter(cb->opaque,
+ vm->uuid,
+ net,
+ &skipIface);
+@@ -1179,7 +1179,7 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj,
+ break;
+
+ case STEP_APPLY_CURRENT:
+- ret = virNWFilterInstantiateFilter(cb->conn,
++ ret = virNWFilterInstantiateFilter(cb->opaque,
+ vm->uuid,
+ net);
+ if (ret)
+diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h
+index 4b47b4a..8528e2a 100644
+--- a/src/nwfilter/nwfilter_gentech_driver.h
++++ b/src/nwfilter/nwfilter_gentech_driver.h
+@@ -39,23 +39,23 @@ enum instCase {
+ };
+
+
+-int virNWFilterInstantiateFilter(virConnectPtr conn,
++int virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver,
+ const unsigned char *vmuuid,
+ const virDomainNetDefPtr net);
+-int virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
++int virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver,
+ const unsigned char *vmuuid,
+ const virDomainNetDefPtr net,
+ bool *skipIface);
+
+-int virNWFilterInstantiateFilterLate(const unsigned char *vmuuid,
++int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver,
++ const unsigned char *vmuuid,
+ const char *ifname,
+ int ifindex,
+ const char *linkdev,
+ enum virDomainNetType nettype,
+ const virMacAddrPtr macaddr,
+ const char *filtername,
+- virNWFilterHashTablePtr filterparams,
+- virNWFilterDriverStatePtr driver);
++ virNWFilterHashTablePtr filterparams);
+
+ int virNWFilterTeardownFilter(const virDomainNetDefPtr net);
+
+diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c
+index 7e67203..093158a 100644
+--- a/src/nwfilter/nwfilter_learnipaddr.c
++++ b/src/nwfilter/nwfilter_learnipaddr.c
+@@ -612,15 +612,15 @@ learnIPAddressThread(void *arg)
+ "cache for interface %s"), inetaddr, req->ifname);
+ }
+
+- ret = virNWFilterInstantiateFilterLate(NULL,
++ ret = virNWFilterInstantiateFilterLate(req->driver,
++ NULL,
+ req->ifname,
+ req->ifindex,
+ req->linkdev,
+ req->nettype,
+ &req->macaddr,
+ req->filtername,
+- req->filterparams,
+- req->driver);
++ req->filterparams);
+ VIR_DEBUG("Result from applying firewall rules on "
+ "%s with IP addr %s : %d\n", req->ifname, inetaddr, ret);
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 20832604f4fb7568148bcf277452a2981ff2456d Mon Sep 17 00:00:00 2001
+Message-Id: <20832604f4fb7568148bcf277452a2981ff2456d.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 17:17:27 +0100
+Subject: [PATCH] Don't set netdev offline in container cleanup
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+During container cleanup there is a race where the kernel may
+have destroyed the veth device before we try to set it offline.
+This causes log error messages. Given that we're about to
+delete the device entirely, setting it offline is pointless.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit f5eae5708623401f50a07729283624423894ed68)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_process.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index 0a28305..bc9bdfb 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -192,7 +192,6 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
+ virDomainNetDefPtr iface = vm->def->nets[i];
+ vport = virDomainNetGetActualVirtPortProfile(iface);
+ if (iface->ifname) {
+- ignore_value(virNetDevSetOnline(iface->ifname, false));
+ if (vport &&
+ vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+--
+1.8.3.2
+
--- /dev/null
+From ba776c58abac13bd5a539cd128c002284a363f58 Mon Sep 17 00:00:00 2001
+Message-Id: <ba776c58abac13bd5a539cd128c002284a363f58.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 31 Jul 2013 19:48:20 +0100
+Subject: [PATCH] Enable support for systemd-machined in cgroups creation
+
+https://bugzilla.redhat.com/show_bug.cgi?id=980929
+
+Make the virCgroupNewMachine method try to use systemd-machined
+first. If that fails, then fallback to using the traditional
+cgroup setup code path.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+
+(cherry picked from commit 2fe2470181ce3722788fd7125d3f1f9be87e6278)
+---
+ src/lxc/lxc_process.c | 10 +--
+ src/qemu/qemu_cgroup.c | 1 +
+ src/util/vircgroup.c | 187 ++++++++++++++++++++++++++++++++++++++++++++-----
+ src/util/vircgroup.h | 1 +
+ 4 files changed, 179 insertions(+), 20 deletions(-)
+
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index 247e516..0a28305 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -1203,8 +1203,9 @@ int virLXCProcessStart(virConnectPtr conn,
+ goto cleanup;
+ }
+
+- if (virCgroupNewDetectMachine(vm->def->name, "lxc",
+- vm->pid, -1, &priv->cgroup) < 0)
++ if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
++ vm->def->resource->partition,
++ -1, &priv->cgroup) < 0)
+ goto error;
+
+ if (!priv->cgroup) {
+@@ -1411,8 +1412,9 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm,
+ if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
+ goto error;
+
+- if (virCgroupNewDetectMachine(vm->def->name, "lxc",
+- vm->pid, -1, &priv->cgroup) < 0)
++ if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
++ vm->def->resource->partition,
++ -1, &priv->cgroup) < 0)
+ goto error;
+
+ if (!priv->cgroup) {
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index 9f6b251..787ddeb 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -707,6 +707,7 @@ qemuConnectCgroup(virQEMUDriverPtr driver,
+ if (virCgroupNewDetectMachine(vm->def->name,
+ "qemu",
+ vm->pid,
++ vm->def->resource->partition,
+ cfg->cgroupControllers,
+ &priv->cgroup) < 0)
+ goto cleanup;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a70bb98..cfb4b3f 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -50,6 +50,7 @@
+ #include "virhash.h"
+ #include "virhashcode.h"
+ #include "virstring.h"
++#include "virsystemd.h"
+
+ #define CGROUP_MAX_VAL 512
+
+@@ -102,11 +103,13 @@ static bool
+ virCgroupValidateMachineGroup(virCgroupPtr group,
+ const char *name,
+ const char *drivername,
++ const char *partition,
+ bool stripEmulatorSuffix)
+ {
+ size_t i;
+ bool valid = false;
+ char *partname;
++ char *scopename;
+
+ if (virAsprintf(&partname, "%s.libvirt-%s",
+ name, drivername) < 0)
+@@ -115,6 +118,15 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+ if (virCgroupPartitionEscape(&partname) < 0)
+ goto cleanup;
+
++ if (!partition)
++ partition = "/machine";
++
++ if (!(scopename = virSystemdMakeScopeName(name, drivername, partition)))
++ goto cleanup;
++
++ if (virCgroupPartitionEscape(&scopename) < 0)
++ goto cleanup;
++
+ for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+ char *tmp;
+
+@@ -142,9 +154,10 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+ tmp++;
+
+ if (STRNEQ(tmp, name) &&
+- STRNEQ(tmp, partname)) {
+- VIR_DEBUG("Name '%s' for controller '%s' does not match '%s' or '%s'",
+- tmp, virCgroupControllerTypeToString(i), name, partname);
++ STRNEQ(tmp, partname) &&
++ STRNEQ(tmp, scopename)) {
++ VIR_DEBUG("Name '%s' for controller '%s' does not match '%s', '%s' or '%s'",
++ tmp, virCgroupControllerTypeToString(i), name, partname, scopename);
+ goto cleanup;
+ }
+ }
+@@ -153,6 +166,7 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+
+ cleanup:
+ VIR_FREE(partname);
++ VIR_FREE(scopename);
+ return valid;
+ }
+ #else
+@@ -1649,6 +1663,7 @@ int virCgroupNewDetect(pid_t pid ATTRIBUTE_UNUSED,
+ int virCgroupNewDetectMachine(const char *name,
+ const char *drivername,
+ pid_t pid,
++ const char *partition,
+ int controllers,
+ virCgroupPtr *group)
+ {
+@@ -1658,7 +1673,7 @@ int virCgroupNewDetectMachine(const char *name,
+ return -1;
+ }
+
+- if (!virCgroupValidateMachineGroup(*group, name, drivername, true)) {
++ if (!virCgroupValidateMachineGroup(*group, name, drivername, partition, true)) {
+ VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
+ name, drivername);
+ virCgroupFree(group);
+@@ -1668,22 +1683,124 @@ int virCgroupNewDetectMachine(const char *name,
+ return 0;
+ }
+
+-int virCgroupNewMachine(const char *name,
+- const char *drivername,
+- bool privileged ATTRIBUTE_UNUSED,
+- const unsigned char *uuid ATTRIBUTE_UNUSED,
+- const char *rootdir ATTRIBUTE_UNUSED,
+- pid_t pidleader ATTRIBUTE_UNUSED,
+- bool isContainer ATTRIBUTE_UNUSED,
+- const char *partition,
+- int controllers,
+- virCgroupPtr *group)
++/*
++ * Returns 0 on success, -1 on fatal error, -2 on systemd not available
++ */
++static int
++virCgroupNewMachineSystemd(const char *name,
++ const char *drivername,
++ bool privileged,
++ const unsigned char *uuid,
++ const char *rootdir,
++ pid_t pidleader,
++ bool isContainer,
++ const char *partition,
++ int controllers,
++ virCgroupPtr *group)
+ {
+- virCgroupPtr parent = NULL;
+ int ret = -1;
++ int rv;
++ virCgroupPtr init, parent = NULL;
++ char *path = NULL;
++ char *offset;
++
++ VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
++ if ((rv = virSystemdCreateMachine(name,
++ drivername,
++ privileged,
++ uuid,
++ rootdir,
++ pidleader,
++ isContainer,
++ partition)) < 0)
++ return rv;
++
++ if (controllers != -1)
++ controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD);
++
++ VIR_DEBUG("Detecting systemd placement");
++ if (virCgroupNewDetect(pidleader,
++ controllers,
++ &init) < 0)
++ return -1;
+
+- *group = NULL;
++ path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement;
++ init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL;
++ virCgroupFree(&init);
++
++ if (!path || STREQ(path, "/") || path[0] != '/') {
++ VIR_DEBUG("Systemd didn't setup its controller");
++ ret = -2;
++ goto cleanup;
++ }
++
++ offset = path;
++
++ if (virCgroupNew(pidleader,
++ "",
++ NULL,
++ controllers,
++ &parent) < 0)
++ goto cleanup;
++
++
++ for (;;) {
++ virCgroupPtr tmp;
++ char *t = strchr(offset + 1, '/');
++ if (t)
++ *t = '\0';
++
++ if (virCgroupNew(pidleader,
++ path,
++ parent,
++ controllers,
++ &tmp) < 0)
++ goto cleanup;
++
++ if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_NONE) < 0) {
++ virCgroupFree(&tmp);
++ goto cleanup;
++ }
++ if (t) {
++ *t = '/';
++ offset = t;
++ virCgroupFree(&parent);
++ parent = tmp;
++ } else {
++ *group = tmp;
++ break;
++ }
++ }
++
++ if (virCgroupAddTask(*group, pidleader) < 0) {
++ virErrorPtr saved = virSaveLastError();
++ virCgroupRemove(*group);
++ virCgroupFree(group);
++ if (saved) {
++ virSetError(saved);
++ virFreeError(saved);
++ }
++ }
++
++ ret = 0;
++ cleanup:
++ virCgroupFree(&parent);
++ VIR_FREE(path);
++ return ret;
++}
+
++static int
++virCgroupNewMachineManual(const char *name,
++ const char *drivername,
++ pid_t pidleader,
++ const char *partition,
++ int controllers,
++ virCgroupPtr *group)
++{
++ virCgroupPtr parent = NULL;
++ int ret = -1;
++
++ VIR_DEBUG("Fallback to non-systemd setup");
+ if (virCgroupNewPartition(partition,
+ STREQ(partition, "/machine"),
+ controllers,
+@@ -1719,6 +1836,44 @@ cleanup:
+ return ret;
+ }
+
++int virCgroupNewMachine(const char *name,
++ const char *drivername,
++ bool privileged,
++ const unsigned char *uuid,
++ const char *rootdir,
++ pid_t pidleader,
++ bool isContainer,
++ const char *partition,
++ int controllers,
++ virCgroupPtr *group)
++{
++ int rv;
++
++ *group = NULL;
++
++ if ((rv = virCgroupNewMachineSystemd(name,
++ drivername,
++ privileged,
++ uuid,
++ rootdir,
++ pidleader,
++ isContainer,
++ partition,
++ controllers,
++ group)) == 0)
++ return 0;
++
++ if (rv == -1)
++ return -1;
++
++ return virCgroupNewMachineManual(name,
++ drivername,
++ pidleader,
++ partition,
++ controllers,
++ group);
++}
++
+ bool virCgroupNewIgnoreError(void)
+ {
+ if (virLastErrorIsSystemErrno(ENXIO) ||
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index e579f41..d7ce892 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -83,6 +83,7 @@ int virCgroupNewDetect(pid_t pid,
+ int virCgroupNewDetectMachine(const char *name,
+ const char *drivername,
+ pid_t pid,
++ const char *partition,
+ int controllers,
+ virCgroupPtr *group);
+
+--
+1.8.3.2
+
--- /dev/null
+From 2e8315d0699d051ad77d9c8f667bad7669ead44b Mon Sep 17 00:00:00 2001
+Message-Id: <2e8315d0699d051ad77d9c8f667bad7669ead44b.1375465853.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 2 Aug 2013 12:15:15 +0100
+Subject: [PATCH] Ensure LXC/QEMU APIs set the filename for errors
+
+https://bugzilla.redhat.com/show_bug.cgi?id=991348
+
+The virLibConnError macros in libvirt-lxc.c and
+libvirt-qemu.c were passing NULL for the filename.
+This causes a crash if the logging code is configured
+to use journald.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit cb3868f701bda3e3f71f9161b4a7f19106600fa6)
+---
+ src/libvirt-lxc.c | 6 +++---
+ src/libvirt-qemu.c | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
+index da69dce..c8cdcea 100644
+--- a/src/libvirt-lxc.c
++++ b/src/libvirt-lxc.c
+@@ -35,12 +35,12 @@
+
+ #define VIR_FROM_THIS VIR_FROM_NONE
+
+-#define virLibConnError(conn, error, info) \
+- virReportErrorHelper(VIR_FROM_NONE, error, NULL, __FUNCTION__, \
++#define virLibConnError(conn, error, info) \
++ virReportErrorHelper(VIR_FROM_NONE, error, __FILE__, __FUNCTION__, \
+ __LINE__, info)
+
+ #define virLibDomainError(domain, error, info) \
+- virReportErrorHelper(VIR_FROM_DOM, error, NULL, __FUNCTION__, \
++ virReportErrorHelper(VIR_FROM_DOM, error, __FILE__, __FUNCTION__, \
+ __LINE__, info)
+
+ /**
+diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c
+index 2a1432b..83fb3b3 100644
+--- a/src/libvirt-qemu.c
++++ b/src/libvirt-qemu.c
+@@ -29,12 +29,12 @@
+
+ #define VIR_FROM_THIS VIR_FROM_NONE
+
+-#define virLibConnError(conn, error, info) \
+- virReportErrorHelper(VIR_FROM_NONE, error, NULL, __FUNCTION__, \
++#define virLibConnError(conn, error, info) \
++ virReportErrorHelper(VIR_FROM_NONE, error, __FILE__, __FUNCTION__, \
+ __LINE__, info)
+
+ #define virLibDomainError(domain, error, info) \
+- virReportErrorHelper(VIR_FROM_DOM, error, NULL, __FUNCTION__, \
++ virReportErrorHelper(VIR_FROM_DOM, error, __FILE__, __FUNCTION__, \
+ __LINE__, info)
+
+ /**
+--
+1.8.3.2
+
--- /dev/null
+From 7f9ba4690a2d5353e0b66686ce2569a795e225c4 Mon Sep 17 00:00:00 2001
+Message-Id: <7f9ba4690a2d5353e0b66686ce2569a795e225c4.1383922566.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:21 +0100
+Subject: [PATCH] Ensure 'arch' is always set in cpuArchNodeData
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+The s390, ppc and arm CPU drivers never set the 'arch' field
+in their impl of cpuArchNodeData. This leads to error messages
+being reported from cpuDataFree later, due to trying to use
+VIR_ARCH_NONE.
+
+ #0 virRaiseErrorFull (filename=filename@entry=0x76f94434 "cpu/cpu.c", funcname=funcname@entry=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58,
+ domain=domain@entry=31, code=code@entry=1, level=level@entry=VIR_ERR_ERROR, str1=0x76f70e18 "internal error: %s",
+ str2=str2@entry=0x7155f2ec "undefined hardware architecture", str3=str3@entry=0x0, int1=int1@entry=-1, int2=int2@entry=-1, fmt=0x76f70e18 "internal error: %s")
+ at util/virerror.c:646
+ #1 0x76e682ea in virReportErrorHelper (domcode=domcode@entry=31, errorcode=errorcode@entry=1, filename=0x76f94434 "cpu/cpu.c",
+ funcname=0x76f942dc <__FUNCTION__.18096> "cpuGetSubDriver", linenr=linenr@entry=58, fmt=0x76f7e7e4 "%s") at util/virerror.c:1292
+ #2 0x76ed82d4 in cpuGetSubDriver (arch=<optimized out>) at cpu/cpu.c:57
+ #3 cpuGetSubDriver (arch=VIR_ARCH_NONE) at cpu/cpu.c:51
+ #4 0x76ed8818 in cpuDataFree (data=data@entry=0x70c22d78) at cpu/cpu.c:216
+ #5 0x716aaec0 in virQEMUCapsInitCPU (arch=VIR_ARCH_ARMV7L, caps=0x70c29a08) at qemu/qemu_capabilities.c:867
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 66ec11ade4664c85a158a2c309517baa8b5b048f)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu.c | 2 +-
+ src/cpu/cpu.h | 2 +-
+ src/cpu/cpu_arm.c | 8 ++++++--
+ src/cpu/cpu_powerpc.c | 12 +++++-------
+ src/cpu/cpu_s390.c | 4 +++-
+ src/cpu/cpu_x86.c | 4 ++--
+ 6 files changed, 18 insertions(+), 14 deletions(-)
+
+diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
+index 7989b45..2660761 100644
+--- a/src/cpu/cpu.c
++++ b/src/cpu/cpu.c
+@@ -244,7 +244,7 @@ cpuNodeData(virArch arch)
+ return NULL;
+ }
+
+- return driver->nodeData();
++ return driver->nodeData(arch);
+ }
+
+
+diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
+index ad6ccfb..f016e2f 100644
+--- a/src/cpu/cpu.h
++++ b/src/cpu/cpu.h
+@@ -69,7 +69,7 @@ typedef void
+ (*cpuArchDataFree) (virCPUDataPtr data);
+
+ typedef virCPUDataPtr
+-(*cpuArchNodeData) (void);
++(*cpuArchNodeData) (virArch arch);
+
+ typedef virCPUCompareResult
+ (*cpuArchGuestData) (virCPUDefPtr host,
+diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
+index 25e25ba..c7dbffc 100644
+--- a/src/cpu/cpu_arm.c
++++ b/src/cpu/cpu_arm.c
+@@ -31,11 +31,15 @@
+ static const virArch archs[] = { VIR_ARCH_ARMV7L };
+
+ static virCPUDataPtr
+-ArmNodeData(void)
++ArmNodeData(virArch arch)
+ {
+ virCPUDataPtr data;
+
+- ignore_value(VIR_ALLOC(data));
++ if (VIR_ALLOC(data) < 0)
++ return NULL;
++
++ data->arch = arch;
++
+ return data;
+ }
+
+diff --git a/src/cpu/cpu_powerpc.c b/src/cpu/cpu_powerpc.c
+index 55a4153..be07af1 100644
+--- a/src/cpu/cpu_powerpc.c
++++ b/src/cpu/cpu_powerpc.c
+@@ -350,21 +350,23 @@ ppcDataFree(virCPUDataPtr data)
+ VIR_FREE(data);
+ }
+
+-#if defined(__powerpc__) || defined(__powerpc64__)
+ static virCPUDataPtr
+-ppcNodeData(void)
++ppcNodeData(virArch arch)
+ {
+ virCPUDataPtr cpuData;
+
+ if (VIR_ALLOC(cpuData) < 0)
+ return NULL;
+
++ cpuData->arch = arch;
++
++#if defined(__powerpc__) || defined(__powerpc64__)
+ asm("mfpvr %0"
+ : "=r" (cpuData->data.ppc.pvr));
++#endif
+
+ return cpuData;
+ }
+-#endif
+
+ static int
+ ppcUpdate(virCPUDefPtr guest ATTRIBUTE_UNUSED,
+@@ -468,11 +470,7 @@ struct cpuArchDriver cpuDriverPowerPC = {
+ .decode = ppcDecode,
+ .encode = NULL,
+ .free = ppcDataFree,
+-#if defined(__powerpc__) || defined(__powerpc64__)
+ .nodeData = ppcNodeData,
+-#else
+- .nodeData = NULL,
+-#endif
+ .guestData = NULL,
+ .baseline = ppcBaseline,
+ .update = ppcUpdate,
+diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c
+index cbfae42..e0d3174 100644
+--- a/src/cpu/cpu_s390.c
++++ b/src/cpu/cpu_s390.c
+@@ -32,13 +32,15 @@
+ static const virArch archs[] = { VIR_ARCH_S390, VIR_ARCH_S390X };
+
+ static virCPUDataPtr
+-s390NodeData(void)
++s390NodeData(virArch arch)
+ {
+ virCPUDataPtr data;
+
+ if (VIR_ALLOC(data) < 0)
+ return NULL;
+
++ data->arch = arch;
++
+ return data;
+ }
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 083cfee..e8e1990 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1731,7 +1731,7 @@ cpuidSet(uint32_t base, virCPUx86CPUID **set)
+
+
+ static virCPUDataPtr
+-x86NodeData(void)
++x86NodeData(virArch arch)
+ {
+ virCPUDataPtr cpuData = NULL;
+ virCPUx86Data *data;
+@@ -1748,7 +1748,7 @@ x86NodeData(void)
+ goto error;
+ data->extended_len = ret;
+
+- if (!(cpuData = x86MakeCPUData(virArchFromHost(), &data)))
++ if (!(cpuData = x86MakeCPUData(arch, &data)))
+ goto error;
+
+ return cpuData;
+--
+1.8.4.2
+
--- /dev/null
+From 044dc48da47a5f5b2dd32212075da4b5e34840e8 Mon Sep 17 00:00:00 2001
+Message-Id: <044dc48da47a5f5b2dd32212075da4b5e34840e8.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:26 +0100
+Subject: [PATCH] Ensure lxcContainerMain reports errors on stderr
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+Ensure the lxcContainerMain method reports any errors that
+occur during setup to stderr, where libvirtd will pick them
+up.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 558546fb8f7104ad7fbdd14c615404618ce91453)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index f6375b7..06fb08d 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1876,6 +1876,15 @@ cleanup:
+ ret = virCommandExec(cmd);
+ }
+
++ if (ret != 0) {
++ virErrorPtr err = virGetLastError();
++ if (err && err->message)
++ fprintf(stderr, "%s\n", err->message);
++ else
++ fprintf(stderr, "%s\n",
++ _("Unknown failure in libvirt_lxc startup"));
++ }
++
+ virCommandFree(cmd);
+ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 614eed200e78648bcc536a7ec41e238fb91e105e Mon Sep 17 00:00:00 2001
+Message-Id: <614eed200e78648bcc536a7ec41e238fb91e105e.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:27 +0100
+Subject: [PATCH] Ensure lxcContainerResolveSymlinks reports errors
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+The lxcContainerResolveSymlinks method merely logged some errors
+as debug messages, rather than reporting them as proper errors.
+This meant startup failures were not diagnosed at all.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 01100c7f60cee7b9075110b1e4b397dfff1a17ba)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index 06fb08d..9479498 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1668,7 +1668,6 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+ {
+ char *newroot;
+ size_t i;
+- char ebuf[1024];
+
+ VIR_DEBUG("Resolving symlinks");
+
+@@ -1678,14 +1677,16 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+ continue;
+
+ if (access(fs->src, F_OK)) {
+- VIR_DEBUG("Failed to access '%s': %s", fs->src,
+- virStrerror(errno, ebuf, sizeof(ebuf)));
++ virReportSystemError(errno,
++ _("Failed to access '%s'"), fs->src);
+ return -1;
+ }
+
+ VIR_DEBUG("Resolving '%s'", fs->src);
+ if (virFileResolveAllLinks(fs->src, &newroot) < 0) {
+- VIR_DEBUG("Failed to resolve symlink at %s", fs->src);
++ virReportSystemError(errno,
++ _("Failed to resolve symlink at %s"),
++ fs->src);
+ return -1;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 44d208f8b25e5c1e4369f671fc70915c29498b76 Mon Sep 17 00:00:00 2001
+Message-Id: <44d208f8b25e5c1e4369f671fc70915c29498b76.1380112456.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 20 Sep 2013 13:07:50 +0100
+Subject: [PATCH] Ensure root filesystem is recursively mounted readonly
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=872648
+
+If the guest is configured with
+
+ <filesystem type='mount'>
+ <source dir='/'/>
+ <target dir='/'/>
+ <readonly/>
+ </filesystem>
+
+Then any submounts under / should also end up readonly, except
+for those setup as basic mounts. eg if the user has /home on a
+separate volume, they'd expect /home to be readonly, but we
+should not touch the /sys, /proc, etc dirs we setup ourselves.
+
+Users can selectively make sub-mounts read-write again by
+simply listing them as new mounts without the <readonly>
+flag set
+
+ <filesystem type='mount'>
+ <source dir='/home'/>
+ <target dir='/home'/>
+ </filesystem>
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 75235a52bc58df5ed714ff8f937220cef9ddfe26)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 86 insertions(+), 2 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index d3154d8..f851fcc 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -532,7 +532,6 @@ static int lxcContainerGetSubtree(const char *prefix,
+ }
+
+ while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+- VIR_DEBUG("Got %s", mntent.mnt_dir);
+ if (!STRPREFIX(mntent.mnt_dir, prefix))
+ continue;
+
+@@ -541,7 +540,6 @@ static int lxcContainerGetSubtree(const char *prefix,
+ if (VIR_STRDUP(mounts[nmounts], mntent.mnt_dir) < 0)
+ goto cleanup;
+ nmounts++;
+- VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
+ }
+
+ if (mounts)
+@@ -779,6 +777,74 @@ static const virLXCBasicMountInfo lxcBasicMounts[] = {
+ };
+
+
++static bool lxcIsBasicMountLocation(const char *path)
++{
++ size_t i;
++
++ for (i = 0; i < ARRAY_CARDINALITY(lxcBasicMounts); i++) {
++ if (STREQ(path, lxcBasicMounts[i].dst))
++ return true;
++ }
++
++ return false;
++}
++
++
++static int lxcContainerSetReadOnly(void)
++{
++ FILE *procmnt;
++ struct mntent mntent;
++ char mntbuf[1024];
++ int ret = -1;
++ char **mounts = NULL;
++ size_t nmounts = 0;
++ size_t i;
++
++ if (!(procmnt = setmntent("/proc/mounts", "r"))) {
++ virReportSystemError(errno, "%s",
++ _("Failed to read /proc/mounts"));
++ return -1;
++ }
++
++ while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
++ if (STREQ(mntent.mnt_dir, "/") ||
++ STREQ(mntent.mnt_dir, "/.oldroot") ||
++ STRPREFIX(mntent.mnt_dir, "/.oldroot/") ||
++ lxcIsBasicMountLocation(mntent.mnt_dir))
++ continue;
++
++ if (VIR_REALLOC_N(mounts, nmounts + 1) < 0)
++ goto cleanup;
++ if (VIR_STRDUP(mounts[nmounts], mntent.mnt_dir) < 0)
++ goto cleanup;
++ nmounts++;
++ }
++
++ if (mounts)
++ qsort(mounts, nmounts, sizeof(mounts[0]),
++ lxcContainerChildMountSort);
++
++ for (i = 0; i < nmounts; i++) {
++ VIR_DEBUG("Bind readonly %s", mounts[i]);
++ if (mount(mounts[i], mounts[i], NULL, MS_BIND|MS_REC|MS_RDONLY|MS_REMOUNT, NULL) < 0) {
++ virReportSystemError(errno,
++ _("Failed to make mount %s readonly"),
++ mounts[i]);
++ goto cleanup;
++ }
++ }
++
++ ret = 0;
++cleanup:
++ for (i = 0; i < nmounts; i++)
++ VIR_FREE(mounts[i]);
++ VIR_FREE(mounts);
++ endmntent(procmnt);
++ return ret;
++
++}
++
++
+ static int lxcContainerMountBasicFS(bool userns_enabled)
+ {
+ size_t i;
+@@ -1006,6 +1072,8 @@ static int lxcContainerMountFSBind(virDomainFSDefPtr fs,
+ int ret = -1;
+ struct stat st;
+
++ VIR_DEBUG("src=%s dst=%s", fs->src, fs->dst);
++
+ if (virAsprintf(&src, "%s%s", srcprefix, fs->src) < 0)
+ goto cleanup;
+
+@@ -1062,6 +1130,13 @@ static int lxcContainerMountFSBind(virDomainFSDefPtr fs,
+ _("Failed to make directory %s readonly"),
+ fs->dst);
+ }
++ } else {
++ VIR_DEBUG("Binding %s readwrite", fs->dst);
++ if (mount(src, fs->dst, NULL, MS_BIND|MS_REMOUNT, NULL) < 0) {
++ virReportSystemError(errno,
++ _("Failed to make directory %s readwrite"),
++ fs->dst);
++ }
+ }
+
+ ret = 0;
+@@ -1335,6 +1410,8 @@ static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
+ char *src = NULL;
+ int ret = -1;
+
++ VIR_DEBUG("src=%s dst=%s", fs->src, fs->dst);
++
+ if (virAsprintf(&src, "%s%s", srcprefix, fs->src) < 0)
+ goto cleanup;
+
+@@ -1354,6 +1431,8 @@ static int lxcContainerMountFSTmpfs(virDomainFSDefPtr fs,
+ int ret = -1;
+ char *data = NULL;
+
++ VIR_DEBUG("usage=%lld sec=%s", fs->usage, sec_mount_options);
++
+ if (virAsprintf(&data,
+ "size=%lldk%s", fs->usage, sec_mount_options) < 0)
+ goto cleanup;
+@@ -1541,6 +1620,11 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
+ if (lxcContainerMountBasicFS(vmDef->idmap.nuidmap) < 0)
+ goto cleanup;
+
++ /* Ensure entire root filesystem (except /.oldroot) is readonly */
++ if (root->readonly &&
++ lxcContainerSetReadOnly() < 0)
++ goto cleanup;
++
+ /* Mounts /proc/meminfo etc sysinfo */
+ if (lxcContainerMountProcFuse(vmDef, stateDir) < 0)
+ goto cleanup;
+--
+1.8.3.2
+
--- /dev/null
+From db465c684adb917f0751776b362ef7fd8a33b188 Mon Sep 17 00:00:00 2001
+Message-Id: <db465c684adb917f0751776b362ef7fd8a33b188.1377873638.git.jdenemar@redhat.com>
+From: Dan Walsh <dwalsh@redhat.com>
+Date: Tue, 13 Aug 2013 11:37:29 +0100
+Subject: [PATCH] Ensure securityfs is mounted readonly in container
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=872642
+
+If securityfs is available on the host, we should ensure to
+mount it read-only in the container. This will avoid systemd
+trying to mount it during startup causing SELinux AVCs.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 6807238d87fd93dee30038bea1e8582a5f0a9fe7)
+---
+ src/lxc/lxc_container.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index b910b10..a943b22 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -770,6 +770,8 @@ static int lxcContainerMountBasicFS(void)
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+ { "sysfs", "/sys", "sysfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
++ { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
++ { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+ #if WITH_SELINUX
+ { SELINUX_MOUNT, SELINUX_MOUNT, "selinuxfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+ { SELINUX_MOUNT, SELINUX_MOUNT, NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+--
+1.8.3.2
+
--- /dev/null
+From 8e0ffba00072a27a03ce78e9623a826f8e79dca2 Mon Sep 17 00:00:00 2001
+Message-Id: <8e0ffba00072a27a03ce78e9623a826f8e79dca2.1379597659.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 28 Aug 2013 15:22:05 +0100
+Subject: [PATCH] Ensure system identity includes process start time
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006272
+
+The polkit access driver will want to use the process start
+time field. This was already set for network identities, but
+not for the system identity.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit e65667c0c6e016d42abea077e31628ae43f57b74)
+---
+ src/util/viridentity.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/util/viridentity.c b/src/util/viridentity.c
+index 03c375b..f681f85 100644
+--- a/src/util/viridentity.c
++++ b/src/util/viridentity.c
+@@ -35,6 +35,7 @@
+ #include "virthread.h"
+ #include "virutil.h"
+ #include "virstring.h"
++#include "virprocess.h"
+
+ #define VIR_FROM_THIS VIR_FROM_IDENTITY
+
+@@ -142,11 +143,20 @@ virIdentityPtr virIdentityGetSystem(void)
+ security_context_t con;
+ #endif
+ char *processid = NULL;
++ unsigned long long timestamp;
++ char *processtime = NULL;
+
+ if (virAsprintf(&processid, "%llu",
+ (unsigned long long)getpid()) < 0)
+ goto cleanup;
+
++ if (virProcessGetStartTime(getpid(), ×tamp) < 0)
++ goto cleanup;
++
++ if (timestamp != 0 &&
++ virAsprintf(&processtime, "%llu", timestamp) < 0)
++ goto cleanup;
++
+ if (!(username = virGetUserName(getuid())))
+ goto cleanup;
+ if (virAsprintf(&userid, "%d", (int)getuid()) < 0)
+@@ -198,6 +208,11 @@ virIdentityPtr virIdentityGetSystem(void)
+ VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
+ processid) < 0)
+ goto error;
++ if (processtime &&
++ virIdentitySetAttr(ret,
++ VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME,
++ processtime) < 0)
++ goto error;
+
+ cleanup:
+ VIR_FREE(username);
+@@ -206,6 +221,7 @@ cleanup:
+ VIR_FREE(groupid);
+ VIR_FREE(seccontext);
+ VIR_FREE(processid);
++ VIR_FREE(processtime);
+ return ret;
+
+ error:
+--
+1.8.3.2
+
--- /dev/null
+From 30951964358bd18f92a8e43646acf9955984033b Mon Sep 17 00:00:00 2001
+Message-Id: <30951964358bd18f92a8e43646acf9955984033b.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 16:59:27 +0100
+Subject: [PATCH] Ensure that /dev exists in the container root filesystem
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=924815
+
+If booting a container with a root FS that isn't the host's
+root, we must ensure that the /dev mount point exists.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit c13a2c282b21b129ac7a519bb8c85dcba014469b)
+---
+ src/lxc/lxc_container.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index 0ab4026..8abaea0 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -868,7 +868,7 @@ static int lxcContainerMountProcFuse(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ static int lxcContainerMountFSDev(virDomainDefPtr def,
+ const char *stateDir)
+ {
+- int ret;
++ int ret = -1;
+ char *path = NULL;
+
+ VIR_DEBUG("Mount /dev/ stateDir=%s", stateDir);
+@@ -877,14 +877,24 @@ static int lxcContainerMountFSDev(virDomainDefPtr def,
+ stateDir, def->name)) < 0)
+ return ret;
+
+- VIR_DEBUG("Tring to move %s to /dev", path);
++ if (virFileMakePath("/dev") < 0) {
++ virReportSystemError(errno, "%s",
++ _("Cannot create /dev"));
++ goto cleanup;
++ }
++
++ VIR_DEBUG("Trying to move %s to /dev", path);
+
+- if ((ret = mount(path, "/dev", NULL, MS_MOVE, NULL)) < 0) {
++ if (mount(path, "/dev", NULL, MS_MOVE, NULL) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mount %s on /dev"),
+ path);
++ goto cleanup;
+ }
+
++ ret = 0;
++
++cleanup:
+ VIR_FREE(path);
+ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 355db223981592db283ff8dd4d2e198237854937 Mon Sep 17 00:00:00 2001
+Message-Id: <355db223981592db283ff8dd4d2e198237854937.1377873640.git.jdenemar@redhat.com>
+From: Martin Kletzander <mkletzan@redhat.com>
+Date: Thu, 22 Aug 2013 15:39:03 +0200
+Subject: [PATCH] Fix URI connect precedence
+
+Commit abfff210 changed the order of vshParseArgv() and vshInit() in
+order to make fix debugging of parameter parsing. However, vshInit()
+did a vshReconnect() even though ctl->name wasn't set according to the
+'-c' parameter yet. In order to keep both issues fixed, I've split
+the vshInit() into vshInitDebug() and vshInit().
+
+One simple memleak of ctl->name is fixed as a part of this patch,
+since it is related to the issue it's fixing.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=999323
+(cherry picked from commit a0b6a36f9456dae895f50d344fd2d38be1167c58)
+Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
+---
+ tools/virsh.c | 28 +++++++++++++++++-----------
+ 1 file changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/tools/virsh.c b/tools/virsh.c
+index 15f529e..2ea44a6 100644
+--- a/tools/virsh.c
++++ b/tools/virsh.c
+@@ -2294,16 +2294,13 @@ vshEventLoop(void *opaque)
+
+
+ /*
+- * Initialize connection.
++ * Initialize debug settings.
+ */
+-static bool
+-vshInit(vshControl *ctl)
++static void
++vshInitDebug(vshControl *ctl)
+ {
+ char *debugEnv;
+
+- if (ctl->conn)
+- return false;
+-
+ if (ctl->debug == VSH_DEBUG_DEFAULT) {
+ /* log level not set from commandline, check env variable */
+ debugEnv = getenv("VIRSH_DEBUG");
+@@ -2328,6 +2325,16 @@ vshInit(vshControl *ctl)
+ }
+
+ vshOpenLogFile(ctl);
++}
++
++/*
++ * Initialize connection.
++ */
++static bool
++vshInit(vshControl *ctl)
++{
++ if (ctl->conn)
++ return false;
+
+ /* set up the library error handler */
+ virSetErrorFunc(NULL, virshErrorHandler);
+@@ -3017,6 +3024,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
+ ctl->timing = true;
+ break;
+ case 'c':
++ VIR_FREE(ctl->name);
+ ctl->name = vshStrdup(ctl, optarg);
+ break;
+ case 'v':
+@@ -3192,12 +3200,10 @@ main(int argc, char **argv)
+ ctl->name = vshStrdup(ctl, defaultConn);
+ }
+
+- if (!vshInit(ctl)) {
+- vshDeinit(ctl);
+- exit(EXIT_FAILURE);
+- }
++ vshInitDebug(ctl);
+
+- if (!vshParseArgv(ctl, argc, argv)) {
++ if (!vshParseArgv(ctl, argc, argv) ||
++ !vshInit(ctl)) {
+ vshDeinit(ctl);
+ exit(EXIT_FAILURE);
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 7f49eef97945667494ba0a8127ee2290ceb7fdb8 Mon Sep 17 00:00:00 2001
+Message-Id: <7f49eef97945667494ba0a8127ee2290ceb7fdb8.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 16:40:51 +0100
+Subject: [PATCH] Fix crash in libvirtd when events are registered & ACLs
+ active (CVE-2013-4399)
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1011429
+
+When a client disconnects from libvirtd, all event callbacks
+must be removed. This involves running the public API
+
+ virConnectDomainEventDeregisterAny
+
+This code does not run in normal API dispatch context, so no
+identity was set. The result was that the access control drivers
+denied the attempt to deregister callbacks. The callbacks thus
+continued to trigger after the client was free'd causing fairly
+predictable use of free memory & a crash.
+
+This can be triggered by any client with readonly access when
+the ACL drivers are active.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 8294aa0c1750dcb49d6345cd9bd97bf421580d8b)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ daemon/remote.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index afd9fb5..1ba8ac2 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -666,8 +666,11 @@ void remoteClientFreeFunc(void *data)
+
+ /* Deregister event delivery callback */
+ if (priv->conn) {
++ virIdentityPtr sysident = virIdentityGetSystem();
+ size_t i;
+
++ virIdentitySetCurrent(sysident);
++
+ for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) {
+ if (priv->domainEventCallbackID[i] != -1) {
+ VIR_DEBUG("Deregistering to relay remote events %zu", i);
+@@ -678,6 +681,9 @@ void remoteClientFreeFunc(void *data)
+ }
+
+ virConnectClose(priv->conn);
++
++ virIdentitySetCurrent(NULL);
++ virObjectUnref(sysident);
+ }
+
+ VIR_FREE(priv);
+--
+1.8.3.2
+
--- /dev/null
+From aa873cb5be6c95c8a7ae95680759dcb0f90f57bb Mon Sep 17 00:00:00 2001
+Message-Id: <aa873cb5be6c95c8a7ae95680759dcb0f90f57bb.1380112456.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 3 Sep 2013 16:52:06 +0100
+Subject: [PATCH] Fix crash in remoteDispatchDomainMemoryStats
+
+CVE-2013-4296
+
+The 'stats' variable was not initialized to NULL, so if some
+early validation of the RPC call fails, it is possible to jump
+to the 'cleanup' label and VIR_FREE an uninitialized pointer.
+This is a security flaw, since the API can be called from a
+readonly connection which can trigger the validation checks.
+
+This was introduced in release v0.9.1 onwards by
+
+ commit 158ba8730e44b7dd07a21ab90499996c5dec080a
+ Author: Daniel P. Berrange <berrange@redhat.com>
+ Date: Wed Apr 13 16:21:35 2011 +0100
+
+ Merge all returns paths from dispatcher into single path
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit e7f400a110e2e3673b96518170bfea0855dd82c0)
+---
+ daemon/remote.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/daemon/remote.c b/daemon/remote.c
+index b5395dd..afd9fb5 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -1146,7 +1146,7 @@ remoteDispatchDomainMemoryStats(virNetServerPtr server ATTRIBUTE_UNUSED,
+ remote_domain_memory_stats_ret *ret)
+ {
+ virDomainPtr dom = NULL;
+- struct _virDomainMemoryStat *stats;
++ struct _virDomainMemoryStat *stats = NULL;
+ int nr_stats;
+ size_t i;
+ int rv = -1;
+--
+1.8.3.2
+
--- /dev/null
+From 248d2007a780bd141298cf0b330342b45f83dde8 Mon Sep 17 00:00:00 2001
+Message-Id: <248d2007a780bd141298cf0b330342b45f83dde8.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 15:20:42 +0100
+Subject: [PATCH] Fix double-free and broken logic in virt-login-shell
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=988491
+
+The virLoginShellAllowedUser method must not free the 'groups'
+parameter it is given, as that is owned by the caller.
+
+The virLoginShellAllowedUser method should be checking
+'!*ptr' (ie empty string) rather than '!ptr' (NULL string)
+since the latter cannot be true.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit ac692e3af231651304a93d63cb54049d9e3d50f8)
+---
+ tools/virt-login-shell.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+index b8f1a28..b27e44f 100644
+--- a/tools/virt-login-shell.c
++++ b/tools/virt-login-shell.c
+@@ -85,7 +85,7 @@ static int virLoginShellAllowedUser(virConfPtr conf,
+ */
+ if (pp->str[0] == '%') {
+ ptr = &pp->str[1];
+- if (!ptr)
++ if (!*ptr)
+ continue;
+ for (i = 0; groups[i]; i++) {
+ if (!(gname = virGetGroupName(groups[i])))
+@@ -96,7 +96,6 @@ static int virLoginShellAllowedUser(virConfPtr conf,
+ }
+ VIR_FREE(gname);
+ }
+- VIR_FREE(groups);
+ continue;
+ }
+ if (fnmatch(pp->str, name, 0) == 0) {
+@@ -109,7 +108,6 @@ static int virLoginShellAllowedUser(virConfPtr conf,
+ virReportSystemError(EPERM, _("%s not listed as an allowed_users in %s"), name, conf_file);
+ cleanup:
+ VIR_FREE(gname);
+- VIR_FREE(groups);
+ return ret;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 77741a2a22befeb1fb09057b502c950e4faea78a Mon Sep 17 00:00:00 2001
+Message-Id: <77741a2a22befeb1fb09057b502c950e4faea78a.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:21 +0100
+Subject: [PATCH] Fix exit status of lxc controller
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+The LXC controller main() method initialized 'rc' to 1
+rather than '-1'. In the cleanup path it will print any
+error to stderr, if-and-only-if rc < 0. Hence the incorrect
+initialization caused errors to be lost.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 13c011c3373ec4edaee188d749d032102503c9ea)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_controller.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index 5802851..e301c43 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -2230,7 +2230,7 @@ cleanup:
+ int main(int argc, char *argv[])
+ {
+ pid_t pid;
+- int rc = 1;
++ int rc = -1;
+ char *name = NULL;
+ size_t nveths = 0;
+ char **veths = NULL;
+--
+1.8.3.2
+
--- /dev/null
+From 7b932543265a2e0abd6b2a5428fe1ad40ea035ec Mon Sep 17 00:00:00 2001
+Message-Id: <7b932543265a2e0abd6b2a5428fe1ad40ea035ec.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:20 +0100
+Subject: [PATCH] Fix flaw in detecting log format
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+The log message regex has been
+
+[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+[0-9]{4}: [0-9]+: debug|info|warning|error :
+
+The precedence of '|' is high though, so this is equivalent to matching
+
+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+[0-9]{4}: [0-9]+: debug
+
+Or
+
+ info
+
+Or
+
+ warning
+
+Or
+
+ error :
+
+Which is clearly not what it should have done. This caused the code to
+skip over things which are not log messages. The solution is to simply
+add brackets.
+
+A test case is also added to validate correctness.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 5787f0b95ed5a58be020836bda4b27fa3538086c)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ .gitignore | 1 +
+ src/util/virlog.c | 5 +++-
+ tests/Makefile.am | 5 ++++
+ tests/virlogtest.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 77 insertions(+), 1 deletion(-)
+ create mode 100644 tests/virlogtest.c
+
+diff --git a/src/util/virlog.c b/src/util/virlog.c
+index 047a131..daf964b 100644
+--- a/src/util/virlog.c
++++ b/src/util/virlog.c
+@@ -83,7 +83,7 @@ static regex_t *virLogRegex = NULL;
+ #define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}"
+ #define VIR_LOG_TIME_REGEX "[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}\\+[0-9]{4}"
+ #define VIR_LOG_PID_REGEX "[0-9]+"
+-#define VIR_LOG_LEVEL_REGEX "debug|info|warning|error"
++#define VIR_LOG_LEVEL_REGEX "(debug|info|warning|error)"
+
+ #define VIR_LOG_REGEX \
+ VIR_LOG_DATE_REGEX " " VIR_LOG_TIME_REGEX ": " \
+@@ -1623,6 +1623,9 @@ virLogSetFromEnv(void)
+ {
+ char *debugEnv;
+
++ if (virLogInitialize() < 0)
++ return;
++
+ debugEnv = getenv("LIBVIRT_DEBUG");
+ if (debugEnv && *debugEnv)
+ virLogParseDefaultPriority(debugEnv);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 4787752..b794005 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -122,6 +122,7 @@ test_programs = virshtest sockettest \
+ viridentitytest \
+ virkeycodetest \
+ virlockspacetest \
++ virlogtest \
+ virstringtest \
+ virportallocatortest \
+ sysinfotest \
+@@ -643,6 +644,10 @@ virlockspacetest_SOURCES = \
+ virlockspacetest.c testutils.h testutils.c
+ virlockspacetest_LDADD = $(LDADDS)
+
++virlogtest_SOURCES = \
++ virlogtest.c testutils.h testutils.c
++virlogtest_LDADD = $(LDADDS)
++
+ virportallocatortest_SOURCES = \
+ virportallocatortest.c testutils.h testutils.c
+ virportallocatortest_LDADD = $(LDADDS)
+diff --git a/tests/virlogtest.c b/tests/virlogtest.c
+new file mode 100644
+index 0000000..ab4c2e8
+--- /dev/null
++++ b/tests/virlogtest.c
+@@ -0,0 +1,67 @@
++/*
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include <config.h>
++
++#include "testutils.h"
++
++#include "virlog.h"
++
++struct testLogMatchData {
++ const char *str;
++ bool res;
++};
++
++static int
++testLogMatch(const void *opaque)
++{
++ const struct testLogMatchData *data = opaque;
++
++ bool got = virLogProbablyLogMessage(data->str);
++ if (got != data->res) {
++ fprintf(stderr, "Expected '%d' but got '%d' for '%s'\n",
++ data->res, got, data->str);
++ return -1;
++ }
++ return 0;
++}
++
++
++static int
++mymain(void)
++{
++ int ret = 0;
++
++#define TEST_LOG_MATCH(str, res) \
++ do { \
++ struct testLogMatchData data = { \
++ str, res \
++ }; \
++ if (virtTestRun("testLogMatch " # str, 1, testLogMatch, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
++ TEST_LOG_MATCH("2013-10-11 15:43:43.866+0000: 28302: info : libvirt version: 1.1.3", true);
++
++ TEST_LOG_MATCH("libvirt: error : cannot execute binary /usr/libexec/libvirt_lxc: No such file or directory", false);
++
++ return ret;
++}
++
++VIRT_TEST_MAIN(mymain)
+--
+1.8.3.2
+
--- /dev/null
+From ac031683b0c5e27992c02a981975fec432340584 Mon Sep 17 00:00:00 2001
+Message-Id: <ac031683b0c5e27992c02a981975fec432340584.1378475168.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Tue, 3 Sep 2013 13:43:05 +0200
+Subject: [PATCH] Fix leaks in python bindings
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003828
+(cherry picked from commit 418137663f1ca0877a176b996ac027d89747fe90)
+---
+ python/libvirt-lxc-override.c | 1 +
+ python/libvirt-qemu-override.c | 3 +++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/python/libvirt-lxc-override.c b/python/libvirt-lxc-override.c
+index 73685df..03bf2df 100644
+--- a/python/libvirt-lxc-override.c
++++ b/python/libvirt-lxc-override.c
+@@ -92,6 +92,7 @@ libvirt_lxc_virDomainLxcOpenNamespace(PyObject *self ATTRIBUTE_UNUSED,
+ goto error;
+ }
+ }
++ VIR_FREE(fdlist);
+ return py_retval;
+
+ error:
+diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c
+index 8f1ce5e..6249031 100644
+--- a/python/libvirt-qemu-override.c
++++ b/python/libvirt-qemu-override.c
+@@ -21,6 +21,7 @@
+ #include <libvirt/virterror.h>
+ #include "typewrappers.h"
+ #include "libvirt-qemu.h"
++#include "viralloc.h"
+
+ #ifndef __CYGWIN__
+ extern void initlibvirtmod_qemu(void);
+@@ -79,6 +80,7 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED,
+ return VIR_PY_NONE;
+
+ py_retval = PyString_FromString(result);
++ VIR_FREE(result);
+ return py_retval;
+ }
+
+@@ -108,6 +110,7 @@ libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject
+ return VIR_PY_NONE;
+
+ py_retval = PyString_FromString(result);
++ VIR_FREE(result);
+ return py_retval;
+ }
+ /************************************************************************
+--
+1.8.3.2
+
--- /dev/null
+From e043b7231c5b4be3915b8674121b618008bad825 Mon Sep 17 00:00:00 2001
+Message-Id: <e043b7231c5b4be3915b8674121b618008bad825.1382534060.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 16 Oct 2013 23:12:55 +0800
+Subject: [PATCH] Fix max stream packet size for old clients
+
+https://bugzilla.redhat.com/show_bug.cgi?id=950416
+
+The libvirtd server pushes data out to clients. It does not
+know what protocol version the client might have, so must be
+conservative and use the old payload limits. ie send no more
+than 256kb of data per packet.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 27e81517a876dcb738dd8a9bb2e0e68d71c3b7e3)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ daemon/stream.c | 2 +-
+ src/rpc/virnetprotocol.x | 7 +++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/daemon/stream.c b/daemon/stream.c
+index 87dfaf5..9e36e8a 100644
+--- a/daemon/stream.c
++++ b/daemon/stream.c
+@@ -708,7 +708,7 @@ daemonStreamHandleRead(virNetServerClientPtr client,
+ daemonClientStream *stream)
+ {
+ char *buffer;
+- size_t bufferLen = VIR_NET_MESSAGE_PAYLOAD_MAX;
++ size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
+ int ret;
+
+ VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
+diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x
+index 131e40b..1eae7cb 100644
+--- a/src/rpc/virnetprotocol.x
++++ b/src/rpc/virnetprotocol.x
+@@ -50,6 +50,13 @@
+ */
+ const VIR_NET_MESSAGE_INITIAL = 65536;
+
++/*
++ * Until we enlarged the message buffers, this was the max
++ * payload size. We need to remember this for compat with
++ * old clients.
++ */
++const VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX = 262144;
++
+ /* Maximum total message size (serialised). */
+ const VIR_NET_MESSAGE_MAX = 16777216;
+
+--
+1.8.4
+
--- /dev/null
+From 79615330836ae08cf6ed3773e2eaab7c3fa0cd31 Mon Sep 17 00:00:00 2001
+Message-Id: <79615330836ae08cf6ed3773e2eaab7c3fa0cd31.1379193140.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 12 Sep 2013 17:34:46 +0100
+Subject: [PATCH] Fix naming of permission for detecting storage pools
+
+https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+The VIR_ACCESS_PERM_CONNECT_DETECT_STORAGE_POOLS enum
+constant had its string format be 'detect_storage_pool',
+note the missing trailing 's'. This prevent the ACL
+check from ever succeeding. Fix this and add a simple
+test script to validate this problem of matching names.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 935e7d02cfd6f5cca04f548d91a04f5f08fa4bcf)
+---
+ src/Makefile.am | 8 ++++-
+ src/access/viraccessperm.c | 2 +-
+ src/check-aclperms.pl | 73 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 81 insertions(+), 2 deletions(-)
+ create mode 100755 src/check-aclperms.pl
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 1b734e0..66bb6b9 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -508,10 +508,16 @@ check-aclrules:
+ $(REMOTE_PROTOCOL) \
+ $(addprefix $(srcdir)/,$(filter-out /%,$(STATEFUL_DRIVER_SOURCE_FILES)))
+
++check-aclperms:
++ $(AM_V_GEN)$(PERL) $(srcdir)/check-aclperms.pl \
++ $(srcdir)/access/viraccessperm.h \
++ $(srcdir)/access/viraccessperm.c
++
+ EXTRA_DIST += check-driverimpls.pl check-aclrules.pl
+
+ check-local: check-protocol check-symfile check-symsorting \
+- check-drivername check-driverimpls check-aclrules
++ check-drivername check-driverimpls check-aclrules \
++ check-aclperms
+ .PHONY: check-protocol $(PROTOCOL_STRUCTS:structs=struct)
+
+ # Mock driver, covering domains, storage, networks, etc
+diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
+index 9c720f9..d517c66 100644
+--- a/src/access/viraccessperm.c
++++ b/src/access/viraccessperm.c
+@@ -30,7 +30,7 @@ VIR_ENUM_IMPL(virAccessPermConnect,
+ "search_storage_pools", "search_node_devices",
+ "search_interfaces", "search_secrets",
+ "search_nwfilters",
+- "detect_storage_pool", "pm_control",
++ "detect_storage_pools", "pm_control",
+ "interface_transaction");
+
+ VIR_ENUM_IMPL(virAccessPermDomain,
+diff --git a/src/check-aclperms.pl b/src/check-aclperms.pl
+new file mode 100755
+index 0000000..5b1b4db
+--- /dev/null
++++ b/src/check-aclperms.pl
+@@ -0,0 +1,73 @@
++#!/usr/bin/perl
++#
++# Copyright (C) 2013 Red Hat, Inc.
++#
++# This library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++#
++# This library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with this library. If not, see
++# <http://www.gnu.org/licenses/>.
++#
++# This script just validates that the stringified version of
++# a virAccessPerm enum matches the enum constant name. We do
++# a lot of auto-generation of code, so when these don't match
++# problems occur, preventing auth from succeeding at all.
++
++my $hdr = shift;
++my $impl = shift;
++
++my %perms;
++
++my @perms;
++
++open HDR, $hdr or die "cannot read $hdr: $!";
++
++while (<HDR>) {
++ if (/^\s+VIR_ACCESS_PERM_([_A-Z]+)(,?|\s|$)/) {
++ my $perm = $1;
++
++ $perms{$perm} = 1 unless ($perm =~ /_LAST$/);
++ }
++}
++
++close HDR;
++
++
++open IMPL, $impl or die "cannot read $impl: $!";
++
++my $group;
++my $warned = 0;
++
++while (defined (my $line = <IMPL>)) {
++ if ($line =~ /VIR_ACCESS_PERM_([_A-Z]+)_LAST/) {
++ $group = $1;
++ } elsif ($line =~ /"[_a-z]+"/) {
++ my @bits = split /,/, $line;
++ foreach my $bit (@bits) {
++ if ($bit =~ /"([_a-z]+)"/) {
++ my $perm = uc($group . "_" . $1);
++ if (!exists $perms{$perm}) {
++ print STDERR "Unknown perm string $1 for group $group\n";
++ $warned = 1;
++ }
++ delete $perms{$perm};
++ }
++ }
++ }
++}
++close IMPL;
++
++foreach my $perm (keys %perms) {
++ print STDERR "Perm $perm had not string form\n";
++ $warned = 1;
++}
++
++exit $warned;
+--
+1.8.3.2
+
--- /dev/null
+From 948fae5a1104dbfe93d060e447920fb65fb5c8a5 Mon Sep 17 00:00:00 2001
+Message-Id: <948fae5a1104dbfe93d060e447920fb65fb5c8a5.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:49 +0100
+Subject: [PATCH] Fix parallel runs of TLS test suites
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+Use a separate keyfile name for the two TLS test suites so that
+they don't clash when running tests in parallel
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit eaa99a17dbad06d973f335a632fd47605556096c)
+---
+ tests/virnettlscontexttest.c | 10 ++++++----
+ tests/virnettlshelpers.c | 6 ++----
+ tests/virnettlshelpers.h | 6 ++----
+ tests/virnettlssessiontest.c | 10 ++++++----
+ 4 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 9ade785..53792ee 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -40,6 +40,8 @@
+
+ # define VIR_FROM_THIS VIR_FROM_RPC
+
++# define KEYFILE "key-ctx.pem"
++
+ struct testTLSContextData {
+ bool isServer;
+ const char *cacrt;
+@@ -66,7 +68,7 @@ static int testTLSContextInit(const void *opaque)
+ ctxt = virNetTLSContextNewServer(data->cacrt,
+ NULL,
+ data->crt,
+- keyfile,
++ KEYFILE,
+ NULL,
+ true,
+ true);
+@@ -74,7 +76,7 @@ static int testTLSContextInit(const void *opaque)
+ ctxt = virNetTLSContextNewClient(data->cacrt,
+ NULL,
+ data->crt,
+- keyfile,
++ KEYFILE,
+ true,
+ true);
+ }
+@@ -109,7 +111,7 @@ mymain(void)
+ {
+ int ret = 0;
+
+- testTLSInit();
++ testTLSInit(KEYFILE);
+
+ # define DO_CTX_TEST(_isServer, _caCrt, _crt, _expectFail) \
+ do { \
+@@ -617,7 +619,7 @@ mymain(void)
+ testTLSDiscardCert(&clientcertlevel2breq);
+ unlink("cacertchain.pem");
+
+- testTLSCleanup();
++ testTLSCleanup(KEYFILE);
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+diff --git a/tests/virnettlshelpers.c b/tests/virnettlshelpers.c
+index 39a2df6..8a10340 100644
+--- a/tests/virnettlshelpers.c
++++ b/tests/virnettlshelpers.c
+@@ -34,8 +34,6 @@
+
+ # define VIR_FROM_THIS VIR_FROM_RPC
+
+-const char *keyfile = abs_builddir "/virnettlscontexttest-key.pem";
+-
+ /*
+ * These store some static data that is needed when
+ * encoding extensions in the x509 certs
+@@ -99,7 +97,7 @@ static gnutls_x509_privkey_t testTLSLoadKey(void)
+ }
+
+
+-void testTLSInit(void)
++void testTLSInit(const char *keyfile)
+ {
+ gnutls_global_init();
+
+@@ -112,7 +110,7 @@ void testTLSInit(void)
+ }
+
+
+-void testTLSCleanup(void)
++void testTLSCleanup(const char *keyfile)
+ {
+ asn1_delete_structure(&pkix_asn1);
+ unlink(keyfile);
+diff --git a/tests/virnettlshelpers.h b/tests/virnettlshelpers.h
+index 7c3f8da..3f6afb9 100644
+--- a/tests/virnettlshelpers.h
++++ b/tests/virnettlshelpers.h
+@@ -28,8 +28,6 @@
+
+ # include "rpc/virnettlscontext.h"
+
+-extern const char *keyfile;
+-
+ /*
+ * This contains parameter about how to generate
+ * certificates.
+@@ -76,7 +74,7 @@ void testTLSWriteCertChain(const char *filename,
+ size_t ncerts);
+ void testTLSDiscardCert(struct testTLSCertReq *req);
+
+-void testTLSInit(void);
+-void testTLSCleanup(void);
++void testTLSInit(const char *keyfile);
++void testTLSCleanup(const char *keyfile);
+
+ #endif
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+index bc176aa..9b171ed 100644
+--- a/tests/virnettlssessiontest.c
++++ b/tests/virnettlssessiontest.c
+@@ -38,6 +38,8 @@
+
+ # define VIR_FROM_THIS VIR_FROM_RPC
+
++# define KEYFILE "key-sess.pem"
++
+ struct testTLSSessionData {
+ const char *servercacrt;
+ const char *clientcacrt;
+@@ -107,7 +109,7 @@ static int testTLSSessionInit(const void *opaque)
+ serverCtxt = virNetTLSContextNewServer(data->servercacrt,
+ NULL,
+ data->servercrt,
+- keyfile,
++ KEYFILE,
+ data->wildcards,
+ false,
+ true);
+@@ -115,7 +117,7 @@ static int testTLSSessionInit(const void *opaque)
+ clientCtxt = virNetTLSContextNewClient(data->clientcacrt,
+ NULL,
+ data->clientcrt,
+- keyfile,
++ KEYFILE,
+ false,
+ true);
+
+@@ -236,7 +238,7 @@ mymain(void)
+ {
+ int ret = 0;
+
+- testTLSInit();
++ testTLSInit(KEYFILE);
+
+ # define DO_SESS_TEST(_caCrt, _serverCrt, _clientCrt, _expectServerFail, \
+ _expectClientFail, _hostname, _wildcards) \
+@@ -474,7 +476,7 @@ mymain(void)
+ testTLSDiscardCert(&clientcertlevel2breq);
+ unlink("cacertchain.pem");
+
+- testTLSCleanup();
++ testTLSCleanup(KEYFILE);
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From ae5cbaaba2cf9419004cc9972f18c4ad4e555ba8 Mon Sep 17 00:00:00 2001
+Message-Id: <ae5cbaaba2cf9419004cc9972f18c4ad4e555ba8.1382534062.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 22 Oct 2013 17:18:07 +0100
+Subject: [PATCH] Fix perms for virConnectDomainXML{To, From}Native
+
+CVE-2013-4401
+
+The virConnectDomainXMLToNative API should require 'connect:write'
+not 'connect:read', since it will trigger execution of the QEMU
+binaries listed in the XML.
+
+Also make virConnectDomainXMLFromNative API require a full
+read-write connection and 'connect:write' permission. Although the
+current impl doesn't trigger execution of QEMU, we should not
+rely on that impl detail from an API permissioning POV.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 57687fd6bf7f6e1b3662c52f3f26c06ab19dc96c)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt.c | 4 ++++
+ src/remote/remote_protocol.x | 4 ++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 66e8248..1a6c771 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -4606,6 +4606,10 @@ char *virConnectDomainXMLFromNative(virConnectPtr conn,
+ virDispatchError(NULL);
+ return NULL;
+ }
++ if (conn->flags & VIR_CONNECT_RO) {
++ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
++ goto error;
++ }
+
+ virCheckNonNullArgGoto(nativeFormat, error);
+ virCheckNonNullArgGoto(nativeConfig, error);
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index a8450b1..c7181da 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -3812,13 +3812,13 @@ enum remote_procedure {
+
+ /**
+ * @generate: both
+- * @acl: connect:read
++ * @acl: connect:write
+ */
+ REMOTE_PROC_CONNECT_DOMAIN_XML_FROM_NATIVE = 135,
+
+ /**
+ * @generate: both
+- * @acl: connect:read
++ * @acl: connect:write
+ */
+ REMOTE_PROC_CONNECT_DOMAIN_XML_TO_NATIVE = 136,
+
+--
+1.8.4
+
--- /dev/null
+From 151a0e8c4ce50a8096b1d1cc46277a9831d30b1a Mon Sep 17 00:00:00 2001
+Message-Id: <151a0e8c4ce50a8096b1d1cc46277a9831d30b1a.1379193140.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 12 Sep 2013 17:34:45 +0100
+Subject: [PATCH] Fix polkit permission names for storage pools, vols & node
+ devices
+
+https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+The polkit access driver used the wrong permission names for checks
+on storage pools, volumes and node devices. This led to them always
+being denied access.
+
+The 'dettach' permission was also mis-spelt and should have been
+'detach'. While permission names are ABI sensitive, the fact that
+the code used the wrong object name for checking node device
+permissions, means that no one could have used the mis-spelt
+'dettach' permission.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 621849383ad1aad61fe630184e689f5aca6ab7e0)
+---
+ src/access/viraccessdriverpolkit.c | 6 +++---
+ src/access/viraccessperm.c | 2 +-
+ src/access/viraccessperm.h | 2 +-
+ src/remote/remote_protocol.x | 8 ++++----
+ 4 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c
+index 4c76e64..b472bc3 100644
+--- a/src/access/viraccessdriverpolkit.c
++++ b/src/access/viraccessdriverpolkit.c
+@@ -248,7 +248,7 @@ virAccessDriverPolkitCheckNodeDevice(virAccessManagerPtr manager,
+ };
+
+ return virAccessDriverPolkitCheck(manager,
+- "nodedevice",
++ "node-device",
+ virAccessPermNodeDeviceTypeToString(perm),
+ attrs);
+ }
+@@ -355,7 +355,7 @@ virAccessDriverPolkitCheckStoragePool(virAccessManagerPtr manager,
+ virUUIDFormat(pool->uuid, uuidstr);
+
+ return virAccessDriverPolkitCheck(manager,
+- "pool",
++ "storage-pool",
+ virAccessPermStoragePoolTypeToString(perm),
+ attrs);
+ }
+@@ -379,7 +379,7 @@ virAccessDriverPolkitCheckStorageVol(virAccessManagerPtr manager,
+ virUUIDFormat(pool->uuid, uuidstr);
+
+ return virAccessDriverPolkitCheck(manager,
+- "vol",
++ "storage-vol",
+ virAccessPermStorageVolTypeToString(perm),
+ attrs);
+ }
+diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
+index 17f6243..9c720f9 100644
+--- a/src/access/viraccessperm.c
++++ b/src/access/viraccessperm.c
+@@ -58,7 +58,7 @@ VIR_ENUM_IMPL(virAccessPermNodeDevice,
+ VIR_ACCESS_PERM_NODE_DEVICE_LAST,
+ "getattr", "read", "write",
+ "start", "stop",
+- "dettach");
++ "detach");
+
+ VIR_ENUM_IMPL(virAccessPermNWFilter,
+ VIR_ACCESS_PERM_NWFILTER_LAST,
+diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h
+index 2f76c95..fdc461b 100644
+--- a/src/access/viraccessperm.h
++++ b/src/access/viraccessperm.h
+@@ -427,7 +427,7 @@ typedef enum {
+ * @desc: Detach node device
+ * @message: Detaching node device driver requires authorization
+ */
+- VIR_ACCESS_PERM_NODE_DEVICE_DETTACH,
++ VIR_ACCESS_PERM_NODE_DEVICE_DETACH,
+
+ VIR_ACCESS_PERM_NODE_DEVICE_LAST
+ } virAccessPermNodeDevice;
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index a1c23da..85ad9ba 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -3696,19 +3696,19 @@ enum remote_procedure {
+
+ /**
+ * @generate: server
+- * @acl: node_device:dettach
++ * @acl: node_device:detach
+ */
+ REMOTE_PROC_NODE_DEVICE_DETTACH = 118,
+
+ /**
+ * @generate: server
+- * @acl: node_device:dettach
++ * @acl: node_device:detach
+ */
+ REMOTE_PROC_NODE_DEVICE_RE_ATTACH = 119,
+
+ /**
+ * @generate: server
+- * @acl: node_device:dettach
++ * @acl: node_device:detach
+ */
+ REMOTE_PROC_NODE_DEVICE_RESET = 120,
+
+@@ -4929,7 +4929,7 @@ enum remote_procedure {
+
+ /**
+ * @generate: server
+- * @acl: node_device:dettach
++ * @acl: node_device:detach
+ */
+ REMOTE_PROC_NODE_DEVICE_DETACH_FLAGS = 301,
+
+--
+1.8.3.2
+
--- /dev/null
+From ea5c964f4a939017a3b4fd072b735df3994d7e1f Mon Sep 17 00:00:00 2001
+Message-Id: <ea5c964f4a939017a3b4fd072b735df3994d7e1f.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <dan@berrange.com>
+Date: Fri, 30 Aug 2013 11:13:43 +0100
+Subject: [PATCH] Fix typo in domain name in polkit acl example
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+Signed-off-by: Daniel P. Berrange <dan@berrange.com>
+(cherry picked from commit b6c7e3bb52bc9ab57335c72ad079eb8b7d89a0e3)
+---
+ docs/aclpolkit.html.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/docs/aclpolkit.html.in b/docs/aclpolkit.html.in
+index 3b0d81a..3f0689e 100644
+--- a/docs/aclpolkit.html.in
++++ b/docs/aclpolkit.html.in
+@@ -398,7 +398,7 @@ polkit.addRule(function(action, subject) {
+ if (action.id == "org.libvirt.api.domain.getattr" &&
+ subject.user == "berrange") {
+ if (action._detail_connect_driver == 'LXC' &&
+- action._detail_domain_name == 'busy') {
++ action._detail_domain_name == 'demo') {
+ return polkit.Result.YES;
+ } else {
+ return polkit.Result.NO;
+--
+1.8.3.2
+
--- /dev/null
+From 141a54556cb19004ab72780417d315bfebbd872d Mon Sep 17 00:00:00 2001
+Message-Id: <141a54556cb19004ab72780417d315bfebbd872d.1380112457.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 23 Sep 2013 15:26:07 -0600
+Subject: [PATCH] Fix typo in identity code which is pre-requisite for
+ CVE-2013-4311
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006272
+
+The fix for CVE-2013-4311 had a pre-requisite enhancement
+to the identity code
+
+ commit db7a5688c05f3fd60d9d2b74c72427eb9ee9c176
+ Author: Daniel P. Berrange <berrange@redhat.com>
+ Date: Thu Aug 22 16:00:01 2013 +0100
+
+ Also store user & group ID values in virIdentity
+
+This had a typo which caused the group ID to overwrite the
+user ID string. This meant any checks using this would have
+the wrong ID value. This only affected the ACL code, not the
+initial polkit auth. It also leaked memory.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit e4697b92abaad16e8e6b41a1e55be9b084d48d5a)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/rpc/virnetserverclient.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
+index 19c4100..0b9ab52 100644
+--- a/src/rpc/virnetserverclient.c
++++ b/src/rpc/virnetserverclient.c
+@@ -678,7 +678,7 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
+ goto cleanup;
+ if (!(groupname = virGetGroupName(gid)))
+ goto cleanup;
+- if (virAsprintf(&userid, "%d", (int)gid) < 0)
++ if (virAsprintf(&groupid, "%d", (int)gid) < 0)
+ goto cleanup;
+ if (virAsprintf(&processid, "%llu",
+ (unsigned long long)pid) < 0)
+--
+1.8.3.2
+
--- /dev/null
+From efc84d335fa6ec218e7ad4c942300b3e5bd27bc8 Mon Sep 17 00:00:00 2001
+Message-Id: <efc84d335fa6ec218e7ad4c942300b3e5bd27bc8.1377873637.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:48 +0100
+Subject: [PATCH] Fix validation of CA certificate chains
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+The code added to validate CA certificates did not take into
+account the possibility that the cacert.pem file can contain
+multiple (concatenated) cert data blocks. Extend the code for
+loading CA certs to use the gnutls APIs for loading cert lists.
+Add test cases to check that multi-level trees of certs will
+validate correctly.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 31d41d9268a6731e303700b5a5825a87a6f36a19)
+---
+ src/rpc/virnettlscontext.c | 70 ++++++++++++++++++++++++++++++++++----------
+ tests/virnettlscontexttest.c | 59 +++++++++++++++++++++++++++++++++++++
+ tests/virnettlshelpers.c | 34 +++++++++++++++++++++
+ tests/virnettlshelpers.h | 3 ++
+ tests/virnettlssessiontest.c | 63 +++++++++++++++++++++++++++++++++++++--
+ 5 files changed, 211 insertions(+), 18 deletions(-)
+
+diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
+index af0ec21..2beee8f 100644
+--- a/src/rpc/virnettlscontext.c
++++ b/src/rpc/virnettlscontext.c
+@@ -455,14 +455,15 @@ static int virNetTLSContextCheckCert(gnutls_x509_crt_t cert,
+
+ static int virNetTLSContextCheckCertPair(gnutls_x509_crt_t cert,
+ const char *certFile,
+- gnutls_x509_crt_t cacert,
++ gnutls_x509_crt_t *cacerts,
++ size_t ncacerts,
+ const char *cacertFile,
+ bool isServer)
+ {
+ unsigned int status;
+
+ if (gnutls_x509_crt_list_verify(&cert, 1,
+- &cacert, 1,
++ cacerts, ncacerts,
+ NULL, 0,
+ 0, &status) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, isServer ?
+@@ -500,16 +501,15 @@ static int virNetTLSContextCheckCertPair(gnutls_x509_crt_t cert,
+
+
+ static gnutls_x509_crt_t virNetTLSContextLoadCertFromFile(const char *certFile,
+- bool isServer,
+- bool isCA ATTRIBUTE_UNUSED)
++ bool isServer)
+ {
+ gnutls_datum_t data;
+ gnutls_x509_crt_t cert = NULL;
+ char *buf = NULL;
+ int ret = -1;
+
+- VIR_DEBUG("isServer %d isCA %d certFile %s",
+- isServer, isCA, certFile);
++ VIR_DEBUG("isServer %d certFile %s",
++ isServer, certFile);
+
+ if (gnutls_x509_crt_init(&cert) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+@@ -543,31 +543,69 @@ cleanup:
+ }
+
+
++static int virNetTLSContextLoadCACertListFromFile(const char *certFile,
++ gnutls_x509_crt_t *certs,
++ size_t *ncerts)
++{
++ gnutls_datum_t data;
++ char *buf = NULL;
++ int ret = -1;
++ unsigned int certMax = *ncerts;
++
++ *ncerts = 0;
++ VIR_DEBUG("certFile %s", certFile);
++
++ if (virFileReadAll(certFile, (1<<16), &buf) < 0)
++ goto cleanup;
++
++ data.data = (unsigned char *)buf;
++ data.size = strlen(buf);
++
++ if (gnutls_x509_crt_list_import(certs, &certMax, &data, GNUTLS_X509_FMT_PEM, 0) < 0) {
++ virReportError(VIR_ERR_SYSTEM_ERROR,
++ _("Unable to import CA certificate list %s"),
++ certFile);
++ goto cleanup;
++ }
++ *ncerts = certMax;
++
++ ret = 0;
++
++cleanup:
++ VIR_FREE(buf);
++ return ret;
++}
++
++
++#define MAX_CERTS 16
+ static int virNetTLSContextSanityCheckCredentials(bool isServer,
+ const char *cacertFile,
+ const char *certFile)
+ {
+ gnutls_x509_crt_t cert = NULL;
+- gnutls_x509_crt_t cacert = NULL;
++ gnutls_x509_crt_t cacerts[MAX_CERTS];
++ size_t ncacerts = MAX_CERTS;
++ size_t i;
+ int ret = -1;
+
+ if ((access(certFile, R_OK) == 0) &&
+- !(cert = virNetTLSContextLoadCertFromFile(certFile, isServer, false)))
++ !(cert = virNetTLSContextLoadCertFromFile(certFile, isServer)))
+ goto cleanup;
+ if ((access(cacertFile, R_OK) == 0) &&
+- !(cacert = virNetTLSContextLoadCertFromFile(cacertFile, isServer, false)))
++ virNetTLSContextLoadCACertListFromFile(cacertFile, cacerts, &ncacerts) < 0)
+ goto cleanup;
+
+ if (cert &&
+ virNetTLSContextCheckCert(cert, certFile, isServer, false) < 0)
+ goto cleanup;
+
+- if (cacert &&
+- virNetTLSContextCheckCert(cacert, cacertFile, isServer, true) < 0)
+- goto cleanup;
++ for (i = 0; i < ncacerts; i++) {
++ if (virNetTLSContextCheckCert(cacerts[i], cacertFile, isServer, true) < 0)
++ goto cleanup;
++ }
+
+- if (cert && cacert &&
+- virNetTLSContextCheckCertPair(cert, certFile, cacert, cacertFile, isServer) < 0)
++ if (cert && ncacerts &&
++ virNetTLSContextCheckCertPair(cert, certFile, cacerts, ncacerts, cacertFile, isServer) < 0)
+ goto cleanup;
+
+ ret = 0;
+@@ -575,8 +613,8 @@ static int virNetTLSContextSanityCheckCredentials(bool isServer,
+ cleanup:
+ if (cert)
+ gnutls_x509_crt_deinit(cert);
+- if (cacert)
+- gnutls_x509_crt_deinit(cacert);
++ for (i = 0; i < ncacerts; i++)
++ gnutls_x509_crt_deinit(cacerts[i]);
+ return ret;
+ }
+
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 3012c4a..9ade785 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -510,6 +510,57 @@ mymain(void)
+ DO_CTX_TEST(true, cacertreq.filename, servercertnew1req.filename, true);
+ DO_CTX_TEST(false, cacertreq.filename, clientcertnew1req.filename, true);
+
++ TLS_ROOT_REQ(cacertrootreq,
++ "UK", "libvirt root", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
++ "UK", "libvirt level 1a", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
++ "UK", "libvirt level 1b", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
++ "UK", "libvirt level 2a", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
++ "UK", "libvirt client level 2b", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
++
++ gnutls_x509_crt_t certchain[] = {
++ cacertrootreq.crt,
++ cacertlevel1areq.crt,
++ cacertlevel1breq.crt,
++ cacertlevel2areq.crt,
++ };
++
++ testTLSWriteCertChain("cacertchain.pem",
++ certchain,
++ ARRAY_CARDINALITY(certchain));
++
++ DO_CTX_TEST(true, "cacertchain.pem", servercertlevel3areq.filename, false);
++ DO_CTX_TEST(false, "cacertchain.pem", clientcertlevel2breq.filename, false);
++
+ testTLSDiscardCert(&cacertreq);
+ testTLSDiscardCert(&cacert1req);
+ testTLSDiscardCert(&cacert2req);
+@@ -558,6 +609,14 @@ mymain(void)
+ testTLSDiscardCert(&servercertnew1req);
+ testTLSDiscardCert(&clientcertnew1req);
+
++ testTLSDiscardCert(&cacertrootreq);
++ testTLSDiscardCert(&cacertlevel1areq);
++ testTLSDiscardCert(&cacertlevel1breq);
++ testTLSDiscardCert(&cacertlevel2areq);
++ testTLSDiscardCert(&servercertlevel3areq);
++ testTLSDiscardCert(&clientcertlevel2breq);
++ unlink("cacertchain.pem");
++
+ testTLSCleanup();
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+diff --git a/tests/virnettlshelpers.c b/tests/virnettlshelpers.c
+index 8236e82..39a2df6 100644
+--- a/tests/virnettlshelpers.c
++++ b/tests/virnettlshelpers.c
+@@ -406,6 +406,40 @@ testTLSGenerateCert(struct testTLSCertReq *req,
+ }
+
+
++void testTLSWriteCertChain(const char *filename,
++ gnutls_x509_crt_t *certs,
++ size_t ncerts)
++{
++ size_t i;
++ int fd;
++ int err;
++ static char buffer[1024*1024];
++ size_t size;
++
++ if ((fd = open(filename, O_WRONLY|O_CREAT, 0600)) < 0) {
++ VIR_WARN("Failed to open %s", filename);
++ abort();
++ }
++
++ for (i = 0; i < ncerts; i++) {
++ size = sizeof(buffer);
++ if ((err = gnutls_x509_crt_export(certs[i], GNUTLS_X509_FMT_PEM, buffer, &size) < 0)) {
++ VIR_WARN("Failed to export certificate %s", gnutls_strerror(err));
++ unlink(filename);
++ abort();
++ }
++
++ if (safewrite(fd, buffer, size) != size) {
++ VIR_WARN("Failed to write certificate to %s", filename);
++ unlink(filename);
++ abort();
++ }
++ }
++
++ VIR_FORCE_CLOSE(fd);
++}
++
++
+ void testTLSDiscardCert(struct testTLSCertReq *req)
+ {
+ if (!req->crt)
+diff --git a/tests/virnettlshelpers.h b/tests/virnettlshelpers.h
+index 50a4ba1..7c3f8da 100644
+--- a/tests/virnettlshelpers.h
++++ b/tests/virnettlshelpers.h
+@@ -71,6 +71,9 @@ struct testTLSCertReq {
+
+ void testTLSGenerateCert(struct testTLSCertReq *req,
+ gnutls_x509_crt_t ca);
++void testTLSWriteCertChain(const char *filename,
++ gnutls_x509_crt_t *certs,
++ size_t ncerts);
+ void testTLSDiscardCert(struct testTLSCertReq *req);
+
+ void testTLSInit(void);
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+index 8636fc8..bc176aa 100644
+--- a/tests/virnettlssessiontest.c
++++ b/tests/virnettlssessiontest.c
+@@ -193,7 +193,7 @@ static int testTLSSessionInit(const void *opaque)
+ VIR_WARN("Expected server cert check fail");
+ goto cleanup;
+ } else {
+- VIR_DEBUG("Not unexpected server cert fail");
++ VIR_DEBUG("No unexpected server cert fail");
+ }
+ }
+
+@@ -213,7 +213,7 @@ static int testTLSSessionInit(const void *opaque)
+ VIR_WARN("Expected client cert check fail");
+ goto cleanup;
+ } else {
+- VIR_DEBUG("Not unexpected client cert fail");
++ VIR_DEBUG("No unexpected client cert fail");
+ }
+ }
+
+@@ -405,6 +405,57 @@ mymain(void)
+ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename,
+ false, false, "libvirt.org", wildcards6);
+
++ TLS_ROOT_REQ(cacertrootreq,
++ "UK", "libvirt root", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
++ "UK", "libvirt level 1a", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
++ "UK", "libvirt level 1b", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
++ "UK", "libvirt level 2a", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0);
++ TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
++ "UK", "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0);
++ TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
++ "UK", "libvirt client level 2b", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0);
++
++ gnutls_x509_crt_t certchain[] = {
++ cacertrootreq.crt,
++ cacertlevel1areq.crt,
++ cacertlevel1breq.crt,
++ cacertlevel2areq.crt,
++ };
++
++ testTLSWriteCertChain("cacertchain.pem",
++ certchain,
++ ARRAY_CARDINALITY(certchain));
++
++ DO_SESS_TEST("cacertchain.pem", servercertlevel3areq.filename, clientcertlevel2breq.filename,
++ false, false, "libvirt.org", NULL);
++
+ testTLSDiscardCert(&clientcertreq);
+ testTLSDiscardCert(&clientcertaltreq);
+
+@@ -415,6 +466,14 @@ mymain(void)
+ testTLSDiscardCert(&cacertreq);
+ testTLSDiscardCert(&altcacertreq);
+
++ testTLSDiscardCert(&cacertrootreq);
++ testTLSDiscardCert(&cacertlevel1areq);
++ testTLSDiscardCert(&cacertlevel1breq);
++ testTLSDiscardCert(&cacertlevel2areq);
++ testTLSDiscardCert(&servercertlevel3areq);
++ testTLSDiscardCert(&clientcertlevel2breq);
++ unlink("cacertchain.pem");
++
+ testTLSCleanup();
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+--
+1.8.3.2
+
--- /dev/null
+From 12fa7634a0d5026efef950a7b5583260bd9d316c Mon Sep 17 00:00:00 2001
+Message-Id: <12fa7634a0d5026efef950a7b5583260bd9d316c.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:15 +0100
+Subject: [PATCH] Fix virsystemdtest for previous commit
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+The change to query org.freedesktop.DBus.ListActivatableNames
+to detect systemd broke the test suite, since we did not have
+stubs to respond to this dbus call.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 468f684e84a6f2dedc60f2a8ed13ba9fbd3df459)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/virsystemdmock.c | 54 +++++++++++++++++++++++++++++++++-----------------
+ tests/virsystemdtest.c | 4 ++++
+ 2 files changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/tests/virsystemdmock.c b/tests/virsystemdmock.c
+index 5dbd33f..59b312d 100644
+--- a/tests/virsystemdmock.c
++++ b/tests/virsystemdmock.c
+@@ -65,29 +65,47 @@ dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message ATTRIBUTE_UNUSED,
+ }
+
+ DBusMessage *dbus_connection_send_with_reply_and_block(DBusConnection *connection ATTRIBUTE_UNUSED,
+- DBusMessage *message ATTRIBUTE_UNUSED,
++ DBusMessage *message,
+ int timeout_milliseconds ATTRIBUTE_UNUSED,
+- DBusError *error)
++ DBusError *error ATTRIBUTE_UNUSED)
+ {
+ DBusMessage *reply = NULL;
++ const char *service = dbus_message_get_destination(message);
+
+- if (getenv("FAIL_BAD_SERVICE")) {
+- DBusMessageIter iter;
+- const char *error_message = "Something went wrong creating the machine";
+- if (!(reply = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR)))
+- return NULL;
+- dbus_message_set_error_name(reply, "org.freedesktop.systemd.badthing");
+- dbus_message_iter_init_append(reply, &iter);
+- if (!dbus_message_iter_append_basic(&iter,
+- DBUS_TYPE_STRING,
+- &error_message)) {
+- dbus_message_unref(reply);
+- return NULL;
++ if (STREQ(service, "org.freedesktop.machine1")) {
++ if (getenv("FAIL_BAD_SERVICE")) {
++ DBusMessageIter iter;
++ const char *error_message = "Something went wrong creating the machine";
++ if (!(reply = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR)))
++ return NULL;
++ dbus_message_set_error_name(reply, "org.freedesktop.systemd.badthing");
++ dbus_message_iter_init_append(reply, &iter);
++ if (!dbus_message_iter_append_basic(&iter,
++ DBUS_TYPE_STRING,
++ &error_message)) {
++ dbus_message_unref(reply);
++ return NULL;
++ }
++ } else {
++ reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
+ }
+- } else if (getenv("FAIL_NO_SERVICE")) {
+- dbus_set_error(error,
+- "org.freedesktop.DBus.Error.ServiceUnknown",
+- "%s", "The name org.freedesktop.machine1 was not provided by any .service files");
++ } else if (STREQ(service, "org.freedesktop.DBus")) {
++ const char *svc1 = "org.foo.bar.wizz";
++ const char *svc2 = "org.freedesktop.machine1";
++ DBusMessageIter iter, sub;
++ reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
++ dbus_message_iter_init_append(reply, &iter);
++ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
++ "s", &sub);
++
++ dbus_message_iter_append_basic(&sub,
++ DBUS_TYPE_STRING,
++ &svc1);
++ if (!getenv("FAIL_NO_SERVICE"))
++ dbus_message_iter_append_basic(&sub,
++ DBUS_TYPE_STRING,
++ &svc2);
++ dbus_message_iter_close_container(&iter, &sub);
+ } else {
+ reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
+ }
+diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c
+index a9c6d32..7dc7520 100644
+--- a/tests/virsystemdtest.c
++++ b/tests/virsystemdtest.c
+@@ -94,9 +94,11 @@ static int testCreateNoSystemd(const void *opaque ATTRIBUTE_UNUSED)
+ 123,
+ false,
+ NULL)) == 0) {
++ unsetenv("FAIL_NO_SERVICE");
+ fprintf(stderr, "%s", "Unexpected create machine success\n");
+ return -1;
+ }
++ unsetenv("FAIL_NO_SERVICE");
+
+ if (rv != -2) {
+ fprintf(stderr, "%s", "Unexpected create machine error\n");
+@@ -126,9 +128,11 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED)
+ 123,
+ false,
+ NULL)) == 0) {
++ unsetenv("FAIL_BAD_SERVICE");
+ fprintf(stderr, "%s", "Unexpected create machine success\n");
+ return -1;
+ }
++ unsetenv("FAIL_BAD_SERVICE");
+
+ if (rv != -1) {
+ fprintf(stderr, "%s", "Unexpected create machine error\n");
+--
+1.8.3.2
+
--- /dev/null
+From 7a032ce726b449746310965777e1b18e531c38b8 Mon Sep 17 00:00:00 2001
+Message-Id: <7a032ce726b449746310965777e1b18e531c38b8.1381871411.git.jdenemar@redhat.com>
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Mon, 7 Oct 2013 17:17:33 +0100
+Subject: [PATCH] Free cmd in virNetDevVethCreate
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+(cherry picked from commit 391b82722ef44df993d21332a06ccdd5e3500306)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virnetdevveth.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
+index ea49053..25eb282 100644
+--- a/src/util/virnetdevveth.c
++++ b/src/util/virnetdevveth.c
+@@ -110,6 +110,7 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ char *veth1auto = NULL;
+ char *veth2auto = NULL;
+ int vethNum = 0;
++ virCommandPtr cmd = NULL;
+ size_t i;
+
+ /*
+@@ -139,7 +140,7 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ vethNum = veth2num + 1;
+ }
+
+- virCommandPtr cmd = virCommandNew("ip");
++ cmd = virCommandNew("ip");
+ virCommandAddArgList(cmd, "link", "add",
+ *veth1 ? *veth1 : veth1auto,
+ "type", "veth", "peer", "name",
+@@ -169,6 +170,8 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ status);
+ VIR_FREE(veth1auto);
+ VIR_FREE(veth2auto);
++ virCommandFree(cmd);
++ cmd = NULL;
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -176,6 +179,7 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ MAX_VETH_RETRIES);
+
+ cleanup:
++ virCommandFree(cmd);
+ VIR_FREE(veth1auto);
+ VIR_FREE(veth2auto);
+ return ret;
+--
+1.8.3.2
+
--- /dev/null
+From ed02ed00086992e3e7445a2938fe5ef5006781f3 Mon Sep 17 00:00:00 2001
+Message-Id: <ed02ed00086992e3e7445a2938fe5ef5006781f3.1381871411.git.jdenemar@redhat.com>
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Mon, 7 Oct 2013 17:17:32 +0100
+Subject: [PATCH] Free cmd in virNetDevVethDelete
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+(cherry picked from commit 524b21979a59b825c5547717bcb38b5e3ff0fa67)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virnetdevveth.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
+index 403961b..ea49053 100644
+--- a/src/util/virnetdevveth.c
++++ b/src/util/virnetdevveth.c
+@@ -196,18 +196,24 @@ int virNetDevVethDelete(const char *veth)
+ {
+ virCommandPtr cmd = virCommandNewArgList("ip", "link", "del", veth, NULL);
+ int status;
++ int ret = -1;
+
+ if (virCommandRun(cmd, &status) < 0)
+- return -1;
++ goto cleanup;
+
+ if (status != 0) {
+ if (!virNetDevExists(veth)) {
+ VIR_DEBUG("Device %s already deleted (by kernel namespace cleanup)", veth);
+- return 0;
++ ret = 0;
++ goto cleanup;
+ }
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to delete veth device %s"), veth);
+- return -1;
++ goto cleanup;
+ }
+- return 0;
++
++ ret = 0;
++cleanup:
++ virCommandFree(cmd);
++ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From cacfd6f28a2adb52687d974072d66b213304b1be Mon Sep 17 00:00:00 2001
+Message-Id: <cacfd6f28a2adb52687d974072d66b213304b1be.1379597659.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Mon, 16 Sep 2013 19:32:08 +0200
+Subject: [PATCH] Free slicename in virSystemdCreateMachine
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008619
+
+1,003 bytes in 1 blocks are definitely lost in loss record 599 of 635
+==404== by 0x50728A7: virBufferAddChar (virbuffer.c:185)
+==404== by 0x50BC466: virSystemdEscapeName (virsystemd.c:67)
+==404== by 0x50BC6B2: virSystemdMakeSliceName (virsystemd.c:108)
+==404== by 0x50BC870: virSystemdCreateMachine (virsystemd.c:169)
+==404== by 0x5078267: virCgroupNewMachine (vircgroup.c:1498)
+(cherry picked from commit 09b48562aac12387a5ff9ac2f27f9a60490f41ee)
+---
+ src/util/virsystemd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index 251b846..d0063a1 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -242,5 +242,6 @@ cleanup:
+ VIR_FREE(username);
+ VIR_FREE(creatorname);
+ VIR_FREE(machinename);
++ VIR_FREE(slicename);
+ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 4fdf3d3899e40d74073622f11a8ba2771d16c002 Mon Sep 17 00:00:00 2001
+Message-Id: <4fdf3d3899e40d74073622f11a8ba2771d16c002.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 14:06:57 +0100
+Subject: [PATCH] Honour root prefix in lxcContainerMountFSBlockAuto
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=924815
+
+The lxcContainerMountFSBlockAuto method can be used to mount the
+initial root filesystem, so it cannot assume a prefix of /.oldroot.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 2d07f84302eac7656ad6ac227c1e6655b8af1425)
+---
+ src/lxc/lxc_container.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index a943b22..0ab4026 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1144,7 +1144,8 @@ lxcContainerMountDetectFilesystem(const char *src ATTRIBUTE_UNUSED,
+ */
+ static int lxcContainerMountFSBlockAuto(virDomainFSDefPtr fs,
+ int fsflags,
+- const char *src)
++ const char *src,
++ const char *srcprefix)
+ {
+ FILE *fp = NULL;
+ int ret = -1;
+@@ -1154,11 +1155,11 @@ static int lxcContainerMountFSBlockAuto(virDomainFSDefPtr fs,
+ char *line = NULL;
+ const char *type;
+
+- VIR_DEBUG("src=%s dst=%s", src, fs->dst);
++ VIR_DEBUG("src=%s dst=%s srcprefix=%s", src, fs->dst, srcprefix);
+
+ /* First time around we use /etc/filesystems */
+ retry:
+- if (virAsprintf(&fslist, "/.oldroot%s",
++ if (virAsprintf(&fslist, "%s%s", srcprefix,
+ tryProc ? "/proc/filesystems" : "/etc/filesystems") < 0)
+ goto cleanup;
+
+@@ -1270,7 +1271,8 @@ cleanup:
+ * probing for filesystem type
+ */
+ static int lxcContainerMountFSBlockHelper(virDomainFSDefPtr fs,
+- const char *src)
++ const char *src,
++ const char *srcprefix)
+ {
+ int fsflags = 0;
+ int ret = -1;
+@@ -1300,7 +1302,7 @@ static int lxcContainerMountFSBlockHelper(virDomainFSDefPtr fs,
+ }
+ ret = 0;
+ } else {
+- ret = lxcContainerMountFSBlockAuto(fs, fsflags, src);
++ ret = lxcContainerMountFSBlockAuto(fs, fsflags, src, srcprefix);
+ }
+
+ cleanup:
+@@ -1318,7 +1320,7 @@ static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
+ if (virAsprintf(&src, "%s%s", srcprefix, fs->src) < 0)
+ goto cleanup;
+
+- ret = lxcContainerMountFSBlockHelper(fs, src);
++ ret = lxcContainerMountFSBlockHelper(fs, src, srcprefix);
+
+ VIR_DEBUG("Done mounting filesystem ret=%d", ret);
+
+--
+1.8.3.2
+
--- /dev/null
+From 6fb618488723ceee1f422006b2517154733cd0dc Mon Sep 17 00:00:00 2001
+Message-Id: <6fb618488723ceee1f422006b2517154733cd0dc.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:22 +0100
+Subject: [PATCH] Improve error reporting with LXC controller
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+The LXC code would read the log file if an LXC guest failed to
+startup. There were a number of failure cases where the guest
+will not start and libvirtd never gets as far as looking at the
+log file.
+
+Fix this by replacing some earlier generic errors with messages
+from the log.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 1815e2d0812a9cd1c85363e93db5c00e302d1c96)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_process.c | 29 +++++++++++++++++++++++------
+ 1 file changed, 23 insertions(+), 6 deletions(-)
+
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index 724ffa9..ccf86af 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -980,6 +980,7 @@ int virLXCProcessStart(virConnectPtr conn,
+ virErrorPtr err = NULL;
+ virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
+ virCgroupPtr selfcgroup;
++ int status;
+
+ if (virCgroupNewSelf(&selfcgroup) < 0)
+ return -1;
+@@ -1182,9 +1183,18 @@ int virLXCProcessStart(virConnectPtr conn,
+ VIR_WARN("Unable to seek to end of logfile: %s",
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+
+- if (virCommandRun(cmd, NULL) < 0)
++ if (virCommandRun(cmd, &status) < 0)
+ goto cleanup;
+
++ if (status != 0) {
++ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) <= 0)
++ snprintf(ebuf, sizeof(ebuf), "unexpected exit status %d", status);
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("guest failed to start: %s"), ebuf);
++ goto cleanup;
++ }
++
++
+ if (VIR_CLOSE(handshakefds[1]) < 0) {
+ virReportSystemError(errno, "%s", _("could not close handshake fd"));
+ goto cleanup;
+@@ -1193,16 +1203,23 @@ int virLXCProcessStart(virConnectPtr conn,
+ /* Connect to the controller as a client *first* because
+ * this will block until the child has written their
+ * pid file out to disk & created their cgroup */
+- if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
++ if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) {
++ /* Intentionally overwrite the real monitor error message,
++ * since a better one is almost always found in the logs
++ */
++ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) {
++ virResetLastError();
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("guest failed to start: %s"), ebuf);
++ }
+ goto cleanup;
++ }
+
+ /* And get its pid */
+ if ((r = virPidFileRead(cfg->stateDir, vm->def->name, &vm->pid)) < 0) {
+- char out[1024];
+-
+- if (virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) > 0)
++ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("guest failed to start: %s"), out);
++ _("guest failed to start: %s"), ebuf);
+ else
+ virReportSystemError(-r,
+ _("Failed to read pid file %s/%s.pid"),
+--
+1.8.3.2
+
--- /dev/null
+From 2ca27d701eea8770bd015c779d6fc959c5d7f176 Mon Sep 17 00:00:00 2001
+Message-Id: <2ca27d701eea8770bd015c779d6fc959c5d7f176.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:28 +0100
+Subject: [PATCH] Improve log filtering in virLXCProcessReadLogOutputData
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+Make the virLXCProcessReadLogOutputData method ignore the log
+lines about the container startup argv, ignore the generic
+error message from libvirt_lxc when lxcContainerMain fails
+and skip over blank lines.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 5a1cb1075af0c0ace466bf7cbb9d722dca812ec9)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_process.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index ccf86af..a5f1f35 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -807,6 +807,20 @@ cleanup:
+ }
+
+
++static bool
++virLXCProcessIgnorableLogLine(const char *str)
++{
++ if (virLogProbablyLogMessage(str))
++ return true;
++ if (strstr(str, "PATH="))
++ return true;
++ if (strstr(str, "error receiving signal from container"))
++ return true;
++ if (STREQ(str, ""))
++ return true;
++ return false;
++}
++
+ static int
+ virLXCProcessReadLogOutputData(virDomainObjPtr vm,
+ int fd,
+@@ -844,7 +858,7 @@ virLXCProcessReadLogOutputData(virDomainObjPtr vm,
+ /* Filter out debug messages from intermediate libvirt process */
+ while ((eol = strchr(filter_next, '\n'))) {
+ *eol = '\0';
+- if (virLogProbablyLogMessage(filter_next)) {
++ if (virLXCProcessIgnorableLogLine(filter_next)) {
+ memmove(filter_next, eol + 1, got - (eol - buf));
+ got -= eol + 1 - filter_next;
+ } else {
+--
+1.8.3.2
+
--- /dev/null
+From 1d0e74a42e6f308bad8603911335d4fda841d316 Mon Sep 17 00:00:00 2001
+Message-Id: <1d0e74a42e6f308bad8603911335d4fda841d316.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:29 +0100
+Subject: [PATCH] Initialize threading & error layer in LXC controller
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018725
+
+In Fedora 20, libvirt_lxc crashes immediately at startup with a
+trace
+
+ #0 0x00007f0cddb653ec in free () from /lib64/libc.so.6
+ #1 0x00007f0ce0e16f4a in virFree (ptrptr=ptrptr@entry=0x7f0ce1830058) at util/viralloc.c:580
+ #2 0x00007f0ce0e2764b in virResetError (err=0x7f0ce1830030) at util/virerror.c:354
+ #3 0x00007f0ce0e27a5a in virResetLastError () at util/virerror.c:387
+ #4 0x00007f0ce0e28858 in virEventRegisterDefaultImpl () at util/virevent.c:233
+ #5 0x00007f0ce0db47c6 in main (argc=11, argv=0x7fff4596c328) at lxc/lxc_controller.c:2352
+
+Normally virInitialize calls virErrorInitialize and
+virThreadInitialize, but we don't link to libvirt.so
+in libvirt_lxc, and nor did we ever call the error
+or thread initializers.
+
+I have absolutely no idea how this has ever worked, let alone
+what caused it to stop working in Fedora 20.
+
+In addition not all code paths from virLogSetFromEnv will
+ensure virLogInitialize is called correctly, which is another
+possible crash scenario.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 97973ebb7a64a3be6710ddd38d124307991ad7cb)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_controller.c | 4 +++-
+ src/util/virlog.c | 6 ++++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index e301c43..357910d 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -2257,7 +2257,9 @@ int main(int argc, char *argv[])
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+- textdomain(PACKAGE) == NULL) {
++ textdomain(PACKAGE) == NULL ||
++ virThreadInitialize() < 0 ||
++ virErrorInitialize() < 0) {
+ fprintf(stderr, _("%s: initialization failed\n"), argv[0]);
+ exit(EXIT_FAILURE);
+ }
+diff --git a/src/util/virlog.c b/src/util/virlog.c
+index daf964b..6f791ad 100644
+--- a/src/util/virlog.c
++++ b/src/util/virlog.c
+@@ -547,6 +547,9 @@ virLogDefineFilter(const char *match,
+
+ virCheckFlags(VIR_LOG_STACK_TRACE, -1);
+
++ if (virLogInitialize() < 0)
++ return -1;
++
+ if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
+ (priority > VIR_LOG_ERROR))
+ return -1;
+@@ -662,6 +665,9 @@ virLogDefineOutput(virLogOutputFunc f,
+
+ virCheckFlags(0, -1);
+
++ if (virLogInitialize() < 0)
++ return -1;
++
+ if (f == NULL)
+ return -1;
+
+--
+1.8.3.2
+
--- /dev/null
+From 838cf2f32c9f7050da3ae5a31b3108ce77684839 Mon Sep 17 00:00:00 2001
+Message-Id: <838cf2f32c9f7050da3ae5a31b3108ce77684839.1377873638.git.jdenemar@redhat.com>
+From: Dan Walsh <dwalsh@redhat.com>
+Date: Tue, 13 Aug 2013 15:20:40 +0100
+Subject: [PATCH] Introduce a virt-login-shell binary
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=988491
+
+Add a virt-login-shell binary that can be set as a user's
+shell, such that when they login, it causes them to enter
+the LXC container with a name matching their user name.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 54d69f540c9928da98f10202b3f21b7abb00bac1)
+---
+ .gitignore | 1 +
+ libvirt.spec.in | 3 +
+ po/POTFILES.in | 1 +
+ tools/Makefile.am | 30 +++-
+ tools/virt-login-shell.c | 350 ++++++++++++++++++++++++++++++++++++++++++++
+ tools/virt-login-shell.conf | 26 ++++
+ tools/virt-login-shell.pod | 62 ++++++++
+ 7 files changed, 472 insertions(+), 1 deletion(-)
+ create mode 100644 tools/virt-login-shell.c
+ create mode 100644 tools/virt-login-shell.conf
+ create mode 100644 tools/virt-login-shell.pod
+
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 1fd84af..884b70a 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -231,3 +231,4 @@ tools/virt-host-validate-common.c
+ tools/virt-host-validate-lxc.c
+ tools/virt-host-validate-qemu.c
+ tools/virt-host-validate.c
++tools/virt-login-shell.c
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index 644a86d..00c582a 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -37,6 +37,7 @@ EXTRA_DIST = \
+ virt-pki-validate.in \
+ virt-sanlock-cleanup.in \
+ virt-sanlock-cleanup.8 \
++ virt-login-shell.pod \
+ virsh.pod \
+ libvirt-guests.sysconf \
+ virsh-edit.c \
+@@ -52,8 +53,11 @@ EXTRA_DIST = \
+
+ DISTCLEANFILES =
+
++confdir = $(sysconfdir)/libvirt
++conf_DATA = virt-login-shell.conf
++
+ bin_SCRIPTS = virt-xml-validate virt-pki-validate
+-bin_PROGRAMS = virsh virt-host-validate
++bin_PROGRAMS = virsh virt-host-validate virt-login-shell
+ libexec_SCRIPTS = libvirt-guests.sh
+
+ if WITH_SANLOCK
+@@ -65,6 +69,7 @@ dist_man1_MANS = \
+ virt-host-validate.1 \
+ virt-pki-validate.1 \
+ virt-xml-validate.1 \
++ virt-login-shell.1 \
+ virsh.1
+ if WITH_SANLOCK
+ dist_man8_MANS = virt-sanlock-cleanup.8
+@@ -128,6 +133,24 @@ virt_host_validate_CFLAGS = \
+ $(COVERAGE_CFLAGS) \
+ $(NULL)
+
++virt_login_shell_SOURCES = \
++ virt-login-shell.conf \
++ virt-login-shell.c
++
++virt_login_shell_LDFLAGS = $(COVERAGE_LDFLAGS)
++virt_login_shell_LDADD = \
++ $(STATIC_BINARIES) \
++ $(PIE_LDFLAGS) \
++ $(RELRO_LDFLAGS) \
++ ../src/libvirt.la \
++ ../src/libvirt-lxc.la \
++ ../gnulib/lib/libgnu.la
++
++virt_login_shell_CFLAGS = \
++ $(WARN_CFLAGS) \
++ $(PIE_CFLAGS) \
++ $(COVERAGE_CFLAGS)
++
+ virsh_SOURCES = \
+ console.c console.h \
+ virsh.c virsh.h \
+@@ -189,6 +212,11 @@ virsh_win_icon.$(OBJEXT): virsh_win_icon.rc
+ --output-format coff --output $@
+ endif
+
++virt-login-shell.1: virt-login-shell.pod $(top_srcdir)/configure.ac
++ $(AM_V_GEN)$(POD2MAN) $< $(srcdir)/$@ \
++ && if grep 'POD ERROR' $(srcdir)/$@ ; then \
++ rm $(srcdir)/$@; exit 1; fi
++
+ virsh.1: virsh.pod $(top_srcdir)/configure.ac
+ $(AM_V_GEN)$(POD2MAN) $< $(srcdir)/$@ \
+ && if grep 'POD ERROR' $(srcdir)/$@ ; then \
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+new file mode 100644
+index 0000000..ffbc713
+--- /dev/null
++++ b/tools/virt-login-shell.c
+@@ -0,0 +1,350 @@
++/*
++ * virt-login-shell.c: a shell to connect to a container
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Daniel Walsh <dwalsh@redhat.com>
++ */
++#include <config.h>
++
++#include <stdarg.h>
++#include <getopt.h>
++#include <stdio.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <fnmatch.h>
++
++#include "internal.h"
++#include "virerror.h"
++#include "virconf.h"
++#include "virutil.h"
++#include "virfile.h"
++#include "virprocess.h"
++#include "configmake.h"
++#include "virstring.h"
++#include "viralloc.h"
++#include "vircommand.h"
++#define VIR_FROM_THIS VIR_FROM_NONE
++
++static ssize_t nfdlist = 0;
++static int *fdlist = NULL;
++static const char *conf_file = SYSCONFDIR "/libvirt/virt-login-shell.conf";
++
++static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom)
++{
++ size_t i;
++
++ for (i = 0; i < nfdlist; i++)
++ VIR_FORCE_CLOSE(fdlist[i]);
++ VIR_FREE(fdlist);
++ nfdlist = 0;
++ if (dom)
++ virDomainFree(dom);
++ if (conn)
++ virConnectClose(conn);
++}
++
++static int virLoginShellAllowedUser(virConfPtr conf,
++ const char *name,
++ gid_t *groups)
++{
++ virConfValuePtr p;
++ int ret = -1;
++ char *ptr = NULL;
++ size_t i;
++ char *gname = NULL;
++
++ p = virConfGetValue(conf, "allowed_users");
++ if (p && p->type == VIR_CONF_LIST) {
++ virConfValuePtr pp;
++
++ /* Calc length and check items */
++ for (pp = p->list; pp; pp = pp->next) {
++ if (pp->type != VIR_CONF_STRING) {
++ virReportSystemError(EINVAL, "%s", _("shell must be a list of strings"));
++ goto cleanup;
++ } else {
++ /*
++ If string begins with a % this indicates a linux group.
++ Check to see if the user is in the Linux Group.
++ */
++ if (pp->str[0] == '%') {
++ ptr = &pp->str[1];
++ if (!ptr)
++ continue;
++ for (i = 0; groups[i]; i++) {
++ if (!(gname = virGetGroupName(groups[i])))
++ continue;
++ if (fnmatch(ptr, gname, 0) == 0) {
++ ret = 0;
++ goto cleanup;
++ }
++ VIR_FREE(gname);
++ }
++ VIR_FREE(groups);
++ continue;
++ }
++ if (fnmatch(pp->str, name, 0) == 0) {
++ ret = 0;
++ goto cleanup;
++ }
++ }
++ }
++ }
++ virReportSystemError(EPERM, _("%s not listed as an allowed_users in %s"), name, conf_file);
++cleanup:
++ VIR_FREE(gname);
++ VIR_FREE(groups);
++ return ret;
++}
++
++static char **virLoginShellGetShellArgv(virConfPtr conf)
++{
++ size_t i;
++ char **shargv=NULL;
++ virConfValuePtr p;
++
++ p = virConfGetValue(conf, "shell");
++ if (!p)
++ return virStringSplit("/bin/sh -l", " ", 3);
++
++ if (p && p->type == VIR_CONF_LIST) {
++ size_t len;
++ virConfValuePtr pp;
++
++ /* Calc length and check items */
++ for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
++ if (pp->type != VIR_CONF_STRING) {
++ virReportSystemError(EINVAL, "%s", _("shell must be a list of strings"));
++ goto error;
++ }
++ }
++
++ if (VIR_ALLOC_N(shargv, len + 1) < 0)
++ goto error;
++ for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
++ if (VIR_STRDUP(shargv[i], pp->str) < 0)
++ goto error;
++ }
++ shargv[len] = NULL;
++ }
++ return shargv;
++error:
++ virStringFreeList(shargv);
++ return NULL;
++}
++
++static char *progname;
++
++/*
++ * Print usage
++ */
++static void
++usage(void)
++{
++ fprintf(stdout, _("\n"
++ "%s is a privileged program that allows non root users \n"
++ "specified in %s to join a Linux container \n"
++ "with a matching user name and launch a shell. \n"
++ "\n%s [options]\n\n"
++ " options:\n"
++ " -h | --help this help:\n\n"), progname, conf_file, progname);
++ return;
++}
++
++int
++main(int argc, char **argv)
++{
++ virConfPtr conf = NULL;
++ const char *login_shell_path = conf_file;
++ pid_t cpid;
++ int ret = EXIT_FAILURE;
++ int status;
++ int status2;
++ uid_t uid = getuid();
++ gid_t gid = getgid();
++ char *name = NULL;
++ char **shargv = NULL;
++ virSecurityModelPtr secmodel = NULL;
++ virSecurityLabelPtr seclabel = NULL;
++ virDomainPtr dom = NULL;
++ virConnectPtr conn = NULL;
++ char *homedir = NULL;
++ int arg;
++ int longindex = -1;
++ int ngroups;
++ gid_t *groups = NULL;
++
++ struct option opt[] = {
++ {"help", no_argument, NULL, 'h'},
++ {NULL, 0, NULL, 0}
++ };
++ if (virInitialize() < 0) {
++ fprintf(stderr, _("Failed to initialize libvirt Error Handling"));
++ return EXIT_FAILURE;
++ }
++
++ virSetErrorFunc(NULL, NULL);
++ virSetErrorLogPriorityFunc(NULL);
++
++ progname = argv[0];
++ if (!setlocale(LC_ALL, "")) {
++ perror("setlocale");
++ /* failure to setup locale is not fatal */
++ }
++ if (!bindtextdomain(PACKAGE, LOCALEDIR)) {
++ perror("bindtextdomain");
++ return ret;
++ }
++ if (!textdomain(PACKAGE)) {
++ perror("textdomain");
++ return ret;
++ }
++
++ /* The only option we support is help
++ */
++ while ((arg = getopt_long(argc, argv, "h", opt, &longindex)) != -1) {
++ switch (arg) {
++ case 'h':
++ usage();
++ exit(EXIT_SUCCESS);
++ break;
++ }
++ }
++
++ if (argc > optind) {
++ virReportSystemError(EINVAL, _("%s takes no options"), progname);
++ errno = EINVAL;
++ goto cleanup;
++ }
++
++ if (uid == 0) {
++ virReportSystemError(EPERM, _("%s must be run by non root users"), progname);
++ goto cleanup;
++ }
++
++ name = virGetUserName(uid);
++ if (!name)
++ goto cleanup;
++
++ homedir = virGetUserDirectoryByUID(uid);
++ if (!homedir)
++ goto cleanup;
++
++ if (!(conf = virConfReadFile(login_shell_path, 0)))
++ goto cleanup;
++
++ if ((ngroups = virGetGroupList(uid, gid, &groups)) < 0)
++ goto cleanup;
++
++ if (virLoginShellAllowedUser(conf, name, groups) < 0)
++ goto cleanup;
++
++ if (!(shargv = virLoginShellGetShellArgv(conf)))
++ goto cleanup;
++
++ conn = virConnectOpen("lxc:///");
++ if (!conn)
++ goto cleanup;
++
++ dom = virDomainLookupByName(conn, name);
++ if (!dom)
++ goto cleanup;
++
++ if (!virDomainIsActive(dom) && virDomainCreate(dom)) {
++ virErrorPtr last_error;
++ last_error = virGetLastError();
++ if (last_error->code != VIR_ERR_OPERATION_INVALID) {
++ virReportSystemError(last_error->code,_("Can't create %s container: %s"), name, virGetLastErrorMessage());
++ goto cleanup;
++ }
++ }
++
++ if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0)
++ goto cleanup;
++ if (VIR_ALLOC(secmodel) < 0)
++ goto cleanup;
++ if (VIR_ALLOC(seclabel) < 0)
++ goto cleanup;
++ if (virNodeGetSecurityModel(conn, secmodel) < 0)
++ goto cleanup;
++ if (virDomainGetSecurityLabel(dom, seclabel) < 0)
++ goto cleanup;
++
++ if (virFork(&cpid) < 0)
++ goto cleanup;
++
++ if (cpid == 0) {
++ pid_t ccpid;
++
++ /* Fork once because we don't want to affect
++ * virt-login-shell's namespace itself
++ */
++ if (virSetUIDGID(0, 0, NULL, 0) < 0)
++ return EXIT_FAILURE;
++
++ if (virDomainLxcEnterSecurityLabel(secmodel,
++ seclabel,
++ NULL,
++ 0) < 0)
++ return EXIT_FAILURE;
++
++ if (nfdlist > 0) {
++ if (virDomainLxcEnterNamespace(dom,
++ nfdlist,
++ fdlist,
++ NULL,
++ NULL,
++ 0) < 0)
++ return EXIT_FAILURE;
++ }
++
++ ret = virSetUIDGID(uid, gid, groups, ngroups);
++ VIR_FREE(groups);
++ if (ret < 0)
++ return EXIT_FAILURE;
++
++ if (virFork(&ccpid) < 0)
++ return EXIT_FAILURE;
++
++ if (ccpid == 0) {
++ if (chdir(homedir) < 0) {
++ virReportSystemError(errno, _("Unable chdir(%s)"), homedir);
++ return EXIT_FAILURE;
++ }
++ if (execv(shargv[0], (char *const*) shargv) < 0) {
++ virReportSystemError(errno, _("Unable exec shell %s"), shargv[0]);
++ return -errno;
++ }
++ }
++ return virProcessWait(ccpid, &status2);
++ }
++ ret = virProcessWait(cpid, &status);
++
++cleanup:
++ virConfFree(conf);
++ virLoginShellFini(conn, dom);
++ virStringFreeList(shargv);
++ VIR_FREE(name);
++ VIR_FREE(homedir);
++ VIR_FREE(seclabel);
++ VIR_FREE(secmodel);
++ VIR_FREE(groups);
++ if (ret)
++ virDispatchError(NULL);
++ return ret;
++}
+diff --git a/tools/virt-login-shell.conf b/tools/virt-login-shell.conf
+new file mode 100644
+index 0000000..835fd3f
+--- /dev/null
++++ b/tools/virt-login-shell.conf
+@@ -0,0 +1,26 @@
++# Master configuration file for the virt-login-shell program.
++# All settings described here are optional - if omitted, sensible
++# defaults are used.
++
++# By default, virt-login-shell will connect you to a container running
++# with the /bin/sh program. Modify the shell variable if you want your
++# users to run a different shell or a setup container when joining a
++# container. Shell commands must be a list of commands/options separated by
++# comma and delimited by square brackets. Defaults to: /bin/sh -l.
++# Modify and uncomment the following to modify the login shell.
++# shell = [ "/bin/sh", "-l" ]
++
++# allowed_users specifies the user names of all users that are allowed to
++# execute virt-login-shell. You can specify the users as a comma
++# separated list of usernames or user groups.
++# The list of names support glob syntax.
++# To disallow all users (default)
++# allowed_users = []
++# If you do not specify any names (default) then no one is allowed
++# to use this executable.
++# To allow fred and joe only
++# allowed_users = ["fred", "joe"]
++# To allow all users within a specific group prefix the group name with %.
++# allowed_users = ["%engineers"]
++# To allow all users specify the following
++# allowed_users = [ "*" ]
+diff --git a/tools/virt-login-shell.pod b/tools/virt-login-shell.pod
+new file mode 100644
+index 0000000..0cd35cf
+--- /dev/null
++++ b/tools/virt-login-shell.pod
+@@ -0,0 +1,62 @@
++=head1 NAME
++
++virt-login-shell - tool to execute a shell within a container matching the users name
++
++=head1 SYNOPSIS
++
++B<virt-login-shell>
++
++=head1 DESCRIPTION
++
++The B<virt-login-shell> program is setuid shell that is used to join
++an LXC container that matches the users name. If the container is not
++running virt-login-shell will attempt to start the container.
++virt-sandbox-shell is not allowed to be run by root. Normal users will get
++added to a container that matches their username, if it exists. And they are
++configured in /etc/libvirt/virt-login-shell.conf.
++
++The basic structure of most virt-login-shell usage is:
++
++ virt-login-shell
++
++=head1 CONFIG
++
++By default, virt-login-shell will execute the /bin/sh program for the user.
++You can modify this behaviour by defining the shell variable in /etc/libvirt/virt-login-shell.conf.
++
++eg. shell = [ "/bin/ksh", "--login"]
++
++By default no users are allowed to user virt-login-shell, if you want to allow
++certain users to use virt-login-shell, you need to modify the allowed_users variable in /etc/libvirt/virt-login-shell.conf.
++
++eg. allowed_users = [ "tom", "dick", "harry" ]
++
++=head1 BUGS
++
++Report any bugs discovered to the libvirt community via the mailing
++list C<http://libvirt.org/contact.html> or bug tracker C<http://libvirt.org/bugs.html>.
++Alternatively report bugs to your software distributor / vendor.
++
++=head1 AUTHORS
++
++ Please refer to the AUTHORS file distributed with libvirt.
++
++ Daniel Walsh <dwalsh at redhat dot com>
++
++=head1 COPYRIGHT
++
++Copyright (C) 2013 Red Hat, Inc., and the authors listed in the
++libvirt AUTHORS file.
++
++=head1 LICENSE
++
++virt-login-shell is distributed under the terms of the GNU LGPL v2+.
++This is free software; see the source for copying conditions. There
++is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
++PURPOSE
++
++=head1 SEE ALSO
++
++L<virsh(1)>, L<http://www.libvirt.org/>
++
++=cut
+--
+1.8.3.2
+
--- /dev/null
+From 8f5480fdbf65d53aade99836156fad34f21d3803 Mon Sep 17 00:00:00 2001
+Message-Id: <8f5480fdbf65d53aade99836156fad34f21d3803.1377873636.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 5 Aug 2013 11:30:17 +0200
+Subject: [PATCH] Introduce max_queued_clients
+
+https://bugzilla.redhat.com/show_bug.cgi?id=981729
+
+This configuration knob lets user to set the length of queue of
+connection requests waiting to be accept()-ed by the daemon. IOW, it
+just controls the @backlog passed to listen:
+
+ int listen(int sockfd, int backlog);
+(cherry picked from commit 1199edb1d4e3ebbc691bd32d3519a3b662225420)
+---
+ daemon/libvirtd-config.c | 1 +
+ daemon/libvirtd-config.h | 1 +
+ daemon/libvirtd.aug | 1 +
+ daemon/libvirtd.c | 4 ++++
+ daemon/libvirtd.conf | 6 ++++++
+ src/locking/lock_daemon.c | 2 +-
+ src/lxc/lxc_controller.c | 1 +
+ src/rpc/virnetserverservice.c | 6 ++++--
+ src/rpc/virnetserverservice.h | 2 ++
+ 9 files changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/daemon/libvirtd-config.c b/daemon/libvirtd-config.c
+index 107a9cf..c816fda 100644
+--- a/daemon/libvirtd-config.c
++++ b/daemon/libvirtd-config.c
+@@ -414,6 +414,7 @@ daemonConfigLoadOptions(struct daemonConfig *data,
+ GET_CONF_INT(conf, filename, min_workers);
+ GET_CONF_INT(conf, filename, max_workers);
+ GET_CONF_INT(conf, filename, max_clients);
++ GET_CONF_INT(conf, filename, max_queued_clients);
+
+ GET_CONF_INT(conf, filename, prio_workers);
+
+diff --git a/daemon/libvirtd-config.h b/daemon/libvirtd-config.h
+index 973e0ea..a24d5d2 100644
+--- a/daemon/libvirtd-config.h
++++ b/daemon/libvirtd-config.h
+@@ -63,6 +63,7 @@ struct daemonConfig {
+ int min_workers;
+ int max_workers;
+ int max_clients;
++ int max_queued_clients;
+
+ int prio_workers;
+
+diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug
+index 7c56a41..70fce5c 100644
+--- a/daemon/libvirtd.aug
++++ b/daemon/libvirtd.aug
+@@ -56,6 +56,7 @@ module Libvirtd =
+ let processing_entry = int_entry "min_workers"
+ | int_entry "max_workers"
+ | int_entry "max_clients"
++ | int_entry "max_queued_clients"
+ | int_entry "max_requests"
+ | int_entry "max_client_requests"
+ | int_entry "prio_workers"
+diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
+index 9f7fd8a..402b494 100644
+--- a/daemon/libvirtd.c
++++ b/daemon/libvirtd.c
+@@ -485,6 +485,7 @@ static int daemonSetupNetworking(virNetServerPtr srv,
+ NULL,
+ #endif
+ false,
++ config->max_queued_clients,
+ config->max_client_requests)))
+ goto error;
+ if (sock_path_ro) {
+@@ -497,6 +498,7 @@ static int daemonSetupNetworking(virNetServerPtr srv,
+ NULL,
+ #endif
+ true,
++ config->max_queued_clients,
+ config->max_client_requests)))
+ goto error;
+ }
+@@ -522,6 +524,7 @@ static int daemonSetupNetworking(virNetServerPtr srv,
+ NULL,
+ #endif
+ false,
++ config->max_queued_clients,
+ config->max_client_requests)))
+ goto error;
+
+@@ -562,6 +565,7 @@ static int daemonSetupNetworking(virNetServerPtr srv,
+ config->auth_tls,
+ ctxt,
+ false,
++ config->max_queued_clients,
+ config->max_client_requests))) {
+ virObjectUnref(ctxt);
+ goto error;
+diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf
+index af4493e..5353927 100644
+--- a/daemon/libvirtd.conf
++++ b/daemon/libvirtd.conf
+@@ -257,6 +257,12 @@
+ # over all sockets combined.
+ #max_clients = 20
+
++# The maximum length of queue of connections waiting to be
++# accepted by the daemon. Note, that some protocols supporting
++# retransmission may obey this so that a later reattempt at
++# connection succeeds.
++#max_queued_clients = 1000
++
+
+ # The minimum limit sets the number of workers to start up
+ # initially. If the number of active clients exceeds this,
+diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
+index c4c1727..c45f45c 100644
+--- a/src/locking/lock_daemon.c
++++ b/src/locking/lock_daemon.c
+@@ -671,7 +671,7 @@ virLockDaemonSetupNetworkingNative(virNetServerPtr srv, const char *sock_path)
+ #if WITH_GNUTLS
+ NULL,
+ #endif
+- false, 1)))
++ false, 0, 1)))
+ return -1;
+
+ if (virNetServerAddService(srv, svc, NULL) < 0) {
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index 124ab19..ed73ab0 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -745,6 +745,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
+ NULL,
+ #endif
+ false,
++ 0,
+ 5)))
+ goto error;
+
+diff --git a/src/rpc/virnetserverservice.c b/src/rpc/virnetserverservice.c
+index 632f03d..4113ec9 100644
+--- a/src/rpc/virnetserverservice.c
++++ b/src/rpc/virnetserverservice.c
+@@ -97,6 +97,7 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
+ virNetTLSContextPtr tls,
+ #endif
+ bool readonly,
++ size_t max_queued_clients,
+ size_t nrequests_client_max)
+ {
+ virNetServerServicePtr svc;
+@@ -122,7 +123,7 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
+ goto error;
+
+ for (i = 0; i < svc->nsocks; i++) {
+- if (virNetSocketListen(svc->socks[i], 0) < 0)
++ if (virNetSocketListen(svc->socks[i], max_queued_clients) < 0)
+ goto error;
+
+ /* IO callback is initially disabled, until we're ready
+@@ -155,6 +156,7 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
+ virNetTLSContextPtr tls,
+ #endif
+ bool readonly,
++ size_t max_queued_clients,
+ size_t nrequests_client_max)
+ {
+ virNetServerServicePtr svc;
+@@ -185,7 +187,7 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
+ goto error;
+
+ for (i = 0; i < svc->nsocks; i++) {
+- if (virNetSocketListen(svc->socks[i], 0) < 0)
++ if (virNetSocketListen(svc->socks[i], max_queued_clients) < 0)
+ goto error;
+
+ /* IO callback is initially disabled, until we're ready
+diff --git a/src/rpc/virnetserverservice.h b/src/rpc/virnetserverservice.h
+index 1ece503..eb31abf 100644
+--- a/src/rpc/virnetserverservice.h
++++ b/src/rpc/virnetserverservice.h
+@@ -44,6 +44,7 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
+ virNetTLSContextPtr tls,
+ # endif
+ bool readonly,
++ size_t max_queued_clients,
+ size_t nrequests_client_max);
+ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
+ mode_t mask,
+@@ -53,6 +54,7 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
+ virNetTLSContextPtr tls,
+ # endif
+ bool readonly,
++ size_t max_queued_clients,
+ size_t nrequests_client_max);
+ virNetServerServicePtr virNetServerServiceNewFD(int fd,
+ int auth,
+--
+1.8.3.2
+
--- /dev/null
+From 9b1952c45a8d014142c3c5d332a2a4c35da0cbd9 Mon Sep 17 00:00:00 2001
+Message-Id: <9b1952c45a8d014142c3c5d332a2a4c35da0cbd9.1381871412.git.jdenemar@redhat.com>
+From: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
+Date: Mon, 14 Oct 2013 16:45:25 +0100
+Subject: [PATCH] LXC: Check the existence of dir before resolving symlinks
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+If a dir does not exist, raise an immediate error in logs
+rather than letting virFileResolveAllLinks fail, since this
+gives better error reporting to the user.
+
+Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
+(cherry picked from commit 9a08e2cbc6933c068310c85354cff75e015f1de0)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index 43178e2..f6375b7 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1668,6 +1668,7 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+ {
+ char *newroot;
+ size_t i;
++ char ebuf[1024];
+
+ VIR_DEBUG("Resolving symlinks");
+
+@@ -1675,6 +1676,13 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+ virDomainFSDefPtr fs = vmDef->fss[i];
+ if (!fs->src)
+ continue;
++
++ if (access(fs->src, F_OK)) {
++ VIR_DEBUG("Failed to access '%s': %s", fs->src,
++ virStrerror(errno, ebuf, sizeof(ebuf)));
++ return -1;
++ }
++
+ VIR_DEBUG("Resolving '%s'", fs->src);
+ if (virFileResolveAllLinks(fs->src, &newroot) < 0) {
+ VIR_DEBUG("Failed to resolve symlink at %s", fs->src);
+--
+1.8.3.2
+
--- /dev/null
+From 36b51f3b1f6129a29abdee018d5d63f6ae37b586 Mon Sep 17 00:00:00 2001
+Message-Id: <36b51f3b1f6129a29abdee018d5d63f6ae37b586.1380112456.git.jdenemar@redhat.com>
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Fri, 20 Sep 2013 13:07:48 +0100
+Subject: [PATCH] LXC: Don't mount securityfs when user namespace enabled
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=872648
+
+Right now, securityfs is disallowed to be mounted in non-initial
+user namespace, so we must avoid trying to mount securityfs in
+a container which has user namespace enabled.
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+(cherry picked from commit 1583dfda7c4e5ad71efe0615c06e5676528d8203)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index 8abaea0..c41ab40 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -750,7 +750,7 @@ err:
+ }
+
+
+-static int lxcContainerMountBasicFS(void)
++static int lxcContainerMountBasicFS(bool userns_enabled)
+ {
+ const struct {
+ const char *src;
+@@ -801,6 +801,9 @@ static int lxcContainerMountBasicFS(void)
+ continue;
+ #endif
+
++ if (STREQ(mnts[i].src, "securityfs") && userns_enabled)
++ continue;
++
+ if (virFileMakePath(mnts[i].dst) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mkdir %s"),
+@@ -1530,7 +1533,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
+ goto cleanup;
+
+ /* Mounts the core /proc, /sys, etc filesystems */
+- if (lxcContainerMountBasicFS() < 0)
++ if (lxcContainerMountBasicFS(vmDef->idmap.nuidmap) < 0)
+ goto cleanup;
+
+ /* Mounts /proc/meminfo etc sysinfo */
+--
+1.8.3.2
+
--- /dev/null
+From 2109b3f2a7cfd9abf1ae17905508abdc1b492532 Mon Sep 17 00:00:00 2001
+Message-Id: <2109b3f2a7cfd9abf1ae17905508abdc1b492532.1381871412.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 9 Oct 2013 17:49:36 +0200
+Subject: [PATCH] LXC: Fix handling of RAM filesystem size units
+
+Since 76b644c when the support for RAM filesystems was introduced,
+libvirt accepted the following XML:
+<source usage='1024' unit='KiB'/>
+
+This was parsed correctly and internally stored in bytes, but it
+was formatted as (with an extra 's'):
+<source usage='1024' units='KiB'/>
+When read again, this was treated as if the units were missing,
+meaning libvirt was unable to parse its own XML correctly.
+
+The usage attribute was documented as being in KiB, but it was not
+scaled if the unit was missing. Transient domains still worked,
+because this was balanced by an extra 'k' in the mount options.
+
+This patch:
+Changes the parser to use 'units' instead of 'unit', as the latter
+was never documented (fixing persistent domains) and some programs
+(libvirt-glib, libvirt-sandbox) already parse the 'units' attribute.
+
+Removes the extra 'k' from the tmpfs mount options, which is needed
+because now we parse our own XML correctly.
+
+Changes the default input unit to KiB to match documentation, fixing:
+https://bugzilla.redhat.com/show_bug.cgi?id=1015689
+(cherry picked from commit 3f029fb5319b9dc9cc2fbf8d1ba4505ee9e4b1e3)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/formatdomain.html.in | 6 +++--
+ docs/schemas/domaincommon.rng | 2 +-
+ src/conf/domain_conf.c | 9 ++++---
+ src/conf/domain_conf.h | 2 +-
+ src/lxc/lxc_container.c | 2 +-
+ tests/domainschematest | 2 +-
+ tests/lxcxml2xmldata/lxc-filesystem-ram.xml | 33 ++++++++++++++++++++++++++
+ tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml | 33 ++++++++++++++++++++++++++
+ tests/lxcxml2xmltest.c | 1 +
+ 9 files changed, 79 insertions(+), 11 deletions(-)
+ create mode 100644 tests/lxcxml2xmldata/lxc-filesystem-ram.xml
+ create mode 100644 tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 4308dbe..4fecdee 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -2169,7 +2169,8 @@
+ <dd>
+ An in-memory filesystem, using memory from the host OS.
+ The source element has a single attribute <code>usage</code>
+- which gives the memory usage limit in kibibytes. Only used
++ which gives the memory usage limit in KiB, unless units
++ are specified by the <code>units</code> attribute. Only used
+ by LXC driver.
+ <span class="since"> (since 0.9.13)</span></dd>
+ <dt><code>type='bind'</code></dt>
+@@ -2235,7 +2236,8 @@
+ <code>name</code> attribute must be used with
+ <code>type='template'</code>, and the <code>dir</code> attribute must
+ be used with <code>type='mount'</code>. The <code>usage</code> attribute
+- is used with <code>type='ram'</code> to set the memory limit in KB.
++ is used with <code>type='ram'</code> to set the memory limit in KiB,
++ unless units are specified by the <code>units</code> attribute.
+ </dd>
+
+ <dt><code>target</code></dt>
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 838f657..5540745 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -1681,7 +1681,7 @@
+ <ref name="unsignedLong"/>
+ </attribute>
+ <optional>
+- <attribute name='unit'>
++ <attribute name='units'>
+ <ref name='unit'/>
+ </attribute>
+ </optional>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index bca2151..dea8130 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -5862,7 +5862,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
+ char *accessmode = NULL;
+ char *wrpolicy = NULL;
+ char *usage = NULL;
+- char *unit = NULL;
++ char *units = NULL;
+
+ ctxt->node = node;
+
+@@ -5918,7 +5918,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
+ source = virXMLPropString(cur, "name");
+ else if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
+ usage = virXMLPropString(cur, "usage");
+- unit = virXMLPropString(cur, "unit");
++ units = virXMLPropString(cur, "units");
+ }
+ } else if (!target &&
+ xmlStrEqual(cur->name, BAD_CAST "target")) {
+@@ -5988,8 +5988,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
+ usage);
+ goto error;
+ }
+- if (unit &&
+- virScaleInteger(&def->usage, unit,
++ if (virScaleInteger(&def->usage, units,
+ 1024, ULLONG_MAX) < 0)
+ goto error;
+ }
+@@ -6011,7 +6010,7 @@ cleanup:
+ VIR_FREE(accessmode);
+ VIR_FREE(wrpolicy);
+ VIR_FREE(usage);
+- VIR_FREE(unit);
++ VIR_FREE(units);
+ VIR_FREE(format);
+
+ return def;
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 5d2cb83..5a21576 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -874,7 +874,7 @@ struct _virDomainFSDef {
+ int accessmode; /* enum virDomainFSAccessMode */
+ int wrpolicy; /* enum virDomainFSWrpolicy */
+ int format; /* enum virStorageFileFormat */
+- unsigned long long usage;
++ unsigned long long usage; /* in bytes */
+ char *src;
+ char *dst;
+ bool readonly;
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index f851fcc..43178e2 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1434,7 +1434,7 @@ static int lxcContainerMountFSTmpfs(virDomainFSDefPtr fs,
+ VIR_DEBUG("usage=%lld sec=%s", fs->usage, sec_mount_options);
+
+ if (virAsprintf(&data,
+- "size=%lldk%s", fs->usage, sec_mount_options) < 0)
++ "size=%lld%s", fs->usage, sec_mount_options) < 0)
+ goto cleanup;
+
+ if (virFileMakePath(fs->dst) < 0) {
+diff --git a/tests/domainschematest b/tests/domainschematest
+index 0e360ca..9ebf0b9 100755
+--- a/tests/domainschematest
++++ b/tests/domainschematest
+@@ -7,7 +7,7 @@
+ DIRS=""
+ DIRS="$DIRS domainschemadata qemuxml2argvdata sexpr2xmldata"
+ DIRS="$DIRS xmconfigdata xml2sexprdata qemuxml2xmloutdata "
+-DIRS="$DIRS lxcxml2xmldata"
++DIRS="$DIRS lxcxml2xmldata lxcxml2xmloutdata"
+ SCHEMA="domain.rng"
+
+ check_schema "$DIRS" "$SCHEMA"
+diff --git a/tests/lxcxml2xmldata/lxc-filesystem-ram.xml b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml
+new file mode 100644
+index 0000000..002fde6
+--- /dev/null
++++ b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml
+@@ -0,0 +1,33 @@
++<domain type='lxc'>
++ <name>demo</name>
++ <uuid>8369f1ac-7e46-e869-4ca5-759d51478066</uuid>
++ <memory unit='KiB'>500000</memory>
++ <currentMemory unit='KiB'>500000</currentMemory>
++ <vcpu placement='static'>1</vcpu>
++ <os>
++ <type arch='x86_64'>exe</type>
++ <init>/bin/sh</init>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/libvirt_lxc</emulator>
++ <filesystem type='ram'>
++ <source usage='1048576'/>
++ <target dir='/mnt/mississippi'/>
++ </filesystem>
++ <filesystem type='ram'>
++ <source usage='1048576' units='bytes'/>
++ <target dir='/mnt/antananarivo'/>
++ </filesystem>
++ <filesystem type='ram'>
++ <source usage='1024' units='KiB'/>
++ <target dir='/mnt/ouagadougou'/>
++ </filesystem>
++ <console type='pty'>
++ <target type='lxc' port='0'/>
++ </console>
++ </devices>
++</domain>
+diff --git a/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
+new file mode 100644
+index 0000000..d2369a2
+--- /dev/null
++++ b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml
+@@ -0,0 +1,33 @@
++<domain type='lxc'>
++ <name>demo</name>
++ <uuid>8369f1ac-7e46-e869-4ca5-759d51478066</uuid>
++ <memory unit='KiB'>500000</memory>
++ <currentMemory unit='KiB'>500000</currentMemory>
++ <vcpu placement='static'>1</vcpu>
++ <os>
++ <type arch='x86_64'>exe</type>
++ <init>/bin/sh</init>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/libvirt_lxc</emulator>
++ <filesystem type='ram' accessmode='passthrough'>
++ <source usage='1048576' units='KiB'/>
++ <target dir='/mnt/mississippi'/>
++ </filesystem>
++ <filesystem type='ram' accessmode='passthrough'>
++ <source usage='1024' units='KiB'/>
++ <target dir='/mnt/antananarivo'/>
++ </filesystem>
++ <filesystem type='ram' accessmode='passthrough'>
++ <source usage='1024' units='KiB'/>
++ <target dir='/mnt/ouagadougou'/>
++ </filesystem>
++ <console type='pty'>
++ <target type='lxc' port='0'/>
++ </console>
++ </devices>
++</domain>
+diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
+index ca05d29..f8b5959 100644
+--- a/tests/lxcxml2xmltest.c
++++ b/tests/lxcxml2xmltest.c
+@@ -131,6 +131,7 @@ mymain(void)
+ DO_TEST("systemd");
+ DO_TEST("hostdev");
+ DO_TEST("disk-formats");
++ DO_TEST_DIFFERENT("filesystem-ram");
+
+ virObjectUnref(caps);
+ virObjectUnref(xmlopt);
+--
+1.8.3.2
+
--- /dev/null
+From 58fab1b319adbb2204df5eca88109426ed867d8e Mon Sep 17 00:00:00 2001
+Message-Id: <58fab1b319adbb2204df5eca88109426ed867d8e.1381871412.git.jdenemar@redhat.com>
+From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
+Date: Mon, 14 Oct 2013 16:45:16 +0100
+Subject: [PATCH] LXC: workaround machined uncleaned data with containers
+ running systemd.
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+The problem is described by [0] but its effect on libvirt is that
+starting a container with a full distro running systemd after having
+stopped it simply fails.
+
+The container cleanup now calls the machined Terminate function to make
+sure that everything is in order for the next run.
+
+ [0]: https://bugs.freedesktop.org/show_bug.cgi?id=68370
+
+(cherry picked from commit bd773e74f0d1d1b9ebbfcaa645178316b4f2265c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 2 ++
+ src/lxc/lxc_process.c | 8 +++++
+ src/util/virsystemd.c | 80 +++++++++++++++++++++++++++++++++++++++++-------
+ src/util/virsystemd.h | 8 +++++
+ tests/virsystemdtest.c | 28 +++++++++++++++++
+ 5 files changed, 115 insertions(+), 11 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 47e989c..d9561b8 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1938,8 +1938,10 @@ virSysinfoSetup;
+
+ # util/virsystemd.h
+ virSystemdCreateMachine;
++virSystemdMakeMachineName;
+ virSystemdMakeScopeName;
+ virSystemdMakeSliceName;
++virSystemdTerminateMachine;
+
+
+ # util/virthread.h
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index 47e6dd7..724ffa9 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -50,6 +50,7 @@
+ #include "virstring.h"
+ #include "viratomic.h"
+ #include "virprocess.h"
++#include "virsystemd.h"
+
+ #define VIR_FROM_THIS VIR_FROM_LXC
+
+@@ -209,6 +210,13 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
+ virCgroupFree(&priv->cgroup);
+ }
+
++ /* Get machined to terminate the machine as it may not have cleaned it
++ * properly. See https://bugs.freedesktop.org/show_bug.cgi?id=68370 for
++ * the bug we are working around here.
++ */
++ virSystemdTerminateMachine(vm->def->name, "lxc", true);
++
++
+ /* now that we know it's stopped call the hook if present */
+ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
+ char *xml = virDomainDefFormat(vm->def, 0);
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index e72b7f0..1ba37cc 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -116,6 +116,27 @@ char *virSystemdMakeSliceName(const char *partition)
+ return virBufferContentAndReset(&buf);
+ }
+
++char *virSystemdMakeMachineName(const char *name,
++ const char *drivername,
++ bool privileged)
++{
++ char *machinename = NULL;
++ char *username = NULL;
++ if (privileged) {
++ if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0)
++ goto cleanup;
++ } else {
++ if (!(username = virGetUserName(geteuid())))
++ goto cleanup;
++ if (virAsprintf(&machinename, "%s-%s-%s", username, drivername, name) < 0)
++ goto cleanup;
++ }
++
++cleanup:
++ VIR_FREE(username);
++
++ return machinename;
++}
+
+ /**
+ * virSystemdCreateMachine:
+@@ -142,7 +163,6 @@ int virSystemdCreateMachine(const char *name,
+ DBusConnection *conn;
+ char *machinename = NULL;
+ char *creatorname = NULL;
+- char *username = NULL;
+ char *slicename = NULL;
+
+ ret = virDBusIsServiceEnabled("org.freedesktop.machine1");
+@@ -152,15 +172,8 @@ int virSystemdCreateMachine(const char *name,
+ conn = virDBusGetSystemBus();
+
+ ret = -1;
+- if (privileged) {
+- if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0)
+- goto cleanup;
+- } else {
+- if (!(username = virGetUserName(geteuid())))
+- goto cleanup;
+- if (virAsprintf(&machinename, "%s-%s-%s", username, drivername, name) < 0)
+- goto cleanup;
+- }
++ if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged)))
++ goto cleanup;
+
+ if (virAsprintf(&creatorname, "libvirt-%s", drivername) < 0)
+ goto cleanup;
+@@ -236,9 +249,54 @@ int virSystemdCreateMachine(const char *name,
+ ret = 0;
+
+ cleanup:
+- VIR_FREE(username);
+ VIR_FREE(creatorname);
+ VIR_FREE(machinename);
+ VIR_FREE(slicename);
+ return ret;
+ }
++
++int virSystemdTerminateMachine(const char *name,
++ const char *drivername,
++ bool privileged)
++{
++ int ret;
++ DBusConnection *conn;
++ char *machinename = NULL;
++
++ ret = virDBusIsServiceEnabled("org.freedesktop.machine1");
++ if (ret < 0)
++ return ret;
++
++ conn = virDBusGetSystemBus();
++
++ ret = -1;
++ if (!(machinename = virSystemdMakeMachineName(name, drivername, privileged)))
++ goto cleanup;
++
++ /*
++ * The systemd DBus API we're invoking has the
++ * following signature
++ *
++ * TerminateMachine(in s name);
++ *
++ * @name a host unique name for the machine. shows up
++ * in 'ps' listing & similar
++ */
++
++ VIR_DEBUG("Attempting to terminate machine via systemd");
++ if (virDBusCallMethod(conn,
++ NULL,
++ "org.freedesktop.machine1",
++ "/org/freedesktop/machine1",
++ "org.freedesktop.machine1.Manager",
++ "TerminateMachine",
++ "s",
++ machinename) < 0)
++ goto cleanup;
++
++ ret = 0;
++
++cleanup:
++ VIR_FREE(machinename);
++ return ret;
++}
+diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h
+index 414ae5a..d9845e1 100644
+--- a/src/util/virsystemd.h
++++ b/src/util/virsystemd.h
+@@ -29,6 +29,10 @@ char *virSystemdMakeScopeName(const char *name,
+ const char *slicename);
+ char *virSystemdMakeSliceName(const char *partition);
+
++char *virSystemdMakeMachineName(const char *name,
++ const char *drivername,
++ bool privileged);
++
+ int virSystemdCreateMachine(const char *name,
+ const char *drivername,
+ bool privileged,
+@@ -38,4 +42,8 @@ int virSystemdCreateMachine(const char *name,
+ bool iscontainer,
+ const char *partition);
+
++int virSystemdTerminateMachine(const char *name,
++ const char *drivername,
++ bool privileged);
++
+ #endif /* __VIR_SYSTEMD_H__ */
+diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c
+index 7dc7520..b314013 100644
+--- a/tests/virsystemdtest.c
++++ b/tests/virsystemdtest.c
+@@ -51,6 +51,18 @@ static int testCreateContainer(const void *opaque ATTRIBUTE_UNUSED)
+ return 0;
+ }
+
++static int testTerminateContainer(const void *opaque ATTRIBUTE_UNUSED)
++{
++ if (virSystemdTerminateMachine("demo",
++ "lxc",
++ true) < 0) {
++ fprintf(stderr, "%s", "Failed to terminate LXC machine\n");
++ return -1;
++ }
++
++ return 0;
++}
++
+ static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED)
+ {
+ unsigned char uuid[VIR_UUID_BUFLEN] = {
+@@ -74,6 +86,18 @@ static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED)
+ return 0;
+ }
+
++static int testTerminateMachine(const void *opaque ATTRIBUTE_UNUSED)
++{
++ if (virSystemdTerminateMachine("demo",
++ "qemu",
++ false) < 0) {
++ fprintf(stderr, "%s", "Failed to terminate KVM machine\n");
++ return -1;
++ }
++
++ return 0;
++}
++
+ static int testCreateNoSystemd(const void *opaque ATTRIBUTE_UNUSED)
+ {
+ unsigned char uuid[VIR_UUID_BUFLEN] = {
+@@ -181,8 +205,12 @@ mymain(void)
+
+ if (virtTestRun("Test create container ", 1, testCreateContainer, NULL) < 0)
+ ret = -1;
++ if (virtTestRun("Test terminate container ", 1, testTerminateContainer, NULL) < 0)
++ ret = -1;
+ if (virtTestRun("Test create machine ", 1, testCreateMachine, NULL) < 0)
+ ret = -1;
++ if (virtTestRun("Test terminate machine ", 1, testTerminateMachine, NULL) < 0)
++ ret = -1;
+ if (virtTestRun("Test create no systemd ", 1, testCreateNoSystemd, NULL) < 0)
+ ret = -1;
+ if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
+--
+1.8.3.2
+
--- /dev/null
+From 84d64b72a8006ca821b03f1a901266773e56e07a Mon Sep 17 00:00:00 2001
+Message-Id: <84d64b72a8006ca821b03f1a901266773e56e07a.1381871412.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:19 +0100
+Subject: [PATCH] Make LXC controller use a private dbus connection & close it
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=998365
+
+The LXC controller uses dbus to talk to systemd to create
+cgroups. This means that each LXC controller instance has
+a dbus connection. The DBus daemon is limited to 256
+connections by default and we want to be able to run many
+1000 of containers.
+
+While the dbus limit could be raised in the config files,
+it is simpler to make libvirt LXC controller close its
+dbus connection once everything is configured.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit ae9a0485ae52aea6c7773176a15228abaa5de680)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/Makefile.am | 1 +
+ src/lxc/lxc_controller.c | 9 +++++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 66bb6b9..5976a68 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -2333,6 +2333,7 @@ libvirt_lxc_CFLAGS = \
+ $(PIE_CFLAGS) \
+ $(LIBNL_CFLAGS) \
+ $(FUSE_CFLAGS) \
++ $(DBUS_CFLAGS) \
+ $(NULL)
+ if WITH_BLKID
+ libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index ed73ab0..5802851 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -64,6 +64,7 @@
+ #include "virrandom.h"
+ #include "virprocess.h"
+ #include "virnuma.h"
++#include "virdbus.h"
+ #include "rpc/virnetserver.h"
+ #include "virstring.h"
+
+@@ -2200,6 +2201,12 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
+ if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0)
+ goto cleanup;
+
++ /* We must not hold open a dbus connection for life
++ * of LXC instance, since dbus-daemon is limited to
++ * only a few 100 connections by default
++ */
++ virDBusCloseSystemBus();
++
+ rc = virLXCControllerMain(ctrl);
+
+ virLXCControllerEventSendExit(ctrl, rc);
+@@ -2351,6 +2358,8 @@ int main(int argc, char *argv[])
+
+ virEventRegisterDefaultImpl();
+
++ virDBusSetSharedBus(false);
++
+ if (!(ctrl = virLXCControllerNew(name)))
+ goto cleanup;
+
+--
+1.8.3.2
+
--- /dev/null
+From f012f3f9db0db87efd7f6b8ee7d871932eaa918b Mon Sep 17 00:00:00 2001
+Message-Id: <f012f3f9db0db87efd7f6b8ee7d871932eaa918b.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:36:51 +0100
+Subject: [PATCH] Make check for /dev/loop device names stricter to avoid
+ /dev/loop-control
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=924815
+
+Recentish (2011) kernels introduced a new device called /dev/loop-control,
+which causes libvirt's detection of loop devices to get confused
+since it only checks for a prefix of 'loop'. Also check that the
+next character is a digit
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 68a9637b2c0655c23713965f6444f66af95fbff3)
+---
+ src/util/virfile.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 8f0eec3..2b07ac9 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -546,7 +546,11 @@ static int virFileLoopDeviceOpen(char **dev_name)
+
+ errno = 0;
+ while ((de = readdir(dh)) != NULL) {
+- if (!STRPREFIX(de->d_name, "loop"))
++ /* Checking 'loop' prefix is insufficient, since
++ * new kernels have a dev named 'loop-control'
++ */
++ if (!STRPREFIX(de->d_name, "loop") ||
++ !c_isdigit(de->d_name[4]))
+ continue;
+
+ if (virAsprintf(&looppath, "/dev/%s", de->d_name) < 0)
+--
+1.8.3.2
+
--- /dev/null
+From 4799286cbbf12b5d2734ae79d0580d92b8d3b100 Mon Sep 17 00:00:00 2001
+Message-Id: <4799286cbbf12b5d2734ae79d0580d92b8d3b100.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:50 +0000
+Subject: [PATCH] Make virCommand env handling robust in setuid env
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+When running setuid, we must be careful about what env vars
+we allow commands to inherit from us. Replace the
+virCommandAddEnvPass function with two new ones which do
+filtering
+
+ virCommandAddEnvPassAllowSUID
+ virCommandAddEnvPassBlockSUID
+
+And make virCommandAddEnvPassCommon use the appropriate
+ones
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 9b8f307c6ad002a17a0510513883d06395636793)
+
+Conflicts:
+ src/qemu/qemu_command.c
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 3 ++-
+ src/lxc/lxc_process.c | 2 +-
+ src/qemu/qemu_command.c | 6 +++---
+ src/rpc/virnetsocket.c | 16 ++++++++--------
+ src/util/vircommand.c | 50 +++++++++++++++++++++++++++++++++++++-----------
+ src/util/vircommand.h | 8 ++++++--
+ tests/commandtest.c | 8 ++++----
+ 7 files changed, 63 insertions(+), 30 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 374a332..ca6275c 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1237,7 +1237,8 @@ virCommandAddArgSet;
+ virCommandAddEnvBuffer;
+ virCommandAddEnvFormat;
+ virCommandAddEnvPair;
+-virCommandAddEnvPass;
++virCommandAddEnvPassAllowSUID;
++virCommandAddEnvPassBlockSUID;
+ virCommandAddEnvPassCommon;
+ virCommandAddEnvString;
+ virCommandAllowCap;
+diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
+index a5f1f35..a88fb4d 100644
+--- a/src/lxc/lxc_process.c
++++ b/src/lxc/lxc_process.c
+@@ -740,7 +740,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
+ cmd = virCommandNew(vm->def->emulator);
+
+ /* The controller may call ip command, so we have to retain PATH. */
+- virCommandAddEnvPass(cmd, "PATH");
++ virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
+
+ virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d",
+ virLogGetDefaultPriority());
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 78f07c8..0292b72 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -6997,7 +6997,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
+ * security issues and might not work when using VNC.
+ */
+ if (cfg->vncAllowHostAudio)
+- virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
++ virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
+ else
+ virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
+
+@@ -7242,8 +7242,8 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
+ * use QEMU's host audio drivers, possibly SDL too
+ * User can set these two before starting libvirtd
+ */
+- virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
+- virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
++ virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "SDL_AUDIODRIVER", NULL);
+
+ /* New QEMU has this flag to let us explicitly ask for
+ * SDL graphics. This is better than relying on the
+diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
+index ae81512..fcd41ca 100644
+--- a/src/rpc/virnetsocket.c
++++ b/src/rpc/virnetsocket.c
+@@ -127,9 +127,9 @@ static int virNetSocketForkDaemon(const char *binary)
+ NULL);
+
+ virCommandAddEnvPassCommon(cmd);
+- virCommandAddEnvPass(cmd, "XDG_CACHE_HOME");
+- virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME");
+- virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR");
++ virCommandAddEnvPassBlockSUID(cmd, "XDG_CACHE_HOME", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "XDG_CONFIG_HOME", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "XDG_RUNTIME_DIR", NULL);
+ virCommandClearCaps(cmd);
+ virCommandDaemonize(cmd);
+ ret = virCommandRun(cmd, NULL);
+@@ -680,11 +680,11 @@ int virNetSocketNewConnectSSH(const char *nodename,
+
+ cmd = virCommandNew(binary ? binary : "ssh");
+ virCommandAddEnvPassCommon(cmd);
+- virCommandAddEnvPass(cmd, "KRB5CCNAME");
+- virCommandAddEnvPass(cmd, "SSH_AUTH_SOCK");
+- virCommandAddEnvPass(cmd, "SSH_ASKPASS");
+- virCommandAddEnvPass(cmd, "DISPLAY");
+- virCommandAddEnvPass(cmd, "XAUTHORITY");
++ virCommandAddEnvPassBlockSUID(cmd, "KRB5CCNAME", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "SSH_AUTH_SOCK", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "SSH_ASKPASS", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "XAUTHORITY", NULL);
+ virCommandClearCaps(cmd);
+
+ if (service)
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index 00ff69a..fca0e09 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -1247,21 +1247,49 @@ virCommandAddEnvBuffer(virCommandPtr cmd, virBufferPtr buf)
+
+
+ /**
+- * virCommandAddEnvPass:
++ * virCommandAddEnvPassAllowSUID:
+ * @cmd: the command to modify
+ * @name: the name to look up in current environment
+ *
+ * Pass an environment variable to the child
+ * using current process' value
++ *
++ * Allow to be passed even if setuid
++ */
++void
++virCommandAddEnvPassAllowSUID(virCommandPtr cmd, const char *name)
++{
++ const char *value;
++ if (!cmd || cmd->has_error)
++ return;
++
++ value = virGetEnvAllowSUID(name);
++ if (value)
++ virCommandAddEnvPair(cmd, name, value);
++}
++
++
++/**
++ * virCommandAddEnvPassBlockSUID:
++ * @cmd: the command to modify
++ * @name: the name to look up in current environment
++ * @defvalue: value to return if running setuid, may be NULL
++ *
++ * Pass an environment variable to the child
++ * using current process' value.
++ *
++ * Do not pass if running setuid
+ */
+ void
+-virCommandAddEnvPass(virCommandPtr cmd, const char *name)
++virCommandAddEnvPassBlockSUID(virCommandPtr cmd, const char *name, const char *defvalue)
+ {
+- char *value;
++ const char *value;
+ if (!cmd || cmd->has_error)
+ return;
+
+- value = getenv(name);
++ value = virGetEnvBlockSUID(name);
++ if (!value)
++ value = defvalue;
+ if (value)
+ virCommandAddEnvPair(cmd, name, value);
+ }
+@@ -1286,13 +1314,13 @@ virCommandAddEnvPassCommon(virCommandPtr cmd)
+
+ virCommandAddEnvPair(cmd, "LC_ALL", "C");
+
+- virCommandAddEnvPass(cmd, "LD_PRELOAD");
+- virCommandAddEnvPass(cmd, "LD_LIBRARY_PATH");
+- virCommandAddEnvPass(cmd, "PATH");
+- virCommandAddEnvPass(cmd, "HOME");
+- virCommandAddEnvPass(cmd, "USER");
+- virCommandAddEnvPass(cmd, "LOGNAME");
+- virCommandAddEnvPass(cmd, "TMPDIR");
++ virCommandAddEnvPassBlockSUID(cmd, "LD_PRELOAD", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "LD_LIBRARY_PATH", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
++ virCommandAddEnvPassBlockSUID(cmd, "HOME", NULL);
++ virCommandAddEnvPassAllowSUID(cmd, "USER");
++ virCommandAddEnvPassAllowSUID(cmd, "LOGNAME");
++ virCommandAddEnvPassBlockSUID(cmd, "TMPDIR", NULL);
+ }
+
+ /**
+diff --git a/src/util/vircommand.h b/src/util/vircommand.h
+index c619e06..e977f93 100644
+--- a/src/util/vircommand.h
++++ b/src/util/vircommand.h
+@@ -99,8 +99,12 @@ void virCommandAddEnvString(virCommandPtr cmd,
+ void virCommandAddEnvBuffer(virCommandPtr cmd,
+ virBufferPtr buf);
+
+-void virCommandAddEnvPass(virCommandPtr cmd,
+- const char *name) ATTRIBUTE_NONNULL(2);
++void virCommandAddEnvPassBlockSUID(virCommandPtr cmd,
++ const char *name,
++ const char *defvalue) ATTRIBUTE_NONNULL(2);
++
++void virCommandAddEnvPassAllowSUID(virCommandPtr cmd,
++ const char *name) ATTRIBUTE_NONNULL(2);
+
+ void virCommandAddEnvPassCommon(virCommandPtr cmd);
+
+diff --git a/tests/commandtest.c b/tests/commandtest.c
+index eeb6d1e..1acc8d9 100644
+--- a/tests/commandtest.c
++++ b/tests/commandtest.c
+@@ -294,8 +294,8 @@ static int test6(const void *unused ATTRIBUTE_UNUSED)
+ {
+ virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
+
+- virCommandAddEnvPass(cmd, "DISPLAY");
+- virCommandAddEnvPass(cmd, "DOESNOTEXIST");
++ virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virErrorPtr err = virGetLastError();
+@@ -319,8 +319,8 @@ static int test7(const void *unused ATTRIBUTE_UNUSED)
+ virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
+
+ virCommandAddEnvPassCommon(cmd);
+- virCommandAddEnvPass(cmd, "DISPLAY");
+- virCommandAddEnvPass(cmd, "DOESNOTEXIST");
++ virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
++ virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virErrorPtr err = virGetLastError();
+--
+1.8.4.2
+
--- /dev/null
+From 53ff78bcd85b2e8df67edd1ecf2c70de4c9c96fe Mon Sep 17 00:00:00 2001
+Message-Id: <53ff78bcd85b2e8df67edd1ecf2c70de4c9c96fe.1382534061.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 11:24:33 +0200
+Subject: [PATCH] Migration: Introduce VIR_MIGRATE_PARAM_LISTEN_ADDRESS
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015215
+
+The parameter allows overriding default listen address for '-incoming'
+cmd line argument on destination.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 72aafe9c812e17547df185abebb3fe4e56d0d982)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ include/libvirt/libvirt.h.in | 10 ++++++++++
+ tools/virsh-domain.c | 11 +++++++++++
+ tools/virsh.pod | 10 ++++++++--
+ 3 files changed, 29 insertions(+), 2 deletions(-)
+
+diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
+index 52ac95d..1bc6624 100644
+--- a/include/libvirt/libvirt.h.in
++++ b/include/libvirt/libvirt.h.in
+@@ -1270,6 +1270,16 @@ typedef enum {
+ */
+ #define VIR_MIGRATE_PARAM_GRAPHICS_URI "graphics_uri"
+
++/**
++ * VIR_MIGRATE_PARAM_LISTEN_ADDRESS:
++ *
++ * virDomainMigrate* params field: The listen address that hypervisor on the
++ * destination side should bind to for incoming migration. Both, IPv4 and IPv6
++ * addresses are accepted as well as hostnames (the resolving is done on
++ * destination). Some hypervisors do not support this feature an will return an
++ * error if this field is used.
++ */
++#define VIR_MIGRATE_PARAM_LISTEN_ADDRESS "listen_address"
+
+ /* Domain migration. */
+ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index bf5f425..b4faa69 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -8405,6 +8405,10 @@ static const vshCmdOptDef opts_migrate[] = {
+ .type = VSH_OT_DATA,
+ .help = N_("graphics URI to be used for seamless graphics migration")
+ },
++ {.name = "listen-address",
++ .type = VSH_OT_DATA,
++ .help = N_("listen address that destination should bind to for incoming migration")
++ },
+ {.name = "dname",
+ .type = VSH_OT_DATA,
+ .help = N_("rename to new name during migration (if supported)")
+@@ -8461,6 +8465,13 @@ doMigrate(void *opaque)
+ VIR_MIGRATE_PARAM_GRAPHICS_URI, opt) < 0)
+ goto save_error;
+
++ if (vshCommandOptStringReq(ctl, cmd, "listen-address", &opt) < 0)
++ goto out;
++ if (opt &&
++ virTypedParamsAddString(¶ms, &nparams, &maxparams,
++ VIR_MIGRATE_PARAM_LISTEN_ADDRESS, opt) < 0)
++ goto save_error;
++
+ if (vshCommandOptStringReq(ctl, cmd, "dname", &opt) < 0)
+ goto out;
+ if (opt &&
+diff --git a/tools/virsh.pod b/tools/virsh.pod
+index 3ff6da1..808a90c 100644
+--- a/tools/virsh.pod
++++ b/tools/virsh.pod
+@@ -1070,8 +1070,8 @@ stats.
+ [I<--persistent>] [I<--undefinesource>] [I<--suspend>] [I<--copy-storage-all>]
+ [I<--copy-storage-inc>] [I<--change-protection>] [I<--unsafe>] [I<--verbose>]
+ [I<--compressed>] [I<--abort-on-error>]
+-I<domain> I<desturi> [I<migrateuri>] [I<graphicsuri>] [I<dname>]
+-[I<--timeout> B<seconds>] [I<--xml> B<file>]
++I<domain> I<desturi> [I<migrateuri>] [I<graphicsuri>] [I<listen-address>]
++[I<dname>] [I<--timeout> B<seconds>] [I<--xml> B<file>]
+
+ Migrate domain to another host. Add I<--live> for live migration; <--p2p>
+ for peer-2-peer migration; I<--direct> for direct migration; or I<--tunnelled>
+@@ -1178,6 +1178,12 @@ specific parameters separated by '&'. Currently recognized parameters are
+
+ spice://target.host.com:1234/?tlsPort=4567
+
++Optional I<listen-address> sets the listen address that hypervisor on the
++destination side should bind to for incoming migration. Both IPv4 and IPv6
++addresses are accepted as well as hostnames (the resolving is done on
++destination). Some hypervisors do not support this feature and will return an
++error if this parameter is used.
++
+ =item B<migrate-setmaxdowntime> I<domain> I<downtime>
+
+ Set maximum tolerable downtime for a domain which is being live-migrated to
+--
+1.8.4
+
--- /dev/null
+From dc8bdc9729fda24e5a12e78d713f956e071c0492 Mon Sep 17 00:00:00 2001
+Message-Id: <dc8bdc9729fda24e5a12e78d713f956e071c0492.1380112456.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 20 Sep 2013 13:07:49 +0100
+Subject: [PATCH] Move array of mounts out of lxcContainerMountBasicFS
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=872648
+
+Move the array of basic mounts out of the lxcContainerMountBasicFS
+function, to a global variable. This is to allow it to be referenced
+by other methods wanting to know what the basic mount paths are.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit f27f5f7eddf531159d791a2b5ac438ca011b5f26)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/lxc/lxc_container.c | 79 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 42 insertions(+), 37 deletions(-)
+
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index c41ab40..d3154d8 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -750,45 +750,50 @@ err:
+ }
+
+
+-static int lxcContainerMountBasicFS(bool userns_enabled)
+-{
+- const struct {
+- const char *src;
+- const char *dst;
+- const char *type;
+- const char *opts;
+- int mflags;
+- } mnts[] = {
+- /* When we want to make a bind mount readonly, for unknown reasons,
+- * it is currently necessary to bind it once, and then remount the
+- * bind with the readonly flag. If this is not done, then the original
+- * mount point in the main OS becomes readonly too which is not what
+- * we want. Hence some things have two entries here.
+- */
+- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
+- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+- { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+- { "sysfs", "/sys", "sysfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+- { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+- { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
++typedef struct {
++ const char *src;
++ const char *dst;
++ const char *type;
++ const char *opts;
++ int mflags;
++} virLXCBasicMountInfo;
++
++static const virLXCBasicMountInfo lxcBasicMounts[] = {
++ /* When we want to make a bind mount readonly, for unknown reasons,
++ * it is currently necessary to bind it once, and then remount the
++ * bind with the readonly flag. If this is not done, then the original
++ * mount point in the main OS becomes readonly too which is not what
++ * we want. Hence some things have two entries here.
++ */
++ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
++ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
++ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
++ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
++ { "sysfs", "/sys", "sysfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
++ { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
++ { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+ #if WITH_SELINUX
+- { SELINUX_MOUNT, SELINUX_MOUNT, "selinuxfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
+- { SELINUX_MOUNT, SELINUX_MOUNT, NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
++ { SELINUX_MOUNT, SELINUX_MOUNT, "selinuxfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
++ { SELINUX_MOUNT, SELINUX_MOUNT, NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
+ #endif
+- };
++};
++
++
++static int lxcContainerMountBasicFS(bool userns_enabled)
++{
+ size_t i;
+ int rc = -1;
+
+ VIR_DEBUG("Mounting basic filesystems");
+
+- for (i = 0; i < ARRAY_CARDINALITY(mnts); i++) {
++ for (i = 0; i < ARRAY_CARDINALITY(lxcBasicMounts); i++) {
++ virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i];
+ const char *srcpath = NULL;
+
+ VIR_DEBUG("Processing %s -> %s",
+- mnts[i].src, mnts[i].dst);
++ mnt->src, mnt->dst);
+
+- srcpath = mnts[i].src;
++ srcpath = mnt->src;
+
+ /* Skip if mount doesn't exist in source */
+ if ((srcpath[0] == '/') &&
+@@ -796,34 +801,34 @@ static int lxcContainerMountBasicFS(bool userns_enabled)
+ continue;
+
+ #if WITH_SELINUX
+- if (STREQ(mnts[i].src, SELINUX_MOUNT) &&
++ if (STREQ(mnt->src, SELINUX_MOUNT) &&
+ !is_selinux_enabled())
+ continue;
+ #endif
+
+- if (STREQ(mnts[i].src, "securityfs") && userns_enabled)
++ if (STREQ(mnt->src, "securityfs") && userns_enabled)
+ continue;
+
+- if (virFileMakePath(mnts[i].dst) < 0) {
++ if (virFileMakePath(mnt->dst) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mkdir %s"),
+- mnts[i].src);
++ mnt->src);
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Mount %s on %s type=%s flags=%x, opts=%s",
+- srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts);
+- if (mount(srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts) < 0) {
++ srcpath, mnt->dst, mnt->type, mnt->mflags, mnt->opts);
++ if (mount(srcpath, mnt->dst, mnt->type, mnt->mflags, mnt->opts) < 0) {
+ #if WITH_SELINUX
+- if (STREQ(mnts[i].src, SELINUX_MOUNT) &&
++ if (STREQ(mnt->src, SELINUX_MOUNT) &&
+ (errno == EINVAL || errno == EPERM))
+ continue;
+ #endif
+
+ virReportSystemError(errno,
+ _("Failed to mount %s on %s type %s flags=%x opts=%s"),
+- srcpath, mnts[i].dst, NULLSTR(mnts[i].type),
+- mnts[i].mflags, NULLSTR(mnts[i].opts));
++ srcpath, mnt->dst, NULLSTR(mnt->type),
++ mnt->mflags, NULLSTR(mnt->opts));
+ goto cleanup;
+ }
+ }
+--
+1.8.3.2
+
--- /dev/null
+From ebad72b771d17033f03c00bcdc5bb24db5116862 Mon Sep 17 00:00:00 2001
+Message-Id: <ebad72b771d17033f03c00bcdc5bb24db5116862.1383321464.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:42 +0000
+Subject: [PATCH] Only allow 'stderr' log output when running setuid
+
+CVE-2013-4400
+
+We must not allow file/syslog/journald log outputs when running
+setuid since they can be abused to do bad things. In particular
+the 'file' output can be used to overwrite files.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 8c3586ea755c40d5e01b22cb7b5c1e668cdec994)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virlog.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/src/util/virlog.c b/src/util/virlog.c
+index 6f791ad..694da89 100644
+--- a/src/util/virlog.c
++++ b/src/util/virlog.c
+@@ -1324,6 +1324,9 @@ int virLogPriorityFromSyslog(int priority ATTRIBUTE_UNUSED)
+ * Multiple output can be defined in a single @output, they just need to be
+ * separated by spaces.
+ *
++ * If running in setuid mode, then only the 'stderr' output will
++ * be allowed
++ *
+ * Returns the number of output parsed and installed or -1 in case of error
+ */
+ int
+@@ -1335,6 +1338,7 @@ virLogParseOutputs(const char *outputs)
+ virLogPriority prio;
+ int ret = -1;
+ int count = 0;
++ bool isSUID = virIsSUID();
+
+ if (cur == NULL)
+ return -1;
+@@ -1354,6 +1358,8 @@ virLogParseOutputs(const char *outputs)
+ if (virLogAddOutputToStderr(prio) == 0)
+ count++;
+ } else if (STREQLEN(cur, "syslog", 6)) {
++ if (isSUID)
++ goto cleanup;
+ cur += 6;
+ if (*cur != ':')
+ goto cleanup;
+@@ -1371,6 +1377,8 @@ virLogParseOutputs(const char *outputs)
+ VIR_FREE(name);
+ #endif /* HAVE_SYSLOG_H */
+ } else if (STREQLEN(cur, "file", 4)) {
++ if (isSUID)
++ goto cleanup;
+ cur += 4;
+ if (*cur != ':')
+ goto cleanup;
+@@ -1391,6 +1399,8 @@ virLogParseOutputs(const char *outputs)
+ VIR_FREE(name);
+ VIR_FREE(abspath);
+ } else if (STREQLEN(cur, "journald", 8)) {
++ if (isSUID)
++ goto cleanup;
+ cur += 8;
+ #if USE_JOURNALD
+ if (virLogAddOutputToJournald(prio) == 0)
+--
+1.8.4.2
+
--- /dev/null
+From 340225143c8f389cb12de610f6208fa643b31fbb Mon Sep 17 00:00:00 2001
+Message-Id: <340225143c8f389cb12de610f6208fa643b31fbb.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:53 +0000
+Subject: [PATCH] Only allow the UNIX transport in remote driver when setuid
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+We don't know enough about quality of external libraries used
+for non-UNIX transports, nor do we want to spawn external
+commands when setuid. Restrict to the bare minimum which is
+UNIX transport for local usage. Users shouldn't need to be
+running setuid if connecting to remote hypervisors in any
+case.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit e22b0232c7b94aefaef87c52c4d626fa532fcce3)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt.c | 6 ++++++
+ src/remote/remote_driver.c | 14 ++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 0a024a9..8a3cc42 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -1135,6 +1135,12 @@ do_open(const char *name,
+ if (name && name[0] == '\0')
+ name = NULL;
+
++ if (!name && virIsSUID()) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("An explicit URI must be provided when setuid"));
++ goto failed;
++ }
++
+ /*
+ * If no URI is passed, then check for an environment string if not
+ * available probe the compiled in drivers to find a default hypervisor
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 67daf79..b6b629c 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -488,6 +488,20 @@ doRemoteOpen(virConnectPtr conn,
+ transport = trans_unix;
+ }
+
++ /*
++ * We don't want to be executing external programs in setuid mode,
++ * so this rules out 'ext' and 'ssh' transports. Exclude libssh
++ * and tls too, since we're not confident the libraries are safe
++ * for setuid usage. Just allow UNIX sockets, since that does
++ * not require any external libraries or command execution
++ */
++ if (virIsSUID() &&
++ transport != trans_unix) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Only Unix socket URI transport is allowed in setuid mode"));
++ return VIR_DRV_OPEN_ERROR;
++ }
++
+ /* Local variables which we will initialize. These can
+ * get freed in the failed: path.
+ */
+--
+1.8.4.2
+
--- /dev/null
+From 92ee92d29a0150c064a7831d1316d7b1f102bc36 Mon Sep 17 00:00:00 2001
+Message-Id: <92ee92d29a0150c064a7831d1316d7b1f102bc36.1379193140.git.jdenemar@redhat.com>
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Sun, 1 Sep 2013 08:50:58 +0200
+Subject: [PATCH] Pass AM_LDFLAGS to driver modules too
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006299
+
+This gives us a RO got, otherwise Debian's lintian complains:
+
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_qemu.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_storage.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_uml.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_vbox.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_nwfilter.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_storage.so
+W: libvirt-bin: hardening-no-relro usr/lib/libvirt/connection-driver/libvirt_driver_uml.so
+W: libvirt-sanlock: hardening-no-relro usr/lib/libvirt/lock-driver/sanlock.so
+(cherry picked from commit f1f0e53b0814aab3c093f1219da95c0f836cdf4a)
+---
+ src/Makefile.am | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index b049895..1b734e0 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -991,7 +991,7 @@ libvirt_driver_xen_la_LIBADD = libvirt_driver_xen_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_xen.la
+ libvirt_driver_xen_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_xen_la_LDFLAGS = -module -avoid-version
++libvirt_driver_xen_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_xen.la
+ # Stateful, so linked to daemon instead
+@@ -1041,7 +1041,7 @@ libvirt_driver_vbox_la_LIBADD = libvirt_driver_vbox_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_vbox.la
+ libvirt_driver_vbox_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_vbox_la_LDFLAGS = -module -avoid-version
++libvirt_driver_vbox_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_vbox.la
+ # GPLv2-only license requries that it be linked into
+@@ -1074,7 +1074,7 @@ libvirt_driver_libxl_la_LIBADD = libvirt_driver_libxl_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_libxl.la
+ libvirt_driver_libxl_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_libxl_la_LDFLAGS = -module -avoid-version
++libvirt_driver_libxl_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_libxl.la
+ # Stateful, so linked to daemon instead
+@@ -1099,7 +1099,7 @@ libvirt_driver_qemu_la_LIBADD = libvirt_driver_qemu_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_qemu.la
+ libvirt_driver_qemu_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_qemu_la_LDFLAGS = -module -avoid-version
++libvirt_driver_qemu_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_qemu.la
+ # Stateful, so linked to daemon instead
+@@ -1173,7 +1173,7 @@ libvirt_driver_uml_la_LIBADD = libvirt_driver_uml_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_uml.la
+ libvirt_driver_uml_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_uml_la_LDFLAGS = -module -avoid-version
++libvirt_driver_uml_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_uml.la
+ # Stateful, so linked to daemon instead
+@@ -1349,7 +1349,7 @@ libvirt_driver_storage_la_LIBADD = libvirt_driver_storage_impl.la
+ if WITH_DRIVER_MODULES
+ mod_LTLIBRARIES += libvirt_driver_storage.la
+ libvirt_driver_storage_la_LIBADD += ../gnulib/lib/libgnu.la
+-libvirt_driver_storage_la_LDFLAGS = -module -avoid-version
++libvirt_driver_storage_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ else
+ noinst_LTLIBRARIES += libvirt_driver_storage.la
+ # Stateful, so linked to daemon instead
+@@ -2104,7 +2104,7 @@ if WITH_SANLOCK
+ lockdriver_LTLIBRARIES += sanlock.la
+ sanlock_la_SOURCES = $(LOCK_DRIVER_SANLOCK_SOURCES)
+ sanlock_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS)
+-sanlock_la_LDFLAGS = -module -avoid-version
++sanlock_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
+ sanlock_la_LIBADD = -lsanlock_client \
+ ../gnulib/lib/libgnu.la
+
+--
+1.8.3.2
+
--- /dev/null
+From 4926fd0000728353fd0e26430398504e66af2899 Mon Sep 17 00:00:00 2001
+Message-Id: <4926fd0000728353fd0e26430398504e66af2899.1378475168.git.jdenemar@redhat.com>
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Tue, 3 Sep 2013 17:15:50 +0200
+Subject: [PATCH] Process virtlockd.conf instead of libvirtd.conf
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003685
+
+(cherry picked from commit 3e32544854d6dcbea19ee4aff46b48f7201099d3)
+---
+ src/locking/virtlockd.aug | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/locking/virtlockd.aug b/src/locking/virtlockd.aug
+index 9d20e72..4b3df9f 100644
+--- a/src/locking/virtlockd.aug
++++ b/src/locking/virtlockd.aug
+@@ -1,6 +1,6 @@
+-(* /etc/libvirt/libvirtd.conf *)
++(* /etc/libvirt/virtlockd.conf *)
+
+-module Libvirtd =
++module Virtlockd =
+ autoload xfm
+
+ let eol = del /[ \t]*\n/ "\n"
+--
+1.8.3.2
+
--- /dev/null
+From bc206c2eb3712871fb737c1b9968b043dc3c9724 Mon Sep 17 00:00:00 2001
+Message-Id: <bc206c2eb3712871fb737c1b9968b043dc3c9724.1377873640.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:16:14 +0100
+Subject: [PATCH] Prohibit unbounded arrays in XDR protocols
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1002667
+
+The use of <> is a security issue for RPC parameters, since a
+malicious client can set a huge array length causing arbitrary
+memory allocation in the daemon.
+
+It is also a robustness issue for RPC return values, because if
+the stream is corrupted, it can cause the client to also allocate
+arbitrary memory.
+
+Use a syntax-check rule to prohibit any use of <>
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit a4d1cfdc59ec18bfade96333cafd465dad7e40fb)
+---
+ cfg.mk | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/cfg.mk b/cfg.mk
+index c59d432..aa2e1a1 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -830,6 +830,12 @@ sc_prohibit_config_h_in_headers:
+ halt='headers should not include <config.h>' \
+ $(_sc_search_regexp)
+
++sc_prohibit_unbounded_arrays_in_rpc:
++ @prohibit='<>' \
++ in_vc_files='\.x$$' \
++ halt='Arrays in XDR must have a upper limit set for <NNN>' \
++ $(_sc_search_regexp)
++
+
+ # We don't use this feature of maint.mk.
+ prev_version_file = /dev/null
+--
+1.8.3.2
+
--- /dev/null
+From 3ff9f885135bd131b2e014a4caf3f5092fd6c21f Mon Sep 17 00:00:00 2001
+Message-Id: <3ff9f885135bd131b2e014a4caf3f5092fd6c21f.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 13:56:52 +0100
+Subject: [PATCH] Properly handle -h / -V for --help/--version aliases in
+ virtlockd/libvirtd
+
+https://bugzilla.redhat.com/show_bug.cgi?id=991494
+
+The virtlockd/libvirtd daemons had listed '?' as the short option
+for --help. getopt_long uses '?' for any unknown option. We want
+to be able to distinguish unknown options (which use EXIT_FAILURE)
+from correct usage of help (which should use EXIT_SUCCESS). Thus
+we should use 'h' as a short option for --help. Also add this to
+the man page docs
+
+The virtlockd/libvirtd daemons did not list any short option
+for the --version arg. Add -V as a valid short option, since
+-v is already used for --verbose.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 63ba687f2bb78bfe4df96eb3d68bf88f675f562c)
+---
+ daemon/libvirtd.c | 31 ++++++++++++++-----------------
+ daemon/libvirtd.pod.in | 4 ++++
+ src/locking/lock_daemon.c | 29 +++++++++++++----------------
+ src/locking/virtlockd.pod.in | 6 +++++-
+ 4 files changed, 36 insertions(+), 34 deletions(-)
+
+diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
+index 402b494..c9cd1a1 100644
+--- a/daemon/libvirtd.c
++++ b/daemon/libvirtd.c
+@@ -1038,12 +1038,13 @@ daemonUsage(const char *argv0, bool privileged)
+ " %s [options]\n"
+ "\n"
+ "Options:\n"
++ " -h | --help Display program help:\n"
+ " -v | --verbose Verbose messages.\n"
+ " -d | --daemon Run as a daemon & write PID file.\n"
+ " -l | --listen Listen for TCP/IP connections.\n"
+ " -t | --timeout <secs> Exit after timeout period.\n"
+ " -f | --config <file> Configuration file.\n"
+- " | --version Display version information.\n"
++ " -V | --version Display version information.\n"
+ " -p | --pid-file <file> Change name of PID file.\n"
+ "\n"
+ "libvirt management daemon:\n"),
+@@ -1098,10 +1099,6 @@ daemonUsage(const char *argv0, bool privileged)
+ }
+ }
+
+-enum {
+- OPT_VERSION = 129
+-};
+-
+ #define MAX_LISTEN 5
+ int main(int argc, char **argv) {
+ virNetServerPtr srv = NULL;
+@@ -1123,14 +1120,14 @@ int main(int argc, char **argv) {
+ mode_t old_umask;
+
+ struct option opts[] = {
+- { "verbose", no_argument, &verbose, 1},
+- { "daemon", no_argument, &godaemon, 1},
+- { "listen", no_argument, &ipsock, 1},
++ { "verbose", no_argument, &verbose, 'v'},
++ { "daemon", no_argument, &godaemon, 'd'},
++ { "listen", no_argument, &ipsock, 'l'},
+ { "config", required_argument, NULL, 'f'},
+ { "timeout", required_argument, NULL, 't'},
+ { "pid-file", required_argument, NULL, 'p'},
+- { "version", no_argument, NULL, OPT_VERSION },
+- { "help", no_argument, NULL, '?' },
++ { "version", no_argument, NULL, 'V' },
++ { "help", no_argument, NULL, 'h' },
+ {0, 0, 0, 0}
+ };
+
+@@ -1173,7 +1170,7 @@ int main(int argc, char **argv) {
+ int c;
+ char *tmp;
+
+- c = getopt_long(argc, argv, "ldf:p:t:v", opts, &optidx);
++ c = getopt_long(argc, argv, "ldf:p:t:vVh", opts, &optidx);
+
+ if (c == -1) {
+ break;
+@@ -1219,17 +1216,17 @@ int main(int argc, char **argv) {
+ }
+ break;
+
+- case OPT_VERSION:
++ case 'V':
+ daemonVersion(argv[0]);
+- return 0;
++ exit(EXIT_SUCCESS);
+
+- case '?':
++ case 'h':
+ daemonUsage(argv[0], privileged);
+- return 2;
++ exit(EXIT_SUCCESS);
+
++ case '?':
+ default:
+- VIR_ERROR(_("%s: internal error: unknown flag: %c"),
+- argv[0], c);
++ daemonUsage(argv[0], privileged);
+ exit(EXIT_FAILURE);
+ }
+ }
+diff --git a/daemon/libvirtd.pod.in b/daemon/libvirtd.pod.in
+index 930b752..9901ecf 100644
+--- a/daemon/libvirtd.pod.in
++++ b/daemon/libvirtd.pod.in
+@@ -36,6 +36,10 @@ from the configuration.
+
+ =over
+
++=item B<-h, --help>
++
++Display command line help usage then exit.
++
+ =item B<-d, --daemon>
+
+ Run as a daemon & write PID file.
+diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
+index c45f45c..77d6e0d 100644
+--- a/src/locking/lock_daemon.c
++++ b/src/locking/lock_daemon.c
+@@ -1096,10 +1096,11 @@ virLockDaemonUsage(const char *argv0, bool privileged)
+ " %s [options]\n"
+ "\n"
+ "Options:\n"
++ " -h | --help Display program help:\n"
+ " -v | --verbose Verbose messages.\n"
+ " -d | --daemon Run as a daemon & write PID file.\n"
+ " -f | --config <file> Configuration file.\n"
+- " | --version Display version information.\n"
++ " -V | --version Display version information.\n"
+ " -p | --pid-file <file> Change name of PID file.\n"
+ "\n"
+ "libvirt lock management daemon:\n"), argv0);
+@@ -1138,10 +1139,6 @@ virLockDaemonUsage(const char *argv0, bool privileged)
+ }
+ }
+
+-enum {
+- OPT_VERSION = 129
+-};
+-
+ #define MAX_LISTEN 5
+ int main(int argc, char **argv) {
+ virNetServerProgramPtr lockProgram = NULL;
+@@ -1161,12 +1158,12 @@ int main(int argc, char **argv) {
+ int rv;
+
+ struct option opts[] = {
+- { "verbose", no_argument, &verbose, 1},
+- { "daemon", no_argument, &godaemon, 1},
++ { "verbose", no_argument, &verbose, 'v'},
++ { "daemon", no_argument, &godaemon, 'd'},
+ { "config", required_argument, NULL, 'f'},
+ { "pid-file", required_argument, NULL, 'p'},
+- { "version", no_argument, NULL, OPT_VERSION },
+- { "help", no_argument, NULL, '?' },
++ { "version", no_argument, NULL, 'V' },
++ { "help", no_argument, NULL, 'h' },
+ {0, 0, 0, 0}
+ };
+
+@@ -1185,7 +1182,7 @@ int main(int argc, char **argv) {
+ int optidx = 0;
+ int c;
+
+- c = getopt_long(argc, argv, "ldf:p:t:v", opts, &optidx);
++ c = getopt_long(argc, argv, "ldf:p:t:vVh", opts, &optidx);
+
+ if (c == -1) {
+ break;
+@@ -1218,17 +1215,17 @@ int main(int argc, char **argv) {
+ }
+ break;
+
+- case OPT_VERSION:
++ case 'V':
+ virLockDaemonVersion(argv[0]);
+- return 0;
++ exit(EXIT_SUCCESS);
+
+- case '?':
++ case 'h':
+ virLockDaemonUsage(argv[0], privileged);
+- return 2;
++ exit(EXIT_SUCCESS);
+
++ case '?':
+ default:
+- fprintf(stderr, _("%s: internal error: unknown flag: %c\n"),
+- argv[0], c);
++ virLockDaemonUsage(argv[0], privileged);
+ exit(EXIT_FAILURE);
+ }
+ }
+diff --git a/src/locking/virtlockd.pod.in b/src/locking/virtlockd.pod.in
+index f5748ca..99612aa 100644
+--- a/src/locking/virtlockd.pod.in
++++ b/src/locking/virtlockd.pod.in
+@@ -26,6 +26,10 @@ The virtlockd daemon listens for requests on a local Unix domain socket.
+
+ =over
+
++=item B<-h, --help>
++
++Display command line help usage then exit.
++
+ =item B<-d, --daemon>
+
+ Run as a daemon and write PID file.
+@@ -42,7 +46,7 @@ Use this name for the PID file, overriding the default value.
+
+ Enable output of verbose messages.
+
+-=item B< --version>
++=item B<-V, --version>
+
+ Display version information then exit.
+
+--
+1.8.3.2
+
--- /dev/null
+From f5e317a62939f1b06081f309ee4e7b146385509b Mon Sep 17 00:00:00 2001
+Message-Id: <f5e317a62939f1b06081f309ee4e7b146385509b.1377873636.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 5 Aug 2013 11:30:16 +0200
+Subject: [PATCH] RPC: Don't accept client if it would overcommit max_clients
+
+https://bugzilla.redhat.com/show_bug.cgi?id=981729
+
+Currently, even if max_client limit is hit, we accept() incoming
+connection request, but close it immediately. This has disadvantage of
+not using listen() queue. We should accept() only those clients we
+know we can serve and let all other wait in the (limited) queue.
+(cherry picked from commit 2737aaafe953fc63c3387aa3ecc540b0f44c735c)
+---
+ src/rpc/virnetserver.c | 29 ++++++++++++++++++++++++++---
+ 1 file changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
+index cb770c3..2306e10 100644
+--- a/src/rpc/virnetserver.c
++++ b/src/rpc/virnetserver.c
+@@ -115,6 +115,8 @@ struct _virNetServer {
+
+ static virClassPtr virNetServerClass;
+ static void virNetServerDispose(void *obj);
++static void virNetServerUpdateServicesLocked(virNetServerPtr srv,
++ bool enabled);
+
+ static int virNetServerOnceInit(void)
+ {
+@@ -270,6 +272,12 @@ static int virNetServerAddClient(virNetServerPtr srv,
+ srv->clients[srv->nclients-1] = client;
+ virObjectRef(client);
+
++ if (srv->nclients == srv->nclients_max) {
++ /* Temporarily stop accepting new clients */
++ VIR_DEBUG("Temporarily suspending services due to max_clients");
++ virNetServerUpdateServicesLocked(srv, false);
++ }
++
+ virNetServerClientSetDispatcher(client,
+ virNetServerDispatchNewMessage,
+ srv);
+@@ -1034,15 +1042,22 @@ static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
+ }
+
+
+-void virNetServerUpdateServices(virNetServerPtr srv,
+- bool enabled)
++static void
++virNetServerUpdateServicesLocked(virNetServerPtr srv,
++ bool enabled)
+ {
+ size_t i;
+
+- virObjectLock(srv);
+ for (i = 0; i < srv->nservices; i++)
+ virNetServerServiceToggle(srv->services[i], enabled);
++}
+
++
++void virNetServerUpdateServices(virNetServerPtr srv,
++ bool enabled)
++{
++ virObjectLock(srv);
++ virNetServerUpdateServicesLocked(srv, enabled);
+ virObjectUnlock(srv);
+ }
+
+@@ -1120,6 +1135,14 @@ void virNetServerRun(virNetServerPtr srv)
+ srv->nclients = 0;
+ }
+
++ /* Enable services if we can accept a new client.
++ * The new client can be accepted if we are at the limit. */
++ if (srv->nclients == srv->nclients_max - 1) {
++ /* Now it makes sense to accept() a new client. */
++ VIR_DEBUG("Re-enabling services");
++ virNetServerUpdateServicesLocked(srv, true);
++ }
++
+ virObjectUnlock(srv);
+ virObjectUnref(client);
+ virObjectLock(srv);
+--
+1.8.3.2
+
--- /dev/null
+From 0d1f9f194177011d678872b55a318c4d60e6b850 Mon Sep 17 00:00:00 2001
+Message-Id: <0d1f9f194177011d678872b55a318c4d60e6b850.1377873638.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:38:27 +0100
+Subject: [PATCH] Record the where the auto-generated data comes from
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+The gendispatch.pl script puts comments at the top of files
+it creates, saying that it auto-generated them. Also include
+the name of the source data file which it reads when doing
+the auto-generation.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 0f3f0fad8c65e664733148b8bb8a766a0b86c603)
+---
+ src/rpc/gendispatch.pl | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
+index ac0c7ab..ceb1ad8 100755
+--- a/src/rpc/gendispatch.pl
++++ b/src/rpc/gendispatch.pl
+@@ -348,19 +348,19 @@ sub hyper_to_long
+
+ if ($mode eq "aclsym") {
+ print <<__EOF__;
+-# Automatically generated by gendispatch.pl.
++# Automatically generated from $protocol by gendispatch.pl.
+ # Do not edit this file. Any changes you make will be lost.
+ __EOF__
+ } elsif ($mode eq "aclapi") {
+ print <<__EOF__;
+ <!--
+- - Automatically generated by gendispatch.pl.
++ - Automatically generated from $protocol by gendispatch.pl.
+ - Do not edit this file. Any changes you make will be lost.
+ -->
+ __EOF__
+ } else {
+ print <<__EOF__;
+-/* Automatically generated by gendispatch.pl.
++/* Automatically generated from $protocol by gendispatch.pl.
+ * Do not edit this file. Any changes you make will be lost.
+ */
+ __EOF__
+--
+1.8.3.2
+
--- /dev/null
+From 8af57380c9ea6f6ffec579804a409e54d323f39a Mon Sep 17 00:00:00 2001
+Message-Id: <8af57380c9ea6f6ffec579804a409e54d323f39a.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:51 +0000
+Subject: [PATCH] Remove all direct use of getenv
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+Unconditional use of getenv is not secure in setuid env.
+While not all libvirt code runs in a setuid env (since
+much of it only exists inside libvirtd) this is not always
+clear to developers. So make all the code paranoid, even
+if it only ever runs inside libvirtd.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 1e4a02bdfe6307f93763fa2c9681f280c564aee5)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ daemon/libvirtd.c | 2 +-
+ src/driver.c | 3 ++-
+ src/libvirt.c | 2 +-
+ src/locking/lock_daemon.c | 4 ++--
+ src/locking/lock_driver_lockd.c | 2 +-
+ src/locking/lock_manager.c | 2 +-
+ src/lxc/lxc_driver.c | 4 ++--
+ src/remote/remote_driver.c | 4 ++--
+ src/rpc/virnettlscontext.c | 4 ++--
+ src/util/virauth.c | 2 +-
+ src/util/virfile.c | 7 +++++--
+ src/util/virlog.c | 8 ++++----
+ src/util/virrandom.c | 2 +-
+ src/util/virutil.c | 8 ++++----
+ src/vbox/vbox_XPCOMCGlue.c | 2 +-
+ src/vbox/vbox_tmpl.c | 4 ++--
+ tools/virsh.c | 18 +++++++++---------
+ 17 files changed, 41 insertions(+), 37 deletions(-)
+
+diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
+index c9cd1a1..808bd4b 100644
+--- a/daemon/libvirtd.c
++++ b/daemon/libvirtd.c
+@@ -991,7 +991,7 @@ static int migrateProfile(void)
+ goto cleanup;
+ }
+
+- config_home = getenv("XDG_CONFIG_HOME");
++ config_home = virGetEnvBlockSUID("XDG_CONFIG_HOME");
+ if (config_home && config_home[0] != '\0') {
+ if (VIR_STRDUP(xdg_dir, config_home) < 0)
+ goto cleanup;
+diff --git a/src/driver.c b/src/driver.c
+index a08dd34..ab2a253 100644
+--- a/src/driver.c
++++ b/src/driver.c
+@@ -27,6 +27,7 @@
+ #include "driver.h"
+ #include "viralloc.h"
+ #include "virlog.h"
++#include "virutil.h"
+ #include "configmake.h"
+ #include "virstring.h"
+
+@@ -43,7 +44,7 @@ static const char *moddir = NULL;
+ void
+ virDriverModuleInitialize(const char *defmoddir)
+ {
+- const char *custommoddir = getenv("LIBVIRT_DRIVER_DIR");
++ const char *custommoddir = virGetEnvBlockSUID("LIBVIRT_DRIVER_DIR");
+ if (custommoddir)
+ moddir = custommoddir;
+ else if (defmoddir)
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 4c1992c..0a024a9 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -1094,7 +1094,7 @@ virConnectGetDefaultURI(virConfPtr conf,
+ {
+ int ret = -1;
+ virConfValuePtr value = NULL;
+- char *defname = getenv("LIBVIRT_DEFAULT_URI");
++ const char *defname = virGetEnvBlockSUID("LIBVIRT_DEFAULT_URI");
+ if (defname && *defname) {
+ VIR_DEBUG("Using LIBVIRT_DEFAULT_URI '%s'", defname);
+ *name = defname;
+diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
+index 77d6e0d..0ac16c3 100644
+--- a/src/locking/lock_daemon.c
++++ b/src/locking/lock_daemon.c
+@@ -605,7 +605,7 @@ virLockDaemonSetupNetworkingSystemD(virNetServerPtr srv)
+
+ VIR_DEBUG("Setting up networking from systemd");
+
+- if (!(pidstr = getenv("LISTEN_PID"))) {
++ if (!(pidstr = virGetEnvAllowSUID("LISTEN_PID"))) {
+ VIR_DEBUG("No LISTEN_FDS from systemd");
+ return 0;
+ }
+@@ -621,7 +621,7 @@ virLockDaemonSetupNetworkingSystemD(virNetServerPtr srv)
+ return 0;
+ }
+
+- if (!(fdstr = getenv("LISTEN_FDS"))) {
++ if (!(fdstr = virGetEnvAllowSUID("LISTEN_FDS"))) {
+ VIR_DEBUG("No LISTEN_FDS from systemd");
+ return 0;
+ }
+diff --git a/src/locking/lock_driver_lockd.c b/src/locking/lock_driver_lockd.c
+index b115799..86ce2d8 100644
+--- a/src/locking/lock_driver_lockd.c
++++ b/src/locking/lock_driver_lockd.c
+@@ -84,7 +84,7 @@ static virLockManagerLockDaemonDriverPtr driver = NULL;
+ static const char *
+ virLockManagerLockDaemonFindDaemon(void)
+ {
+- const char *customDaemon = getenv("VIRTLOCKD_PATH");
++ const char *customDaemon = virGetEnvBlockSUID("VIRTLOCKD_PATH");
+
+ if (customDaemon)
+ return customDaemon;
+diff --git a/src/locking/lock_manager.c b/src/locking/lock_manager.c
+index aff54c0..f09c168 100644
+--- a/src/locking/lock_manager.c
++++ b/src/locking/lock_manager.c
+@@ -135,7 +135,7 @@ virLockManagerPluginPtr virLockManagerPluginNew(const char *name,
+ void *handle = NULL;
+ virLockDriverPtr driver;
+ virLockManagerPluginPtr plugin = NULL;
+- const char *moddir = getenv("LIBVIRT_LOCK_MANAGER_PLUGIN_DIR");
++ const char *moddir = virGetEnvBlockSUID("LIBVIRT_LOCK_MANAGER_PLUGIN_DIR");
+ char *modfile = NULL;
+ char *configFile = NULL;
+
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index 7999b8c..b746ffd 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -1362,14 +1362,14 @@ static int lxcStateInitialize(bool privileged,
+ void *opaque ATTRIBUTE_UNUSED)
+ {
+ virCapsPtr caps = NULL;
+- char *ld;
++ const char *ld;
+ virLXCDriverConfigPtr cfg = NULL;
+
+ /* Valgrind gets very annoyed when we clone containers, so
+ * disable LXC when under valgrind
+ * XXX remove this when valgrind is fixed
+ */
+- ld = getenv("LD_PRELOAD");
++ ld = virGetEnvBlockSUID("LD_PRELOAD");
+ if (ld && strstr(ld, "vgpreload")) {
+ VIR_INFO("Running under valgrind, disabling driver");
+ return 0;
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index dcd433b..67daf79 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -187,7 +187,7 @@ remoteFindDaemonPath(void)
+ NULL
+ };
+ size_t i;
+- const char *customDaemon = getenv("LIBVIRTD_PATH");
++ const char *customDaemon = virGetEnvBlockSUID("LIBVIRTD_PATH");
+
+ if (customDaemon)
+ return customDaemon;
+@@ -955,7 +955,7 @@ remoteConnectOpen(virConnectPtr conn,
+ {
+ struct private_data *priv;
+ int ret, rflags = 0;
+- const char *autostart = getenv("LIBVIRT_AUTOSTART");
++ const char *autostart = virGetEnvBlockSUID("LIBVIRT_AUTOSTART");
+
+ if (inside_daemon && (!conn->uri || (conn->uri && !conn->uri->server)))
+ return VIR_DRV_OPEN_DECLINED;
+diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
+index 7cee27c..cd69794 100644
+--- a/src/rpc/virnettlscontext.c
++++ b/src/rpc/virnettlscontext.c
+@@ -710,7 +710,7 @@ static virNetTLSContextPtr virNetTLSContextNew(const char *cacert,
+ bool isServer)
+ {
+ virNetTLSContextPtr ctxt;
+- char *gnutlsdebug;
++ const char *gnutlsdebug;
+ int err;
+
+ if (virNetTLSContextInitialize() < 0)
+@@ -719,7 +719,7 @@ static virNetTLSContextPtr virNetTLSContextNew(const char *cacert,
+ if (!(ctxt = virObjectLockableNew(virNetTLSContextClass)))
+ return NULL;
+
+- if ((gnutlsdebug = getenv("LIBVIRT_GNUTLS_DEBUG")) != NULL) {
++ if ((gnutlsdebug = virGetEnvAllowSUID("LIBVIRT_GNUTLS_DEBUG")) != NULL) {
+ int val;
+ if (virStrToLong_i(gnutlsdebug, NULL, 10, &val) < 0)
+ val = 10;
+diff --git a/src/util/virauth.c b/src/util/virauth.c
+index f58797c..e66cbf5 100644
+--- a/src/util/virauth.c
++++ b/src/util/virauth.c
+@@ -42,7 +42,7 @@ virAuthGetConfigFilePathURI(virURIPtr uri,
+ {
+ int ret = -1;
+ size_t i;
+- const char *authenv = getenv("LIBVIRT_AUTH_FILE");
++ const char *authenv = virGetEnvBlockSUID("LIBVIRT_AUTH_FILE");
+ char *userdir = NULL;
+
+ *path = NULL;
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 7af0843..92a81a5 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -1354,6 +1354,7 @@ virFileIsLink(const char *linkpath)
+ char *
+ virFindFileInPath(const char *file)
+ {
++ const char *origpath = NULL;
+ char *path = NULL;
+ char *pathiter;
+ char *pathseg;
+@@ -1382,9 +1383,11 @@ virFindFileInPath(const char *file)
+ }
+
+ /* copy PATH env so we can tweak it */
+- path = getenv("PATH");
++ origpath = virGetEnvBlockSUID("PATH");
++ if (!origpath)
++ origpath = "/bin:/usr/bin";
+
+- if (VIR_STRDUP_QUIET(path, path) <= 0)
++ if (VIR_STRDUP_QUIET(path, origpath) <= 0)
+ return NULL;
+
+ /* for each path segment, append the file to search for and test for
+diff --git a/src/util/virlog.c b/src/util/virlog.c
+index 694da89..f250679 100644
+--- a/src/util/virlog.c
++++ b/src/util/virlog.c
+@@ -1637,18 +1637,18 @@ virLogParseDefaultPriority(const char *priority)
+ void
+ virLogSetFromEnv(void)
+ {
+- char *debugEnv;
++ const char *debugEnv;
+
+ if (virLogInitialize() < 0)
+ return;
+
+- debugEnv = getenv("LIBVIRT_DEBUG");
++ debugEnv = virGetEnvAllowSUID("LIBVIRT_DEBUG");
+ if (debugEnv && *debugEnv)
+ virLogParseDefaultPriority(debugEnv);
+- debugEnv = getenv("LIBVIRT_LOG_FILTERS");
++ debugEnv = virGetEnvAllowSUID("LIBVIRT_LOG_FILTERS");
+ if (debugEnv && *debugEnv)
+ virLogParseFilters(debugEnv);
+- debugEnv = getenv("LIBVIRT_LOG_OUTPUTS");
++ debugEnv = virGetEnvAllowSUID("LIBVIRT_LOG_OUTPUTS");
+ if (debugEnv && *debugEnv)
+ virLogParseOutputs(debugEnv);
+ }
+diff --git a/src/util/virrandom.c b/src/util/virrandom.c
+index c233732..6101aac 100644
+--- a/src/util/virrandom.c
++++ b/src/util/virrandom.c
+@@ -50,7 +50,7 @@ virRandomOnceInit(void)
+ /* Normally we want a decent seed. But if reproducible debugging
+ * of a fixed pseudo-random sequence is ever required, uncomment
+ * this block to let an environment variable force the seed. */
+- const char *debug = getenv("VIR_DEBUG_RANDOM_SEED");
++ const char *debug = virGetEnvBlockSUID("VIR_DEBUG_RANDOM_SEED");
+
+ if (debug && virStrToLong_ui(debug, NULL, 0, &seed) < 0)
+ return -1;
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index a41117e..2b3cbeb 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -770,7 +770,7 @@ virGetUserDirectoryByUID(uid_t uid)
+
+ static char *virGetXDGDirectory(const char *xdgenvname, const char *xdgdefdir)
+ {
+- const char *path = getenv(xdgenvname);
++ const char *path = virGetEnvBlockSUID(xdgenvname);
+ char *ret = NULL;
+ char *home = NULL;
+
+@@ -798,7 +798,7 @@ char *virGetUserCacheDirectory(void)
+
+ char *virGetUserRuntimeDirectory(void)
+ {
+- const char *path = getenv("XDG_RUNTIME_DIR");
++ const char *path = virGetEnvBlockSUID("XDG_RUNTIME_DIR");
+
+ if (!path || !path[0]) {
+ return virGetUserCacheDirectory();
+@@ -1111,7 +1111,7 @@ virGetUserDirectoryByUID(uid_t uid ATTRIBUTE_UNUSED)
+ const char *dir;
+ char *ret;
+
+- dir = getenv("HOME");
++ dir = virGetEnvBlockSUID("HOME");
+
+ /* Only believe HOME if it is an absolute path and exists */
+ if (dir) {
+@@ -1131,7 +1131,7 @@ virGetUserDirectoryByUID(uid_t uid ATTRIBUTE_UNUSED)
+
+ if (!dir)
+ /* USERPROFILE is probably the closest equivalent to $HOME? */
+- dir = getenv("USERPROFILE");
++ dir = virGetEnvBlockSUID("USERPROFILE");
+
+ if (VIR_STRDUP(ret, dir) < 0)
+ return NULL;
+diff --git a/src/vbox/vbox_XPCOMCGlue.c b/src/vbox/vbox_XPCOMCGlue.c
+index 10ddcf8..8652e3a 100644
+--- a/src/vbox/vbox_XPCOMCGlue.c
++++ b/src/vbox/vbox_XPCOMCGlue.c
+@@ -201,7 +201,7 @@ VBoxCGlueInit(unsigned int *version)
+ "/usr/local/lib/VirtualBox",
+ "/Applications/VirtualBox.app/Contents/MacOS"
+ };
+- const char *home = getenv("VBOX_APP_HOME");
++ const char *home = virGetEnvBlockSUID("VBOX_APP_HOME");
+
+ /* If the user specifies the location, try only that. */
+ if (home != NULL) {
+diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
+index 5e5ea85..2130590 100644
+--- a/src/vbox/vbox_tmpl.c
++++ b/src/vbox/vbox_tmpl.c
+@@ -2237,7 +2237,6 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) {
+ vboxIID iid = VBOX_IID_INITIALIZER;
+ int gotAllABoutDef = -1;
+ nsresult rc;
+- char *tmp;
+
+ /* Flags checked by virDomainDefFormat */
+
+@@ -2509,8 +2508,9 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) {
+ }
+ } else if ((vrdpPresent != 1) && (totalPresent == 0) && (VIR_ALLOC_N(def->graphics, 1) >= 0)) {
+ if (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0) {
++ const char *tmp;
+ def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP;
+- tmp = getenv("DISPLAY");
++ tmp = virGetEnvBlockSUID("DISPLAY");
+ if (VIR_STRDUP(def->graphics[def->ngraphics]->data.desktop.display, tmp) < 0) {
+ /* just don't go to cleanup yet as it is ok to have
+ * display as NULL
+diff --git a/tools/virsh.c b/tools/virsh.c
+index d1ae183..48bf077 100644
+--- a/tools/virsh.c
++++ b/tools/virsh.c
+@@ -232,7 +232,7 @@ virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error)
+ {
+ virFreeError(last_error);
+ last_error = virSaveLastError();
+- if (getenv("VIRSH_DEBUG") != NULL)
++ if (virGetEnvAllowSUID("VIRSH_DEBUG") != NULL)
+ virDefaultErrorFunc(error);
+ }
+
+@@ -670,7 +670,7 @@ vshEditWriteToTempFile(vshControl *ctl, const char *doc)
+ int fd;
+ char ebuf[1024];
+
+- tmpdir = getenv("TMPDIR");
++ tmpdir = virGetEnvBlockSUID("TMPDIR");
+ if (!tmpdir) tmpdir = "/tmp";
+ if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
+ vshError(ctl, "%s", _("out of memory"));
+@@ -717,9 +717,9 @@ vshEditFile(vshControl *ctl, const char *filename)
+ int outfd = STDOUT_FILENO;
+ int errfd = STDERR_FILENO;
+
+- editor = getenv("VISUAL");
++ editor = virGetEnvBlockSUID("VISUAL");
+ if (!editor)
+- editor = getenv("EDITOR");
++ editor = virGetEnvBlockSUID("EDITOR");
+ if (!editor)
+ editor = "vi"; /* could be cruel & default to ed(1) here */
+
+@@ -2299,11 +2299,11 @@ vshEventLoop(void *opaque)
+ static void
+ vshInitDebug(vshControl *ctl)
+ {
+- char *debugEnv;
++ const char *debugEnv;
+
+ if (ctl->debug == VSH_DEBUG_DEFAULT) {
+ /* log level not set from commandline, check env variable */
+- debugEnv = getenv("VIRSH_DEBUG");
++ debugEnv = virGetEnvAllowSUID("VIRSH_DEBUG");
+ if (debugEnv) {
+ int debug;
+ if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
+@@ -2318,7 +2318,7 @@ vshInitDebug(vshControl *ctl)
+
+ if (ctl->logfile == NULL) {
+ /* log file not set from cmdline */
+- debugEnv = getenv("VIRSH_LOG_FILE");
++ debugEnv = virGetEnvBlockSUID("VIRSH_LOG_FILE");
+ if (debugEnv && *debugEnv) {
+ ctl->logfile = vshStrdup(ctl, debugEnv);
+ vshOpenLogFile(ctl);
+@@ -3164,7 +3164,7 @@ int
+ main(int argc, char **argv)
+ {
+ vshControl _ctl, *ctl = &_ctl;
+- char *defaultConn;
++ const char *defaultConn;
+ bool ret = true;
+
+ memset(ctl, 0, sizeof(vshControl));
+@@ -3202,7 +3202,7 @@ main(int argc, char **argv)
+ else
+ progname++;
+
+- if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
++ if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI"))) {
+ ctl->name = vshStrdup(ctl, defaultConn);
+ }
+
+--
+1.8.4.2
+
--- /dev/null
+From f510cd0de5b55e3b2d0d65bc873d652829a7e2ed Mon Sep 17 00:00:00 2001
+Message-Id: <f510cd0de5b55e3b2d0d65bc873d652829a7e2ed.1383321465.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:56 +0000
+Subject: [PATCH] Remove (nearly) all use of getuid()/getgid()
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+Most of the usage of getuid()/getgid() is in cases where we are
+considering what privileges we have. As such the code should be
+using the effective IDs, not real IDs.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 9b0af09240618184fea5884952941217e65b824f)
+
+Conflicts:
+ tests/qemumonitortestutils.c
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt.c | 2 +-
+ src/locking/lock_daemon.c | 2 +-
+ src/locking/lock_driver_lockd.c | 4 ++--
+ src/lxc/lxc_controller.c | 2 +-
+ src/qemu/qemu_driver.c | 6 +++---
+ src/remote/remote_driver.c | 4 ++--
+ src/storage/storage_backend.c | 4 ++--
+ src/storage/storage_backend_fs.c | 4 ++--
+ src/storage/storage_backend_logical.c | 2 +-
+ src/util/virfile.c | 16 ++++++++--------
+ src/util/viridentity.c | 8 ++++----
+ src/util/virstoragefile.c | 2 +-
+ src/vbox/vbox_driver.c | 2 +-
+ src/vbox/vbox_tmpl.c | 2 +-
+ tests/qemumonitortestutils.c | 4 ++--
+ tests/virnetsockettest.c | 4 ++--
+ 16 files changed, 34 insertions(+), 34 deletions(-)
+
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 8a3cc42..54c90ec 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -133,7 +133,7 @@ static int virConnectAuthGainPolkit(const char *privilege) {
+ int status;
+ int ret = -1;
+
+- if (getuid() == 0)
++ if (geteuid() == 0)
+ return 0;
+
+ cmd = virCommandNewArgList(POLKIT_AUTH, "--obtain", privilege, NULL);
+diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
+index 0ac16c3..d74af13 100644
+--- a/src/locking/lock_daemon.c
++++ b/src/locking/lock_daemon.c
+@@ -1167,7 +1167,7 @@ int main(int argc, char **argv) {
+ {0, 0, 0, 0}
+ };
+
+- privileged = getuid() == 0;
++ privileged = geteuid() == 0;
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+diff --git a/src/locking/lock_driver_lockd.c b/src/locking/lock_driver_lockd.c
+index 86ce2d8..f3b9467 100644
+--- a/src/locking/lock_driver_lockd.c
++++ b/src/locking/lock_driver_lockd.c
+@@ -302,7 +302,7 @@ virLockManagerLockDaemonConnect(virLockManagerPtr lock,
+ {
+ virNetClientPtr client;
+
+- if (!(client = virLockManagerLockDaemonConnectionNew(getuid() == 0, program)))
++ if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, program)))
+ return NULL;
+
+ if (virLockManagerLockDaemonConnectionRegister(lock,
+@@ -331,7 +331,7 @@ static int virLockManagerLockDaemonSetupLockspace(const char *path)
+ memset(&args, 0, sizeof(args));
+ args.path = (char*)path;
+
+- if (!(client = virLockManagerLockDaemonConnectionNew(getuid() == 0, &program)))
++ if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, &program)))
+ return -1;
+
+ if (virNetClientProgramCall(program,
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index 357910d..5754c92 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -2353,7 +2353,7 @@ int main(int argc, char *argv[])
+ goto cleanup;
+ }
+
+- if (getuid() != 0) {
++ if (geteuid() != 0) {
+ fprintf(stderr, "%s: must be run as the 'root' user\n", argv[0]);
+ goto cleanup;
+ }
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 226e32d..e7b0f37 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -2796,8 +2796,8 @@ qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
+ unsigned int vfoflags = 0;
+ int fd = -1;
+ int path_shared = virStorageFileIsSharedFS(path);
+- uid_t uid = getuid();
+- gid_t gid = getgid();
++ uid_t uid = geteuid();
++ gid_t gid = getegid();
+
+ /* path might be a pre-existing block dev, in which case
+ * we need to skip the create step, and also avoid unlink
+@@ -2837,7 +2837,7 @@ qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
+ qemu user is non-root, just set a flag to
+ bypass security driver shenanigans, and retry the operation
+ after doing setuid to qemu user */
+- if ((fd != -EACCES && fd != -EPERM) || fallback_uid == getuid())
++ if ((fd != -EACCES && fd != -EPERM) || fallback_uid == geteuid())
+ goto error;
+
+ /* On Linux we can also verify the FS-type of the directory. */
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 7688bf6..b3e86e1 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -995,7 +995,7 @@ remoteConnectOpen(virConnectPtr conn,
+ (strstr(conn->uri->scheme, "+unix") != NULL)) &&
+ (STREQ(conn->uri->path, "/session") ||
+ STRPREFIX(conn->uri->scheme, "test+")) &&
+- getuid() > 0) {
++ geteuid() > 0) {
+ VIR_DEBUG("Auto-spawn user daemon instance");
+ rflags |= VIR_DRV_OPEN_REMOTE_USER;
+ if (!virIsSUID() &&
+@@ -1013,7 +1013,7 @@ remoteConnectOpen(virConnectPtr conn,
+ if (!conn->uri) {
+ VIR_DEBUG("Auto-probe remote URI");
+ #ifndef __sun
+- if (getuid() > 0) {
++ if (geteuid() > 0) {
+ VIR_DEBUG("Auto-spawn user daemon instance");
+ rflags |= VIR_DRV_OPEN_REMOTE_USER;
+ if (!virIsSUID() &&
+diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
+index 4ebe11b..4bbf988 100644
+--- a/src/storage/storage_backend.c
++++ b/src/storage/storage_backend.c
+@@ -527,11 +527,11 @@ virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
+ bool filecreated = false;
+
+ if ((pool->def->type == VIR_STORAGE_POOL_NETFS)
+- && (((getuid() == 0)
++ && (((geteuid() == 0)
+ && (vol->target.perms.uid != (uid_t) -1)
+ && (vol->target.perms.uid != 0))
+ || ((vol->target.perms.gid != (gid_t) -1)
+- && (vol->target.perms.gid != getgid())))) {
++ && (vol->target.perms.gid != getegid())))) {
+
+ virCommandSetUID(cmd, vol->target.perms.uid);
+ virCommandSetGID(cmd, vol->target.perms.gid);
+diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
+index d305b06..8bbee92 100644
+--- a/src/storage/storage_backend_fs.c
++++ b/src/storage/storage_backend_fs.c
+@@ -786,9 +786,9 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+ /* Reflect the actual uid and gid to the config. */
+ if (pool->def->target.perms.uid == (uid_t) -1)
+- pool->def->target.perms.uid = getuid();
++ pool->def->target.perms.uid = geteuid();
+ if (pool->def->target.perms.gid == (gid_t) -1)
+- pool->def->target.perms.gid = getgid();
++ pool->def->target.perms.gid = getegid();
+
+ if (flags != 0) {
+ ret = virStorageBackendMakeFileSystem(pool, flags);
+diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
+index 8998a11..817edd5 100644
+--- a/src/storage/storage_backend_logical.c
++++ b/src/storage/storage_backend_logical.c
+@@ -719,7 +719,7 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn,
+ goto error;
+
+ /* We can only chown/grp if root */
+- if (getuid() == 0) {
++ if (geteuid() == 0) {
+ if (fchown(fd, vol->target.perms.uid, vol->target.perms.gid) < 0) {
+ virReportSystemError(errno,
+ _("cannot set file owner '%s'"),
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 92a81a5..33a8a6d 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -1457,8 +1457,8 @@ virFileAccessibleAs(const char *path, int mode,
+ gid_t *groups;
+ int ngroups;
+
+- if (uid == getuid() &&
+- gid == getgid())
++ if (uid == geteuid() &&
++ gid == getegid())
+ return access(path, mode);
+
+ ngroups = virGetGroupList(uid, gid, &groups);
+@@ -1750,9 +1750,9 @@ virFileOpenAs(const char *path, int openflags, mode_t mode,
+
+ /* allow using -1 to mean "current value" */
+ if (uid == (uid_t) -1)
+- uid = getuid();
++ uid = geteuid();
+ if (gid == (gid_t) -1)
+- gid = getgid();
++ gid = getegid();
+
+ /* treat absence of both flags as presence of both for simpler
+ * calling. */
+@@ -1760,7 +1760,7 @@ virFileOpenAs(const char *path, int openflags, mode_t mode,
+ flags |= VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK;
+
+ if ((flags & VIR_FILE_OPEN_NOFORK)
+- || (getuid() != 0)
++ || (geteuid() != 0)
+ || ((uid == 0) && (gid == 0))) {
+
+ if ((fd = open(path, openflags, mode)) < 0) {
+@@ -1871,12 +1871,12 @@ virDirCreate(const char *path,
+
+ /* allow using -1 to mean "current value" */
+ if (uid == (uid_t) -1)
+- uid = getuid();
++ uid = geteuid();
+ if (gid == (gid_t) -1)
+- gid = getgid();
++ gid = getegid();
+
+ if ((!(flags & VIR_DIR_CREATE_AS_UID))
+- || (getuid() != 0)
++ || (geteuid() != 0)
+ || ((uid == 0) && (gid == 0))
+ || ((flags & VIR_DIR_CREATE_ALLOW_EXIST) && (stat(path, &st) >= 0))) {
+ return virDirCreateNoFork(path, mode, uid, gid, flags);
+diff --git a/src/util/viridentity.c b/src/util/viridentity.c
+index f681f85..4f5127c 100644
+--- a/src/util/viridentity.c
++++ b/src/util/viridentity.c
+@@ -157,14 +157,14 @@ virIdentityPtr virIdentityGetSystem(void)
+ virAsprintf(&processtime, "%llu", timestamp) < 0)
+ goto cleanup;
+
+- if (!(username = virGetUserName(getuid())))
++ if (!(username = virGetUserName(geteuid())))
+ goto cleanup;
+- if (virAsprintf(&userid, "%d", (int)getuid()) < 0)
++ if (virAsprintf(&userid, "%d", (int)geteuid()) < 0)
+ goto cleanup;
+
+- if (!(groupname = virGetGroupName(getgid())))
++ if (!(groupname = virGetGroupName(getegid())))
+ goto cleanup;
+- if (virAsprintf(&groupid, "%d", (int)getgid()) < 0)
++ if (virAsprintf(&groupid, "%d", (int)getegid()) < 0)
+ goto cleanup;
+
+ #if WITH_SELINUX
+diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
+index 0b9cec3..9453599 100644
+--- a/src/util/virstoragefile.c
++++ b/src/util/virstoragefile.c
+@@ -572,7 +572,7 @@ virFindBackingFile(const char *start, bool start_is_dir, const char *path,
+ goto cleanup;
+ }
+
+- if (virFileAccessibleAs(combined, F_OK, getuid(), getgid()) < 0) {
++ if (virFileAccessibleAs(combined, F_OK, geteuid(), getegid()) < 0) {
+ virReportSystemError(errno,
+ _("Cannot access backing file '%s'"),
+ combined);
+diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c
+index 9d07574..4978913 100644
+--- a/src/vbox/vbox_driver.c
++++ b/src/vbox/vbox_driver.c
+@@ -153,7 +153,7 @@ static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
+ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+ unsigned int flags)
+ {
+- uid_t uid = getuid();
++ uid_t uid = geteuid();
+
+ virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
+index 2130590..5b17048 100644
+--- a/src/vbox/vbox_tmpl.c
++++ b/src/vbox/vbox_tmpl.c
+@@ -999,7 +999,7 @@ static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
+ unsigned int flags)
+ {
+ vboxGlobalData *data = NULL;
+- uid_t uid = getuid();
++ uid_t uid = geteuid();
+
+ virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c
+index 56368a2..1bcdb1f 100644
+--- a/tests/qemumonitortestutils.c
++++ b/tests/qemumonitortestutils.c
+@@ -482,8 +482,8 @@ qemuMonitorTestPtr qemuMonitorTestNew(bool json, virDomainXMLOptionPtr xmlopt)
+
+ if (virNetSocketNewListenUNIX(path,
+ 0700,
+- getuid(),
+- getgid(),
++ geteuid(),
++ getegid(),
+ &test->server) < 0)
+ goto error;
+
+diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c
+index 5b434ba..bb0e572 100644
+--- a/tests/virnetsockettest.c
++++ b/tests/virnetsockettest.c
+@@ -220,7 +220,7 @@ static int testSocketUNIXAccept(const void *data ATTRIBUTE_UNUSED)
+ if (virAsprintf(&path, "%s/test.sock", tmpdir) < 0)
+ goto cleanup;
+
+- if (virNetSocketNewListenUNIX(path, 0700, -1, getgid(), &lsock) < 0)
++ if (virNetSocketNewListenUNIX(path, 0700, -1, getegid(), &lsock) < 0)
+ goto cleanup;
+
+ if (virNetSocketListen(lsock, 0) < 0)
+@@ -270,7 +270,7 @@ static int testSocketUNIXAddrs(const void *data ATTRIBUTE_UNUSED)
+ if (virAsprintf(&path, "%s/test.sock", tmpdir) < 0)
+ goto cleanup;
+
+- if (virNetSocketNewListenUNIX(path, 0700, -1, getgid(), &lsock) < 0)
++ if (virNetSocketNewListenUNIX(path, 0700, -1, getegid(), &lsock) < 0)
+ goto cleanup;
+
+ if (STRNEQ(virNetSocketLocalAddrString(lsock), "127.0.0.1;0")) {
+--
+1.8.4.2
+
--- /dev/null
+From 4424870618c6e43ca44f78842c433e9b5e6c06d4 Mon Sep 17 00:00:00 2001
+Message-Id: <4424870618c6e43ca44f78842c433e9b5e6c06d4.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 16:43:12 +0100
+Subject: [PATCH] Remove use of virConnectPtr from all remaining nwfilter code
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015108
+
+The virConnectPtr is passed around loads of nwfilter code in
+order to provide it as a parameter to the callback registered
+by the virt drivers. None of the virt drivers use this param
+though, so it serves no purpose.
+
+Avoiding the need to pass a virConnectPtr means that the
+nwfilterStateReload method no longer needs to open a bogus
+QEMU driver connection. This addresses a race condition that
+can lead to a crash on startup.
+
+The nwfilter driver starts before the QEMU driver and registers
+some callbacks with DBus to detect firewalld reload. If the
+firewalld reload happens while the QEMU driver is still starting
+up though, the nwfilterStateReload method will open a connection
+to the partially initialized QEMU driver and cause a crash.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 999d72fbd59ea712128ae294b69b6a54039d757b)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/nwfilter_conf.c | 49 ++++++++++++++++--------------------------
+ src/conf/nwfilter_conf.h | 14 +++++-------
+ src/lxc/lxc_driver.c | 3 +--
+ src/nwfilter/nwfilter_driver.c | 42 ++++++++++++++----------------------
+ src/qemu/qemu_driver.c | 3 +--
+ src/uml/uml_driver.c | 3 +--
+ 6 files changed, 43 insertions(+), 71 deletions(-)
+
+diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
+index 424c396..1b86d36 100644
+--- a/src/conf/nwfilter_conf.c
++++ b/src/conf/nwfilter_conf.c
+@@ -2743,8 +2743,7 @@ cleanup:
+
+
+ static int
+-_virNWFilterDefLoopDetect(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++_virNWFilterDefLoopDetect(virNWFilterObjListPtr nwfilters,
+ virNWFilterDefPtr def,
+ const char *filtername)
+ {
+@@ -2768,7 +2767,7 @@ _virNWFilterDefLoopDetect(virConnectPtr conn,
+ obj = virNWFilterObjFindByName(nwfilters,
+ entry->include->filterref);
+ if (obj) {
+- rc = _virNWFilterDefLoopDetect(conn, nwfilters,
++ rc = _virNWFilterDefLoopDetect(nwfilters,
+ obj->def, filtername);
+
+ virNWFilterObjUnlock(obj);
+@@ -2784,7 +2783,6 @@ _virNWFilterDefLoopDetect(virConnectPtr conn,
+
+ /*
+ * virNWFilterDefLoopDetect:
+- * @conn: pointer to virConnect object
+ * @nwfilters : the nwfilters to search
+ * @def : the filter definition that may add a loop and is to be tested
+ *
+@@ -2794,11 +2792,10 @@ _virNWFilterDefLoopDetect(virConnectPtr conn,
+ * Returns 0 in case no loop was detected, -1 otherwise.
+ */
+ static int
+-virNWFilterDefLoopDetect(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++virNWFilterDefLoopDetect(virNWFilterObjListPtr nwfilters,
+ virNWFilterDefPtr def)
+ {
+- return _virNWFilterDefLoopDetect(conn, nwfilters, def, def->name);
++ return _virNWFilterDefLoopDetect(nwfilters, def, def->name);
+ }
+
+ int nCallbackDriver;
+@@ -2857,7 +2854,7 @@ static void *virNWFilterDomainFWUpdateOpaque;
+ * error. This should be called upon reloading of the driver.
+ */
+ int
+-virNWFilterInstFiltersOnAllVMs(virConnectPtr conn)
++virNWFilterInstFiltersOnAllVMs(void)
+ {
+ size_t i;
+ struct domUpdateCBStruct cb = {
+@@ -2867,15 +2864,14 @@ virNWFilterInstFiltersOnAllVMs(virConnectPtr conn)
+ };
+
+ for (i = 0; i < nCallbackDriver; i++)
+- callbackDrvArray[i]->vmFilterRebuild(conn,
+- virNWFilterDomainFWUpdateCB,
++ callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB,
+ &cb);
+
+ return 0;
+ }
+
+ static int
+-virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
++virNWFilterTriggerVMFilterRebuild(void)
+ {
+ size_t i;
+ int ret = 0;
+@@ -2889,8 +2885,7 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
+ return -1;
+
+ for (i = 0; i < nCallbackDriver; i++) {
+- if (callbackDrvArray[i]->vmFilterRebuild(conn,
+- virNWFilterDomainFWUpdateCB,
++ if (callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB,
+ &cb) < 0)
+ ret = -1;
+ }
+@@ -2899,15 +2894,13 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
+ cb.step = STEP_TEAR_NEW; /* rollback */
+
+ for (i = 0; i < nCallbackDriver; i++)
+- callbackDrvArray[i]->vmFilterRebuild(conn,
+- virNWFilterDomainFWUpdateCB,
++ callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB,
+ &cb);
+ } else {
+ cb.step = STEP_TEAR_OLD; /* switch over */
+
+ for (i = 0; i < nCallbackDriver; i++)
+- callbackDrvArray[i]->vmFilterRebuild(conn,
+- virNWFilterDomainFWUpdateCB,
++ callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB,
+ &cb);
+ }
+
+@@ -2918,14 +2911,13 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
+
+
+ int
+-virNWFilterTestUnassignDef(virConnectPtr conn,
+- virNWFilterObjPtr nwfilter)
++virNWFilterTestUnassignDef(virNWFilterObjPtr nwfilter)
+ {
+ int rc = 0;
+
+ nwfilter->wantRemoved = 1;
+ /* trigger the update on VMs referencing the filter */
+- if (virNWFilterTriggerVMFilterRebuild(conn))
++ if (virNWFilterTriggerVMFilterRebuild())
+ rc = -1;
+
+ nwfilter->wantRemoved = 0;
+@@ -2964,8 +2956,7 @@ cleanup:
+ }
+
+ virNWFilterObjPtr
+-virNWFilterObjAssignDef(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++virNWFilterObjAssignDef(virNWFilterObjListPtr nwfilters,
+ virNWFilterDefPtr def)
+ {
+ virNWFilterObjPtr nwfilter;
+@@ -2984,7 +2975,7 @@ virNWFilterObjAssignDef(virConnectPtr conn,
+ virNWFilterObjUnlock(nwfilter);
+ }
+
+- if (virNWFilterDefLoopDetect(conn, nwfilters, def) < 0) {
++ if (virNWFilterDefLoopDetect(nwfilters, def) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("filter would introduce a loop"));
+ return NULL;
+@@ -3003,7 +2994,7 @@ virNWFilterObjAssignDef(virConnectPtr conn,
+
+ nwfilter->newDef = def;
+ /* trigger the update on VMs referencing the filter */
+- if (virNWFilterTriggerVMFilterRebuild(conn)) {
++ if (virNWFilterTriggerVMFilterRebuild()) {
+ nwfilter->newDef = NULL;
+ virNWFilterUnlockFilterUpdates();
+ virNWFilterObjUnlock(nwfilter);
+@@ -3045,8 +3036,7 @@ virNWFilterObjAssignDef(virConnectPtr conn,
+
+
+ static virNWFilterObjPtr
+-virNWFilterObjLoad(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++virNWFilterObjLoad(virNWFilterObjListPtr nwfilters,
+ const char *file,
+ const char *path)
+ {
+@@ -3065,7 +3055,7 @@ virNWFilterObjLoad(virConnectPtr conn,
+ return NULL;
+ }
+
+- if (!(nwfilter = virNWFilterObjAssignDef(conn, nwfilters, def))) {
++ if (!(nwfilter = virNWFilterObjAssignDef(nwfilters, def))) {
+ virNWFilterDefFree(def);
+ return NULL;
+ }
+@@ -3081,8 +3071,7 @@ virNWFilterObjLoad(virConnectPtr conn,
+
+
+ int
+-virNWFilterLoadAllConfigs(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++virNWFilterLoadAllConfigs(virNWFilterObjListPtr nwfilters,
+ const char *configDir)
+ {
+ DIR *dir;
+@@ -3110,7 +3099,7 @@ virNWFilterLoadAllConfigs(virConnectPtr conn,
+ if (!(path = virFileBuildPath(configDir, entry->d_name, NULL)))
+ continue;
+
+- nwfilter = virNWFilterObjLoad(conn, nwfilters, entry->d_name, path);
++ nwfilter = virNWFilterObjLoad(nwfilters, entry->d_name, path);
+ if (nwfilter)
+ virNWFilterObjUnlock(nwfilter);
+
+diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
+index e470615..29906f1 100644
+--- a/src/conf/nwfilter_conf.h
++++ b/src/conf/nwfilter_conf.h
+@@ -687,12 +687,10 @@ int virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver,
+
+ int virNWFilterObjDeleteDef(virNWFilterObjPtr nwfilter);
+
+-virNWFilterObjPtr virNWFilterObjAssignDef(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++virNWFilterObjPtr virNWFilterObjAssignDef(virNWFilterObjListPtr nwfilters,
+ virNWFilterDefPtr def);
+
+-int virNWFilterTestUnassignDef(virConnectPtr conn,
+- virNWFilterObjPtr nwfilter);
++int virNWFilterTestUnassignDef(virNWFilterObjPtr nwfilter);
+
+ virNWFilterDefPtr virNWFilterDefParseNode(xmlDocPtr xml,
+ xmlNodePtr root);
+@@ -706,8 +704,7 @@ int virNWFilterSaveXML(const char *configDir,
+ int virNWFilterSaveConfig(const char *configDir,
+ virNWFilterDefPtr def);
+
+-int virNWFilterLoadAllConfigs(virConnectPtr conn,
+- virNWFilterObjListPtr nwfilters,
++int virNWFilterLoadAllConfigs(virNWFilterObjListPtr nwfilters,
+ const char *configDir);
+
+ char *virNWFilterConfigFile(const char *dir,
+@@ -725,11 +722,10 @@ void virNWFilterUnlockFilterUpdates(void);
+ int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB, void *opaque);
+ void virNWFilterConfLayerShutdown(void);
+
+-int virNWFilterInstFiltersOnAllVMs(virConnectPtr conn);
++int virNWFilterInstFiltersOnAllVMs(void);
+
+
+-typedef int (*virNWFilterRebuild)(virConnectPtr conn,
+- virDomainObjListIterator domUpdateCB,
++typedef int (*virNWFilterRebuild)(virDomainObjListIterator domUpdateCB,
+ void *data);
+ typedef void (*virNWFilterVoidCall)(void);
+
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index bafbe93..7999b8c 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -84,8 +84,7 @@ virLXCDriverPtr lxc_driver = NULL;
+
+ /* callbacks for nwfilter */
+ static int
+-lxcVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+- virDomainObjListIterator iter, void *data)
++lxcVMFilterRebuild(virDomainObjListIterator iter, void *data)
+ {
+ return virDomainObjListForEach(lxc_driver->domains, iter, data);
+ }
+diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
+index 0a515e7..ce75c82 100644
+--- a/src/nwfilter/nwfilter_driver.c
++++ b/src/nwfilter/nwfilter_driver.c
+@@ -230,8 +230,7 @@ nwfilterStateInitialize(bool privileged,
+
+ VIR_FREE(base);
+
+- if (virNWFilterLoadAllConfigs(NULL,
+- &driverState->nwfilters,
++ if (virNWFilterLoadAllConfigs(&driverState->nwfilters,
+ driverState->configDir) < 0)
+ goto error;
+
+@@ -267,37 +266,28 @@ err_free_driverstate:
+ * files and update its state
+ */
+ static int
+-nwfilterStateReload(void) {
+- virConnectPtr conn;
+-
+- if (!driverState) {
++nwfilterStateReload(void)
++{
++ if (!driverState)
+ return -1;
+- }
+
+ if (!driverState->privileged)
+ return 0;
+
+- conn = virConnectOpen("qemu:///system");
+-
+- if (conn) {
+- virNWFilterDHCPSnoopEnd(NULL);
+- /* shut down all threads -- they will be restarted if necessary */
+- virNWFilterLearnThreadsTerminate(true);
+-
+- nwfilterDriverLock(driverState);
+- virNWFilterCallbackDriversLock();
++ virNWFilterDHCPSnoopEnd(NULL);
++ /* shut down all threads -- they will be restarted if necessary */
++ virNWFilterLearnThreadsTerminate(true);
+
+- virNWFilterLoadAllConfigs(conn,
+- &driverState->nwfilters,
+- driverState->configDir);
++ nwfilterDriverLock(driverState);
++ virNWFilterCallbackDriversLock();
+
+- virNWFilterCallbackDriversUnlock();
+- nwfilterDriverUnlock(driverState);
++ virNWFilterLoadAllConfigs(&driverState->nwfilters,
++ driverState->configDir);
+
+- virNWFilterInstFiltersOnAllVMs(conn);
++ virNWFilterCallbackDriversUnlock();
++ nwfilterDriverUnlock(driverState);
+
+- virConnectClose(conn);
+- }
++ virNWFilterInstFiltersOnAllVMs();
+
+ return 0;
+ }
+@@ -568,7 +558,7 @@ nwfilterDefineXML(virConnectPtr conn,
+ if (virNWFilterDefineXMLEnsureACL(conn, def) < 0)
+ goto cleanup;
+
+- if (!(nwfilter = virNWFilterObjAssignDef(conn, &driver->nwfilters, def)))
++ if (!(nwfilter = virNWFilterObjAssignDef(&driver->nwfilters, def)))
+ goto cleanup;
+
+ if (virNWFilterObjSaveDef(driver, nwfilter, def) < 0) {
+@@ -612,7 +602,7 @@ nwfilterUndefine(virNWFilterPtr obj) {
+ if (virNWFilterUndefineEnsureACL(obj->conn, nwfilter->def) < 0)
+ goto cleanup;
+
+- if (virNWFilterTestUnassignDef(obj->conn, nwfilter) < 0) {
++ if (virNWFilterTestUnassignDef(nwfilter) < 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s",
+ _("nwfilter is in use"));
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index fd548b2..3820303 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -177,8 +177,7 @@ static void
+ qemuVMDriverUnlock(void) {}
+
+ static int
+-qemuVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+- virDomainObjListIterator iter, void *data)
++qemuVMFilterRebuild(virDomainObjListIterator iter, void *data)
+ {
+ return virDomainObjListForEach(qemu_driver->domains, iter, data);
+ }
+diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
+index 9ca352f..eb02542 100644
+--- a/src/uml/uml_driver.c
++++ b/src/uml/uml_driver.c
+@@ -148,8 +148,7 @@ static int umlMonitorCommand(const struct uml_driver *driver,
+ static struct uml_driver *uml_driver = NULL;
+
+ static int
+-umlVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+- virDomainObjListIterator iter, void *data)
++umlVMFilterRebuild(virDomainObjListIterator iter, void *data)
+ {
+ return virDomainObjListForEach(uml_driver->domains, iter, data);
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 0b70693af3d91a1390c314fc84d7062ce419808b Mon Sep 17 00:00:00 2001
+Message-Id: <0b70693af3d91a1390c314fc84d7062ce419808b.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 16:43:10 +0100
+Subject: [PATCH] Remove virConnectPtr arg from virNWFilterDefParse*
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015108
+
+None of the virNWFilterDefParse* methods require a virConnectPtr
+arg, so just drop it
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit b77b16ce4166dcc87963ae5d279b77b162ddbb55)
+
+Conflicts:
+ tests/nwfilterxml2xmltest.c
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/nwfilter_conf.c | 15 ++++++---------
+ src/conf/nwfilter_conf.h | 6 ++----
+ src/nwfilter/nwfilter_driver.c | 2 +-
+ tests/nwfilterxml2xmltest.c | 2 +-
+ 4 files changed, 10 insertions(+), 15 deletions(-)
+
+diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
+index a3901d3..54a492d 100644
+--- a/src/conf/nwfilter_conf.c
++++ b/src/conf/nwfilter_conf.c
+@@ -2633,8 +2633,7 @@ cleanup:
+
+
+ static virNWFilterDefPtr
+-virNWFilterDefParse(virConnectPtr conn ATTRIBUTE_UNUSED,
+- const char *xmlStr,
++virNWFilterDefParse(const char *xmlStr,
+ const char *filename) {
+ virNWFilterDefPtr def = NULL;
+ xmlDocPtr xml;
+@@ -2649,18 +2648,16 @@ virNWFilterDefParse(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+
+ virNWFilterDefPtr
+-virNWFilterDefParseString(virConnectPtr conn,
+- const char *xmlStr)
++virNWFilterDefParseString(const char *xmlStr)
+ {
+- return virNWFilterDefParse(conn, xmlStr, NULL);
++ return virNWFilterDefParse(xmlStr, NULL);
+ }
+
+
+ virNWFilterDefPtr
+-virNWFilterDefParseFile(virConnectPtr conn,
+- const char *filename)
++virNWFilterDefParseFile(const char *filename)
+ {
+- return virNWFilterDefParse(conn, NULL, filename);
++ return virNWFilterDefParse(NULL, filename);
+ }
+
+
+@@ -3055,7 +3052,7 @@ virNWFilterObjLoad(virConnectPtr conn,
+ virNWFilterDefPtr def;
+ virNWFilterObjPtr nwfilter;
+
+- if (!(def = virNWFilterDefParseFile(conn, path))) {
++ if (!(def = virNWFilterDefParseFile(path))) {
+ return NULL;
+ }
+
+diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
+index 5d04cff..faa7527 100644
+--- a/src/conf/nwfilter_conf.h
++++ b/src/conf/nwfilter_conf.h
+@@ -713,10 +713,8 @@ int virNWFilterLoadAllConfigs(virConnectPtr conn,
+ char *virNWFilterConfigFile(const char *dir,
+ const char *name);
+
+-virNWFilterDefPtr virNWFilterDefParseString(virConnectPtr conn,
+- const char *xml);
+-virNWFilterDefPtr virNWFilterDefParseFile(virConnectPtr conn,
+- const char *filename);
++virNWFilterDefPtr virNWFilterDefParseString(const char *xml);
++virNWFilterDefPtr virNWFilterDefParseFile(const char *filename);
+
+ void virNWFilterObjLock(virNWFilterObjPtr obj);
+ void virNWFilterObjUnlock(virNWFilterObjPtr obj);
+diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
+index 9bb4b4e..2cae0d0 100644
+--- a/src/nwfilter/nwfilter_driver.c
++++ b/src/nwfilter/nwfilter_driver.c
+@@ -561,7 +561,7 @@ nwfilterDefineXML(virConnectPtr conn,
+ nwfilterDriverLock(driver);
+ virNWFilterCallbackDriversLock();
+
+- if (!(def = virNWFilterDefParseString(conn, xml)))
++ if (!(def = virNWFilterDefParseString(xml)))
+ goto cleanup;
+
+ if (virNWFilterDefineXMLEnsureACL(conn, def) < 0)
+diff --git a/tests/nwfilterxml2xmltest.c b/tests/nwfilterxml2xmltest.c
+index 5476284..68f74cc 100644
+--- a/tests/nwfilterxml2xmltest.c
++++ b/tests/nwfilterxml2xmltest.c
+@@ -36,7 +36,7 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
+
+ virResetLastError();
+
+- if (!(dev = virNWFilterDefParseString(NULL, inXmlData)))
++ if (!(dev = virNWFilterDefParseString(inXmlData)))
+ goto fail;
+
+ if (!!virGetLastError() != expect_error)
+--
+1.8.3.2
+
--- /dev/null
+From b0d1a7dcdb4a8a5a9dca85ce9f2e2b3204f07eb9 Mon Sep 17 00:00:00 2001
+Message-Id: <b0d1a7dcdb4a8a5a9dca85ce9f2e2b3204f07eb9.1377873641.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:25 -0400
+Subject: [PATCH] Report secret usage error message similarly
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000168
+
+Each of the modules handled reporting error messages from the secret fetching
+slightly differently with respect to the error. Provide a similar message
+for each error case and provide as much data as possible.
+
+(cherry picked from commit 1fa7946fbacedfa9f0caa83036816c46a617fb82)
+---
+ src/qemu/qemu_command.c | 26 ++++++++++++++++++++------
+ src/storage/storage_backend_iscsi.c | 26 ++++++++++++++++++++------
+ src/storage/storage_backend_rbd.c | 28 ++++++++++++++++++++++------
+ 3 files changed, 62 insertions(+), 18 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index b811e1d..43934f1 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -3043,18 +3043,32 @@ qemuGetSecretString(virConnectPtr conn,
+ }
+
+ if (!sec) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("%s username '%s' specified but secret not found"),
+- scheme, username);
++ if (diskSecretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("%s no secret matches uuid '%s'"),
++ scheme, uuid);
++ } else {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("%s no secret matches usage value '%s'"),
++ scheme, usage);
++ }
+ goto cleanup;
+ }
+
+ secret = (char *)conn->secretDriver->secretGetValue(sec, &secret_size, 0,
+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
+ if (!secret) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("could not get value of the secret for username %s"),
+- username);
++ if (diskSecretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get value of the secret for "
++ "username '%s' using uuid '%s'"),
++ username, uuid);
++ } else {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get value of the secret for "
++ "username '%s' using usage value '%s'"),
++ username, usage);
++ }
+ goto cleanup;
+ }
+
+diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
+index ee8dd2e..e71ea46 100644
+--- a/src/storage/storage_backend_iscsi.c
++++ b/src/storage/storage_backend_iscsi.c
+@@ -732,15 +732,29 @@ virStorageBackendISCSISetAuth(const char *portal,
+ conn->secretDriver->secretGetValue(secret, &secret_size, 0,
+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
+ if (!secret_value) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("could not get the value of the secret "
+- "for username %s"), chap.username);
++ if (chap.secret.uuidUsable) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get the value of the secret "
++ "for username %s using uuid '%s'"),
++ chap.username, chap.secret.uuid);
++ } else {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get the value of the secret "
++ "for username %s using usage value '%s'"),
++ chap.username, chap.secret.usage);
++ }
+ goto cleanup;
+ }
+ } else {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("username '%s' specified but secret not found"),
+- chap.username);
++ if (chap.secret.uuidUsable) {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("no secret matches uuid '%s'"),
++ chap.secret.uuid);
++ } else {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("no secret matches usage value '%s'"),
++ chap.secret.usage);
++ }
+ goto cleanup;
+ }
+
+diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
+index e3340f6..d9e1789 100644
+--- a/src/storage/storage_backend_rbd.c
++++ b/src/storage/storage_backend_rbd.c
+@@ -91,8 +91,15 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
+ }
+
+ if (secret == NULL) {
+- virReportError(VIR_ERR_NO_SECRET, "%s",
+- _("failed to find the secret"));
++ if (pool->def->source.auth.cephx.secret.uuidUsable) {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("no secret matches uuid '%s'"),
++ pool->def->source.auth.cephx.secret.uuid);
++ } else {
++ virReportError(VIR_ERR_NO_SECRET,
++ _("no secret matches usage value '%s'"),
++ pool->def->source.auth.cephx.secret.usage);
++ }
+ goto cleanup;
+ }
+
+@@ -100,10 +107,19 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
+
+ if (!secret_value) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("could not get the value of the secret "
+- "for username %s"),
+- pool->def->source.auth.cephx.username);
++ if (pool->def->source.auth.cephx.secret.uuidUsable) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get the value of the secret "
++ "for username '%s' using uuid '%s'"),
++ pool->def->source.auth.cephx.username,
++ pool->def->source.auth.cephx.secret.uuid);
++ } else {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("could not get the value of the secret "
++ "for username '%s' using usage value '%s'"),
++ pool->def->source.auth.cephx.username,
++ pool->def->source.auth.cephx.secret.usage);
++ }
+ goto cleanup;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From d6ded4029afabd123c5578a33c4c7f9a6468044b Mon Sep 17 00:00:00 2001
+Message-Id: <d6ded4029afabd123c5578a33c4c7f9a6468044b.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 17:17:30 +0100
+Subject: [PATCH] Retry veth device creation on failure
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+The veth device creation code run in two steps, first it looks
+for two free veth device names, then it runs ip link to create
+the veth pair. There is an obvious race between finding free
+names and creating them, when guests are started in parallel.
+
+Rewrite the code to loop and re-try creation if it fails, to
+deal with the race condition.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit f2e53555eb6971635e526e93f9de07a76daf61cb)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virnetdevveth.c | 151 +++++++++++++++++++++++++++++------------------
+ 1 file changed, 92 insertions(+), 59 deletions(-)
+
+diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
+index c0d32c4..1ccfc54 100644
+--- a/src/util/virnetdevveth.c
++++ b/src/util/virnetdevveth.c
+@@ -33,13 +33,26 @@
+ #include "virfile.h"
+ #include "virstring.h"
+ #include "virutil.h"
++#include "virnetdev.h"
+
+ #define VIR_FROM_THIS VIR_FROM_NONE
+
+ /* Functions */
++
++static int virNetDevVethExists(int devNum)
++{
++ int ret;
++ char *path = NULL;
++ if (virAsprintf(&path, "/sys/class/net/veth%d/", devNum) < 0)
++ return -1;
++ ret = virFileExists(path) ? 1 : 0;
++ VIR_DEBUG("Checked dev veth%d usage: %d", devNum, ret);
++ VIR_FREE(path);
++ return ret;
++}
++
+ /**
+- * virNetDevVethGetFreeName:
+- * @veth: pointer to store returned name for veth device
++ * virNetDevVethGetFreeNum:
+ * @startDev: device number to start at (x in vethx)
+ *
+ * Looks in /sys/class/net/ to find the first available veth device
+@@ -47,25 +60,23 @@
+ *
+ * Returns non-negative device number on success or -1 in case of error
+ */
+-static int virNetDevVethGetFreeName(char **veth, int startDev)
++static int virNetDevVethGetFreeNum(int startDev)
+ {
+- int devNum = startDev-1;
+- char *path = NULL;
++ int devNum;
+
+- VIR_DEBUG("Find free from veth%d", startDev);
+- do {
+- VIR_FREE(path);
+- ++devNum;
+- if (virAsprintf(&path, "/sys/class/net/veth%d/", devNum) < 0)
+- return -1;
+- VIR_DEBUG("Probe %s", path);
+- } while (virFileExists(path));
+- VIR_FREE(path);
++#define MAX_DEV_NUM 65536
+
+- if (virAsprintf(veth, "veth%d", devNum) < 0)
+- return -1;
++ for (devNum = startDev; devNum < MAX_DEV_NUM; devNum++) {
++ int ret = virNetDevVethExists(devNum);
++ if (ret < 0)
++ return -1;
++ if (ret == 0)
++ return devNum;
++ }
+
+- return devNum;
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("No free veth devices available"));
++ return -1;
+ }
+
+ /**
+@@ -95,57 +106,79 @@ static int virNetDevVethGetFreeName(char **veth, int startDev)
+ */
+ int virNetDevVethCreate(char** veth1, char** veth2)
+ {
+- int rc = -1;
+- const char *argv[] = {
+- "ip", "link", "add", NULL, "type", "veth", "peer", "name", NULL, NULL
+- };
+- int vethDev = 0;
+- bool veth1_alloc = false;
+- bool veth2_alloc = false;
+-
+- VIR_DEBUG("Host: %s guest: %s", NULLSTR(*veth1), NULLSTR(*veth2));
+-
+- if (*veth1 == NULL) {
+- if ((vethDev = virNetDevVethGetFreeName(veth1, vethDev)) < 0)
+- goto cleanup;
+- VIR_DEBUG("Assigned host: %s", *veth1);
+- veth1_alloc = true;
+- vethDev++;
+- }
+- argv[3] = *veth1;
++ int ret = -1;
++ char *veth1auto = NULL;
++ char *veth2auto = NULL;
++ int vethNum = 0;
++ size_t i;
++
++ /*
++ * We might race with other containers, but this is reasonably
++ * unlikely, so don't do too many retries for device creation
++ */
++#define MAX_VETH_RETRIES 10
++
++ for (i = 0; i < MAX_VETH_RETRIES; i++) {
++ int status;
++ if (!*veth1) {
++ int veth1num;
++ if ((veth1num = virNetDevVethGetFreeNum(vethNum)) < 0)
++ goto cleanup;
++
++ if (virAsprintf(&veth1auto, "veth%d", veth1num) < 0)
++ goto cleanup;
++ vethNum = veth1num + 1;
++ }
++ if (!*veth2) {
++ int veth2num;
++ if ((veth2num = virNetDevVethGetFreeNum(vethNum)) < 0)
++ goto cleanup;
++
++ if (virAsprintf(&veth2auto, "veth%d", veth2num) < 0)
++ goto cleanup;
++ vethNum = veth2num + 1;
++ }
++
++ virCommandPtr cmd = virCommandNew("ip");
++ virCommandAddArgList(cmd, "link", "add",
++ *veth1 ? *veth1 : veth1auto,
++ "type", "veth", "peer", "name",
++ *veth2 ? *veth2 : veth2auto,
++ NULL);
+
+- while (*veth2 == NULL) {
+- if ((vethDev = virNetDevVethGetFreeName(veth2, vethDev)) < 0) {
+- if (veth1_alloc)
+- VIR_FREE(*veth1);
++ if (virCommandRun(cmd, &status) < 0)
+ goto cleanup;
+- }
+
+- /* Just make sure they didn't accidentally get same name */
+- if (STREQ(*veth1, *veth2)) {
+- vethDev++;
+- VIR_FREE(*veth2);
+- continue;
++ if (status == 0) {
++ if (veth1auto) {
++ *veth1 = veth1auto;
++ veth1auto = NULL;
++ }
++ if (veth2auto) {
++ *veth2 = veth2auto;
++ veth2auto = NULL;
++ }
++ VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2);
++ ret = 0;
++ goto cleanup;
+ }
+
+- VIR_DEBUG("Assigned guest: %s", *veth2);
+- veth2_alloc = true;
+- }
+- argv[8] = *veth2;
+-
+- VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2);
+- if (virRun(argv, NULL) < 0) {
+- if (veth1_alloc)
+- VIR_FREE(*veth1);
+- if (veth2_alloc)
+- VIR_FREE(*veth2);
+- goto cleanup;
++ VIR_DEBUG("Failed to create veth host: %s guest: %s: %d",
++ *veth1 ? *veth1 : veth1auto,
++ *veth1 ? *veth1 : veth1auto,
++ status);
++ VIR_FREE(veth1auto);
++ VIR_FREE(veth2auto);
+ }
+
+- rc = 0;
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Failed to allocate free veth pair after %d attempts"),
++ MAX_VETH_RETRIES);
+
+ cleanup:
+- return rc;
++ VIR_FREE(veth1auto);
++ VIR_FREE(veth2auto);
++ return ret;
+ }
+
+ /**
+--
+1.8.3.2
+
--- /dev/null
+From 5315fe88fe6ca28ad50c2229b08f2bb914f938c9 Mon Sep 17 00:00:00 2001
+Message-Id: <5315fe88fe6ca28ad50c2229b08f2bb914f938c9.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Mon, 26 Aug 2013 15:11:19 +0200
+Subject: [PATCH] Reverse logic allowing partial DHCP host XML
+
+Before, missing attributes were only OK when parsing entries
+for adding (but then rejected by the network def <-> XML round
+trip verification). Entries for modification and deletion
+required all of them.
+
+Now, deletion works with missing attributes, as long as
+the host is uniquely identified.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001078
+
+(cherry picked from commit cf602e7c597830a2d949017fe71f06b5f542c805)
+---
+ src/conf/network_conf.c | 21 +++++----------------
+ 1 file changed, 5 insertions(+), 16 deletions(-)
+
+diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
+index b903df9..b358393 100644
+--- a/src/conf/network_conf.c
++++ b/src/conf/network_conf.c
+@@ -3297,6 +3297,7 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
+ int ret = -1;
+ virNetworkIpDefPtr ipdef = virNetworkIpDefByIndex(def, parentIndex);
+ virNetworkDHCPHostDef host;
++ bool partialOkay = (command == VIR_NETWORK_UPDATE_COMMAND_DELETE);
+
+ memset(&host, 0, sizeof(host));
+
+@@ -3307,13 +3308,11 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
+ if (!ipdef)
+ goto cleanup;
+
+- /* parse the xml into a virNetworkDHCPHostDef */
+- if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
++ if (virNetworkDHCPHostDefParseXML(def->name, ipdef, ctxt->node,
++ &host, partialOkay) < 0)
++ goto cleanup;
+
+- if (virNetworkDHCPHostDefParseXML(def->name, ipdef,
+- ctxt->node, &host, false) < 0) {
+- goto cleanup;
+- }
++ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+
+ /* search for the entry with this (mac|name),
+ * and update the IP+(mac|name) */
+@@ -3345,11 +3344,6 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
+ } else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
+ (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
+
+- if (virNetworkDHCPHostDefParseXML(def->name, ipdef,
+- ctxt->node, &host, true) < 0) {
+- goto cleanup;
+- }
+-
+ /* log error if an entry with same name/address/ip already exists */
+ for (i = 0; i < ipdef->nhosts; i++) {
+ if ((host.mac &&
+@@ -3379,11 +3373,6 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
+ goto cleanup;
+ } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+- if (virNetworkDHCPHostDefParseXML(def->name, ipdef,
+- ctxt->node, &host, false) < 0) {
+- goto cleanup;
+- }
+-
+ /* find matching entry - all specified attributes must match */
+ for (i = 0; i < ipdef->nhosts; i++) {
+ if ((!host.mac ||
+--
+1.8.3.2
+
--- /dev/null
+From 1a092cd295fe4f13238d8147b1b2a0247394b0ca Mon Sep 17 00:00:00 2001
+Message-Id: <1a092cd295fe4f13238d8147b1b2a0247394b0ca.1383321464.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Wed, 30 Oct 2013 17:01:47 +0000
+Subject: [PATCH] Set a sane $PATH for virt-login-shell
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+The virt-login-shell binary shouldn't need to execute programs
+relying on $PATH, but just in case set a fixed $PATH value
+of /bin:/usr/bin
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit d665003da1359410bc4036895a648a7d7256ddaa)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tools/virt-login-shell.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+index c2c9947..baa6202 100644
+--- a/tools/virt-login-shell.c
++++ b/tools/virt-login-shell.c
+@@ -208,6 +208,8 @@ main(int argc, char **argv)
+ return EXIT_FAILURE;
+ }
+
++ setenv("PATH", "/bin:/usr/bin", 1);
++
+ virSetErrorFunc(NULL, NULL);
+ virSetErrorLogPriorityFunc(NULL);
+
+--
+1.8.4.2
+
--- /dev/null
+From 2b2f4867f47391a4b9e608d08db63b0fb4b70c14 Mon Sep 17 00:00:00 2001
+Message-Id: <2b2f4867f47391a4b9e608d08db63b0fb4b70c14.1377873641.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:14:46 +0100
+Subject: [PATCH] Set security label on FD for virDomainOpenGraphics
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=999925
+
+The virDomainOpenGraphics method accepts a UNIX socket FD from
+the client app. It must set the label on this FD otherwise QEMU
+will be prevented from receiving it with recvmsg.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit b6b94374b3bf6b44633ee99a68868141b6cd9ed8)
+---
+ src/qemu/qemu_driver.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 5634abf..99cce90 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -14841,6 +14841,10 @@ qemuDomainOpenGraphics(virDomainPtr dom,
+ goto cleanup;
+ }
+
++ if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
++ fd) < 0)
++ goto cleanup;
++
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+ qemuDomainObjEnterMonitor(driver, vm);
+--
+1.8.3.2
+
--- /dev/null
+From 0ef1dcbe3a13878f4a2c22ea38d113e92424be70 Mon Sep 17 00:00:00 2001
+Message-Id: <0ef1dcbe3a13878f4a2c22ea38d113e92424be70.1377873637.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:45 +0100
+Subject: [PATCH] Split TLS test into two separate tests
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+The virnettlscontexttest.c tests both virNetTLSContext
+and virNetTLSSession functionality. Split into two
+separate tests, to make the code size more manageable
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 236da82dae14a36cf373e3e7af622d9d6f40ecb8)
+---
+ cfg.mk | 2 +-
+ tests/Makefile.am | 17 +-
+ tests/virnettlscontexttest.c | 787 +------------------------------------------
+ tests/virnettlshelpers.c | 420 +++++++++++++++++++++++
+ tests/virnettlshelpers.h | 79 +++++
+ tests/virnettlssessiontest.c | 414 +++++++++++++++++++++++
+ 6 files changed, 945 insertions(+), 774 deletions(-)
+ create mode 100644 tests/virnettlshelpers.c
+ create mode 100644 tests/virnettlshelpers.h
+ create mode 100644 tests/virnettlssessiontest.c
+
+diff --git a/cfg.mk b/cfg.mk
+index 13de268..c59d432 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -899,7 +899,7 @@ $(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protoco
+ exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$
+
+ _src1=libvirt|fdstream|qemu/qemu_monitor|util/(vircommand|virfile)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon
+-_test1=shunloadtest|virnettlscontexttest|vircgroupmock
++_test1=shunloadtest|virnettlscontexttest|virnettlssessiontest|vircgroupmock
+ exclude_file_name_regexp--sc_avoid_write = \
+ ^(src/($(_src1))|daemon/libvirtd|tools/console|tests/($(_test1)))\.c$$
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 5ea806e..efd28e3 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -134,7 +134,7 @@ test_programs += virdbustest \
+ endif
+
+ if WITH_GNUTLS
+-test_programs += virnettlscontexttest
++test_programs += virnettlscontexttest virnettlssessiontest
+ endif
+
+ if WITH_SECDRIVER_SELINUX
+@@ -592,17 +592,28 @@ virnetsockettest_LDADD = $(LDADDS)
+
+ if WITH_GNUTLS
+ virnettlscontexttest_SOURCES = \
+- virnettlscontexttest.c testutils.h testutils.c
++ virnettlscontexttest.c \
++ virnettlshelpers.h virnettlshelpers.c \
++ testutils.h testutils.c
+ virnettlscontexttest_LDADD = $(LDADDS)
++virnettlssessiontest_SOURCES = \
++ virnettlssessiontest.c \
++ virnettlshelpers.h virnettlshelpers.c \
++ testutils.h testutils.c
++virnettlssessiontest_LDADD = $(LDADDS)
+ if HAVE_LIBTASN1
+ virnettlscontexttest_SOURCES += pkix_asn1_tab.c
+ virnettlscontexttest_LDADD += -ltasn1
++virnettlssessiontest_SOURCES += pkix_asn1_tab.c
++virnettlssessiontest_LDADD += -ltasn1
+ else
+ EXTRA_DIST += pkix_asn1_tab.c
+ endif
+ else
+ EXTRA_DIST += \
+- virnettlscontexttest.c testutils.h testutils.c pkix_asn1_tab.c
++ virnettlscontexttest.c virnettlssessiontest.c \
++ virnettlshelpers.h virnettlshelpers.c \
++ testutils.h testutils.c pkix_asn1_tab.c
+ endif
+
+ virtimetest_SOURCES = \
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 908432b..0a0d31a 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -23,10 +23,9 @@
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <sys/socket.h>
+-#include <gnutls/gnutls.h>
+-#include <gnutls/x509.h>
+
+ #include "testutils.h"
++#include "virnettlshelpers.h"
+ #include "virutil.h"
+ #include "virerror.h"
+ #include "viralloc.h"
+@@ -34,409 +33,13 @@
+ #include "virfile.h"
+ #include "vircommand.h"
+ #include "virsocketaddr.h"
+-#include "gnutls_1_0_compat.h"
+
+ #if !defined WIN32 && HAVE_LIBTASN1_H && LIBGNUTLS_VERSION_NUMBER >= 0x020600
+-# include <libtasn1.h>
+
+ # include "rpc/virnettlscontext.h"
+
+ # define VIR_FROM_THIS VIR_FROM_RPC
+
+-const char *keyfile = abs_builddir "/virnettlscontexttest-key.pem";
+-
+-/*
+- * These store some static data that is needed when
+- * encoding extensions in the x509 certs
+- */
+-ASN1_TYPE pkix_asn1;
+-extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
+-
+-/*
+- * To avoid consuming random entropy to generate keys,
+- * here's one we prepared earlier :-)
+- */
+-gnutls_x509_privkey_t privkey;
+-# define PRIVATE_KEY \
+- "-----BEGIN PRIVATE KEY-----\n" \
+- "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVcr\n" \
+- "BL40Tm6yq88FBhJNw1aaoCjmtg0l4dWQZ/e9Fimx4ARxFpT+ji4FE\n" \
+- "Cgl9s/SGqC+1nvlkm9ViSo0j7MKDbnDB+VRHDvMAzQhA2X7e8M0n9\n" \
+- "rPolUY2lIVC83q0BBaOBkCj2RSmT2xTEbbC2xLukSrg2WP/ihVOxc\n" \
+- "kXRuyFtzAgMBAAECgYB7slBexDwXrtItAMIH6m/U+LUpNe0Xx48OL\n" \
+- "IOn4a4whNgO/o84uIwygUK27ZGFZT0kAGAk8CdF9hA6ArcbQ62s1H\n" \
+- "myxrUbF9/mrLsQw1NEqpuUk9Ay2Tx5U/wPx35S3W/X2AvR/ZpTnCn\n" \
+- "2q/7ym9fyiSoj86drD7BTvmKXlOnOwQJBAPOFMp4mMa9NGpGuEssO\n" \
+- "m3Uwbp6lhcP0cA9MK+iOmeANpoKWfBdk5O34VbmeXnGYWEkrnX+9J\n" \
+- "bM4wVhnnBWtgBMCQQC+qAEmvwcfhauERKYznMVUVksyeuhxhCe7EK\n" \
+- "mPh+U2+g0WwdKvGDgO0PPt1gq0ILEjspMDeMHVdTwkaVBo/uMhAkA\n" \
+- "Z5SsZyCP2aTOPFDypXRdI4eqRcjaEPOUBq27r3uYb/jeboVb2weLa\n" \
+- "L1MmVuHiIHoa5clswPdWVI2y0em2IGoDAkBPSp/v9VKJEZabk9Frd\n" \
+- "a+7u4fanrM9QrEjY3KhduslSilXZZSxrWjjAJPyPiqFb3M8XXA26W\n" \
+- "nz1KYGnqYKhLcBAkB7dt57n9xfrhDpuyVEv+Uv1D3VVAhZlsaZ5Pp\n" \
+- "dcrhrkJn2sa/+O8OKvdrPSeeu/N5WwYhJf61+CPoenMp7IFci\n" \
+- "-----END PRIVATE KEY-----\n"
+-
+-
+-/*
+- * This contains parameter about how to generate
+- * certificates.
+- */
+-struct testTLSCertReq {
+- gnutls_x509_crt_t crt;
+- gnutls_x509_crt_t cacrt; /* If not set, then the cert will be self-signed */
+-
+- const char *filename;
+-
+- /* Identifying information */
+- const char *country;
+- const char *cn;
+- const char *altname1;
+- const char *altname2;
+- const char *ipaddr1;
+- const char *ipaddr2;
+-
+- /* Basic constraints */
+- bool basicConstraintsEnable;
+- bool basicConstraintsCritical;
+- bool basicConstraintsIsCA;
+-
+- /* Key usage */
+- bool keyUsageEnable;
+- bool keyUsageCritical;
+- int keyUsageValue;
+-
+- /* Key purpose (aka Extended key usage) */
+- bool keyPurposeEnable;
+- bool keyPurposeCritical;
+- const char *keyPurposeOID1;
+- const char *keyPurposeOID2;
+-
+- /* zero for current time, or non-zero for hours from now */
+- int start_offset;
+- /* zero for 24 hours from now, or non-zero for hours from now */
+- int expire_offset;
+-};
+-
+-
+-/*
+- * Turns an ASN1 object into a DER encoded byte array
+- */
+-static void testTLSDerEncode(ASN1_TYPE src,
+- const char *src_name,
+- gnutls_datum_t * res)
+-{
+- int size;
+- char *data = NULL;
+-
+- size = 0;
+- asn1_der_coding(src, src_name, NULL, &size, NULL);
+-
+- if (VIR_ALLOC_N(data, size) < 0)
+- abort();
+-
+- asn1_der_coding(src, src_name, data, &size, NULL);
+-
+- res->data = (unsigned char *)data;
+- res->size = size;
+-}
+-
+-
+-/*
+- * This is a fairly lame x509 certificate generator.
+- *
+- * Do not copy/use this code for generating real certificates
+- * since it leaves out many things that you would want in
+- * certificates for real world usage.
+- *
+- * This is good enough only for doing tests of the libvirt
+- * TLS certificate code
+- */
+-static void
+-testTLSGenerateCert(struct testTLSCertReq *req)
+-{
+- gnutls_x509_crt_t crt;
+- int err;
+- static char buffer[1024*1024];
+- size_t size = sizeof(buffer);
+- char serial[5] = { 1, 2, 3, 4, 0 };
+- gnutls_datum_t der;
+- time_t start = time(NULL) + (60*60*req->start_offset);
+- time_t expire = time(NULL) + (60*60*(req->expire_offset
+- ? req->expire_offset : 24));
+-
+- /*
+- * Prepare our new certificate object
+- */
+- if ((err = gnutls_x509_crt_init(&crt)) < 0) {
+- VIR_WARN("Failed to initialize certificate %s", gnutls_strerror(err));
+- abort();
+- }
+- if ((err = gnutls_x509_crt_set_key(crt, privkey)) < 0) {
+- VIR_WARN("Failed to set certificate key %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- /*
+- * A v3 certificate is required in order to be able
+- * set any of the basic constraints, key purpose and
+- * key usage data
+- */
+- gnutls_x509_crt_set_version(crt, 3);
+-
+- if (req->country) {
+- if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
+- req->country, strlen(req->country))) < 0) {
+- VIR_WARN("Failed to set certificate country name %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+- if (req->cn) {
+- if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
+- req->cn, strlen(req->cn))) < 0) {
+- VIR_WARN("Failed to set certificate common name %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+-
+- /*
+- * Setup the subject altnames, which are used
+- * for hostname checks in live sessions
+- */
+- if (req->altname1) {
+- if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
+- req->altname1,
+- strlen(req->altname1),
+- GNUTLS_FSAN_APPEND))) {
+- VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+- if (req->altname2) {
+- if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
+- req->altname2,
+- strlen(req->altname2),
+- GNUTLS_FSAN_APPEND))) {
+- VIR_WARN("Failed to set certificate %s alt name", gnutls_strerror(err));
+- abort();
+- }
+- }
+-
+- /*
+- * IP address need to be put into the cert in their
+- * raw byte form, not strings, hence this is a little
+- * more complicated
+- */
+- if (req->ipaddr1) {
+- virSocketAddr addr;
+- char *data;
+- int len;
+- if (virSocketAddrParse(&addr, req->ipaddr1, 0) < 0) {
+- VIR_WARN("Cannot parse %s", req->ipaddr1);
+- abort();
+- }
+-
+- if (addr.data.sa.sa_family == AF_INET) {
+- data = (char*)&addr.data.inet4.sin_addr;
+- len = 4;
+- } else {
+- data = (char*)&addr.data.inet6.sin6_addr;
+- len = 16;
+- }
+-
+- if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
+- data, len, GNUTLS_FSAN_APPEND))) {
+- VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+- if (req->ipaddr2) {
+- virSocketAddr addr;
+- char *data;
+- int len;
+- if (virSocketAddrParse(&addr, req->ipaddr2, 0) < 0) {
+- VIR_WARN("Cannot parse %s", req->ipaddr2);
+- abort();
+- }
+-
+- if (addr.data.sa.sa_family == AF_INET) {
+- data = (char*)&addr.data.inet4.sin_addr;
+- len = 4;
+- } else {
+- data = (char*)&addr.data.inet6.sin6_addr;
+- len = 16;
+- }
+-
+- if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
+- data, len, GNUTLS_FSAN_APPEND))) {
+- VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+-
+-
+- /*
+- * Basic constraints are used to decide if the cert
+- * is for a CA or not. We can't use the convenient
+- * gnutls API for setting this, since it hardcodes
+- * the 'critical' field which we want control over
+- */
+- if (req->basicConstraintsEnable) {
+- ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+-
+- asn1_create_element(pkix_asn1, "PKIX1.BasicConstraints", &ext);
+- asn1_write_value(ext, "cA", req->basicConstraintsIsCA ? "TRUE" : "FALSE", 1);
+- asn1_write_value(ext, "pathLenConstraint", NULL, 0);
+- testTLSDerEncode(ext, "", &der);
+- if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
+- "2.5.29.19",
+- der.data,
+- der.size,
+- req->basicConstraintsCritical)) < 0) {
+- VIR_WARN("Failed to set certificate basic constraints %s", gnutls_strerror(err));
+- VIR_FREE(der.data);
+- abort();
+- }
+- asn1_delete_structure(&ext);
+- VIR_FREE(der.data);
+- }
+-
+- /*
+- * Next up the key usage extension. Again we can't
+- * use the gnutls API since it hardcodes the extension
+- * to be 'critical'
+- */
+- if (req->keyUsageEnable) {
+- ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+- char str[2];
+-
+- str[0] = req->keyUsageValue & 0xff;
+- str[1] = (req->keyUsageValue >> 8) & 0xff;
+-
+- asn1_create_element(pkix_asn1, "PKIX1.KeyUsage", &ext);
+- asn1_write_value(ext, "", str, 9);
+- testTLSDerEncode(ext, "", &der);
+- if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
+- "2.5.29.15",
+- der.data,
+- der.size,
+- req->keyUsageCritical)) < 0) {
+- VIR_WARN("Failed to set certificate key usage %s", gnutls_strerror(err));
+- VIR_FREE(der.data);
+- abort();
+- }
+- asn1_delete_structure(&ext);
+- VIR_FREE(der.data);
+- }
+-
+- /*
+- * Finally the key purpose extension. This time
+- * gnutls has the opposite problem, always hardcoding
+- * it to be non-critical. So once again we have to
+- * set this the hard way building up ASN1 data ourselves
+- */
+- if (req->keyPurposeEnable) {
+- ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+-
+- asn1_create_element(pkix_asn1, "PKIX1.ExtKeyUsageSyntax", &ext);
+- if (req->keyPurposeOID1) {
+- asn1_write_value(ext, "", "NEW", 1);
+- asn1_write_value(ext, "?LAST", req->keyPurposeOID1, 1);
+- }
+- if (req->keyPurposeOID2) {
+- asn1_write_value(ext, "", "NEW", 1);
+- asn1_write_value(ext, "?LAST", req->keyPurposeOID2, 1);
+- }
+- testTLSDerEncode(ext, "", &der);
+- if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
+- "2.5.29.37",
+- der.data,
+- der.size,
+- req->keyPurposeCritical)) < 0) {
+- VIR_WARN("Failed to set certificate key purpose %s", gnutls_strerror(err));
+- VIR_FREE(der.data);
+- abort();
+- }
+- asn1_delete_structure(&ext);
+- VIR_FREE(der.data);
+- }
+-
+- /*
+- * Any old serial number will do, so lets pick 5
+- */
+- if ((err = gnutls_x509_crt_set_serial(crt, serial, 5)) < 0) {
+- VIR_WARN("Failed to set certificate serial %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- if ((err = gnutls_x509_crt_set_activation_time(crt, start)) < 0) {
+- VIR_WARN("Failed to set certificate activation %s", gnutls_strerror(err));
+- abort();
+- }
+- if ((err = gnutls_x509_crt_set_expiration_time(crt, expire)) < 0) {
+- VIR_WARN("Failed to set certificate expiration %s", gnutls_strerror(err));
+- abort();
+- }
+-
+-
+- /*
+- * If no 'cart' is set then we are self signing
+- * the cert. This is done for CA certs
+- */
+- if ((err = gnutls_x509_crt_sign(crt, req->cacrt ? req->cacrt : crt, privkey) < 0)) {
+- VIR_WARN("Failed to sign certificate %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- /*
+- * Finally write the new cert out to disk
+- */
+- if ((err = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &size) < 0)) {
+- VIR_WARN("Failed to export certificate %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- if (virFileWriteStr(req->filename, buffer, 0600) < 0) {
+- VIR_WARN("Failed to write certificate %s %s", req->filename, gnutls_strerror(err));
+- abort();
+- }
+-
+- req->crt = crt;
+- return;
+-}
+-
+-
+-/*
+- * This loads the private key we defined earlier
+- */
+-static gnutls_x509_privkey_t testTLSLoadKey(void)
+-{
+- gnutls_x509_privkey_t key;
+- const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY, strlen(PRIVATE_KEY) };
+- int err;
+-
+- if ((err = gnutls_x509_privkey_init(&key)) < 0) {
+- VIR_WARN("Failed to init key %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- if ((err = gnutls_x509_privkey_import(key, &data,
+- GNUTLS_X509_FMT_PEM)) < 0) {
+- if (err != GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
+- VIR_WARN("Failed to import key %s", gnutls_strerror(err));
+- abort();
+- }
+-
+- if ((err = gnutls_x509_privkey_import_pkcs8(key, &data, GNUTLS_X509_FMT_PEM, NULL, 0)) < 0) {
+- VIR_WARN("Failed to import PKCS8 key %s", gnutls_strerror(err));
+- abort();
+- }
+- }
+-
+- return key;
+-}
+-
+-
+ struct testTLSContextData {
+ bool isServer;
+ struct testTLSCertReq careq;
+@@ -500,257 +103,19 @@ static int testTLSContextInit(const void *opaque)
+
+ cleanup:
+ virObjectUnref(ctxt);
+- gnutls_x509_crt_deinit(data->careq.crt);
+- gnutls_x509_crt_deinit(data->certreq.crt);
+- data->careq.crt = data->certreq.crt = NULL;
+- /* When troubleshooting this tests, we often want to leave the certs on disk */
+- if (getenv("VIRT_TEST_DEBUG_CERTS") == NULL) {
+- unlink(data->careq.filename);
+- unlink(data->certreq.filename);
+- }
++ testTLSDiscardCert(&data->careq);
++ testTLSDiscardCert(&data->certreq);
+ return ret;
+ }
+
+
+
+-struct testTLSSessionData {
+- struct testTLSCertReq careq;
+- struct testTLSCertReq othercareq;
+- struct testTLSCertReq serverreq;
+- struct testTLSCertReq clientreq;
+- bool expectServerFail;
+- bool expectClientFail;
+- const char *hostname;
+- const char *const* wildcards;
+-};
+-
+-
+-static ssize_t testWrite(const char *buf, size_t len, void *opaque)
+-{
+- int *fd = opaque;
+-
+- return write(*fd, buf, len);
+-}
+-
+-static ssize_t testRead(char *buf, size_t len, void *opaque)
+-{
+- int *fd = opaque;
+-
+- return read(*fd, buf, len);
+-}
+-
+-/*
+- * This tests validation checking of peer certificates
+- *
+- * This is replicating the checks that are done for an
+- * active TLS session after handshake completes. To
+- * simulate that we create our TLS contexts, skipping
+- * sanity checks. When then get a socketpair, and
+- * initiate a TLS session across them. Finally do
+- * do actual cert validation tests
+- */
+-static int testTLSSessionInit(const void *opaque)
+-{
+- struct testTLSSessionData *data = (struct testTLSSessionData *)opaque;
+- virNetTLSContextPtr clientCtxt = NULL;
+- virNetTLSContextPtr serverCtxt = NULL;
+- virNetTLSSessionPtr clientSess = NULL;
+- virNetTLSSessionPtr serverSess = NULL;
+- int ret = -1;
+- int channel[2];
+- bool clientShake = false;
+- bool serverShake = false;
+-
+-
+- /* We'll use this for our fake client-server connection */
+- if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) < 0)
+- abort();
+-
+- /*
+- * We have an evil loop to do the handshake in a single
+- * thread, so we need these non-blocking to avoid deadlock
+- * of ourselves
+- */
+- ignore_value(virSetNonBlock(channel[0]));
+- ignore_value(virSetNonBlock(channel[1]));
+-
+-
+- /* Generate all the certs we need for this test */
+- testTLSGenerateCert(&data->careq);
+- data->serverreq.cacrt = data->careq.crt;
+- testTLSGenerateCert(&data->serverreq);
+-
+- if (data->othercareq.filename) {
+- testTLSGenerateCert(&data->othercareq);
+- data->clientreq.cacrt = data->othercareq.crt;
+- } else {
+- data->clientreq.cacrt = data->careq.crt;
+- }
+- testTLSGenerateCert(&data->clientreq);
+-
+-
+- /* We skip initial sanity checks here because we
+- * want to make sure that problems are being
+- * detected at the TLS session validation stage
+- */
+- serverCtxt = virNetTLSContextNewServer(data->careq.filename,
+- NULL,
+- data->serverreq.filename,
+- keyfile,
+- data->wildcards,
+- false,
+- true);
+-
+- clientCtxt = virNetTLSContextNewClient(data->othercareq.filename ?
+- data->othercareq.filename :
+- data->careq.filename,
+- NULL,
+- data->clientreq.filename,
+- keyfile,
+- false,
+- true);
+-
+- if (!serverCtxt) {
+- VIR_WARN("Unexpected failure loading %s against %s",
+- data->careq.filename, data->serverreq.filename);
+- goto cleanup;
+- }
+- if (!clientCtxt) {
+- VIR_WARN("Unexpected failure loading %s against %s",
+- data->othercareq.filename ? data->othercareq.filename :
+- data->careq.filename, data->clientreq.filename);
+- goto cleanup;
+- }
+-
+-
+- /* Now the real part of the test, setup the sessions */
+- serverSess = virNetTLSSessionNew(serverCtxt, NULL);
+- clientSess = virNetTLSSessionNew(clientCtxt, data->hostname);
+-
+- if (!serverSess) {
+- VIR_WARN("Unexpected failure using %s against %s",
+- data->careq.filename, data->serverreq.filename);
+- goto cleanup;
+- }
+- if (!clientSess) {
+- VIR_WARN("Unexpected failure using %s against %s",
+- data->othercareq.filename ? data->othercareq.filename :
+- data->careq.filename, data->clientreq.filename);
+- goto cleanup;
+- }
+-
+- /* For handshake to work, we need to set the I/O callbacks
+- * to read/write over the socketpair
+- */
+- virNetTLSSessionSetIOCallbacks(serverSess, testWrite, testRead, &channel[0]);
+- virNetTLSSessionSetIOCallbacks(clientSess, testWrite, testRead, &channel[1]);
+-
+- /*
+- * Finally we loop around & around doing handshake on each
+- * session until we get an error, or the handshake completes.
+- * This relies on the socketpair being nonblocking to avoid
+- * deadlocking ourselves upon handshake
+- */
+- do {
+- int rv;
+- if (!serverShake) {
+- rv = virNetTLSSessionHandshake(serverSess);
+- if (rv < 0)
+- goto cleanup;
+- if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
+- serverShake = true;
+- }
+- if (!clientShake) {
+- rv = virNetTLSSessionHandshake(clientSess);
+- if (rv < 0)
+- goto cleanup;
+- if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
+- clientShake = true;
+- }
+- } while (!clientShake && !serverShake);
+-
+-
+- /* Finally make sure the server validation does what
+- * we were expecting
+- */
+- if (virNetTLSContextCheckCertificate(serverCtxt,
+- serverSess) < 0) {
+- if (!data->expectServerFail) {
+- VIR_WARN("Unexpected server cert check fail");
+- goto cleanup;
+- } else {
+- VIR_DEBUG("Got expected server cert fail");
+- }
+- } else {
+- if (data->expectServerFail) {
+- VIR_WARN("Expected server cert check fail");
+- goto cleanup;
+- } else {
+- VIR_DEBUG("Not unexpected server cert fail");
+- }
+- }
+-
+- /*
+- * And the same for the client validation check
+- */
+- if (virNetTLSContextCheckCertificate(clientCtxt,
+- clientSess) < 0) {
+- if (!data->expectClientFail) {
+- VIR_WARN("Unexpected client cert check fail");
+- goto cleanup;
+- } else {
+- VIR_DEBUG("Got expected client cert fail");
+- }
+- } else {
+- if (data->expectClientFail) {
+- VIR_WARN("Expected client cert check fail");
+- goto cleanup;
+- } else {
+- VIR_DEBUG("Not unexpected client cert fail");
+- }
+- }
+-
+- ret = 0;
+-
+-cleanup:
+- virObjectUnref(serverCtxt);
+- virObjectUnref(clientCtxt);
+- virObjectUnref(serverSess);
+- virObjectUnref(clientSess);
+- gnutls_x509_crt_deinit(data->careq.crt);
+- if (data->othercareq.filename)
+- gnutls_x509_crt_deinit(data->othercareq.crt);
+- gnutls_x509_crt_deinit(data->clientreq.crt);
+- gnutls_x509_crt_deinit(data->serverreq.crt);
+- data->careq.crt = data->othercareq.crt = data->clientreq.crt = data->serverreq.crt = NULL;
+-
+- /* When troubleshooting this tests, we often want to leave the certs on disk */
+- if (getenv("VIRT_TEST_DEBUG_CERTS") == NULL) {
+- unlink(data->careq.filename);
+- if (data->othercareq.filename)
+- unlink(data->othercareq.filename);
+- unlink(data->clientreq.filename);
+- unlink(data->serverreq.filename);
+- }
+- VIR_FORCE_CLOSE(channel[0]);
+- VIR_FORCE_CLOSE(channel[1]);
+- return ret;
+-}
+-
+-
+ static int
+ mymain(void)
+ {
+ int ret = 0;
+- if (asn1_array2tree(pkix_asn1_tab, &pkix_asn1, NULL) != ASN1_SUCCESS)
+- abort();
+
+- gnutls_global_init();
+-
+- privkey = testTLSLoadKey();
+-
+- if (virFileWriteStr(keyfile, PRIVATE_KEY, 0600) < 0)
+- return EXIT_FAILURE;
++ testTLSInit();
+
+ # define DO_CTX_TEST(_isServer, _caReq, _certReq, _expectFail) \
+ do { \
+@@ -763,40 +128,6 @@ mymain(void)
+ ret = -1; \
+ } while (0)
+
+-# define DO_SESS_TEST(_caReq, _serverReq, _clientReq, _expectServerFail,\
+- _expectClientFail, _hostname, _wildcards) \
+- do { \
+- static struct testTLSSessionData data; \
+- static struct testTLSCertReq other; \
+- data.careq = _caReq; \
+- data.othercareq = other; \
+- data.serverreq = _serverReq; \
+- data.clientreq = _clientReq; \
+- data.expectServerFail = _expectServerFail; \
+- data.expectClientFail = _expectClientFail; \
+- data.hostname = _hostname; \
+- data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
+- ret = -1; \
+- } while (0)
+-
+-# define DO_SESS_TEST_EXT(_caReq, _othercaReq, _serverReq, _clientReq, \
+- _expectServerFail, _expectClientFail, \
+- _hostname, _wildcards) \
+- do { \
+- static struct testTLSSessionData data; \
+- data.careq = _caReq; \
+- data.othercareq = _othercaReq; \
+- data.serverreq = _serverReq; \
+- data.clientreq = _clientReq; \
+- data.expectServerFail = _expectServerFail; \
+- data.expectClientFail = _expectClientFail; \
+- data.hostname = _hostname; \
+- data.wildcards = _wildcards; \
+- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
+- ret = -1; \
+- } while (0)
+-
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+@@ -850,24 +181,10 @@ mymain(void)
+ false, false, NULL, NULL,
+ 0, 0,
+ };
+- /* Basic:not-CA:not-critical */
+-# if 0
+- /* Default GNUTLS session config forbids use of CAs without
+- * basic constraints, so skip this otherwise valid test
+- */
++ /* Key usage:cert-sign:critical */
+ static struct testTLSCertReq cacert3req = {
+ NULL, NULL, "cacert3.pem", "UK",
+ "libvirt CA 3", NULL, NULL, NULL, NULL,
+- true, false, false,
+- false, false, 0,
+- false, false, NULL, NULL,
+- 0, 0,
+- };
+-# endif
+- /* Key usage:cert-sign:critical */
+- static struct testTLSCertReq cacert4req = {
+- NULL, NULL, "cacert4.pem", "UK",
+- "libvirt CA 4", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+@@ -876,35 +193,32 @@ mymain(void)
+
+ DO_CTX_TEST(true, cacert1req, servercertreq, false);
+ DO_CTX_TEST(true, cacert2req, servercertreq, false);
+-# if 0
+ DO_CTX_TEST(true, cacert3req, servercertreq, false);
+-# endif
+- DO_CTX_TEST(true, cacert4req, servercertreq, false);
+
+ /* Now some bad certs */
+
+ /* Key usage:dig-sig:not-critical */
+- static struct testTLSCertReq cacert5req = {
+- NULL, NULL, "cacert5.pem", "UK",
+- "libvirt CA 5", NULL, NULL, NULL, NULL,
++ static struct testTLSCertReq cacert4req = {
++ NULL, NULL, "cacert4.pem", "UK",
++ "libvirt CA 4", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, false, GNUTLS_KEY_DIGITAL_SIGNATURE,
+ false, false, NULL, NULL,
+ 0, 0,
+ };
+ /* no-basic */
+- static struct testTLSCertReq cacert6req = {
+- NULL, NULL, "cacert6.pem", "UK",
+- "libvirt CA 6", NULL, NULL, NULL, NULL,
++ static struct testTLSCertReq cacert5req = {
++ NULL, NULL, "cacert5.pem", "UK",
++ "libvirt CA 5", NULL, NULL, NULL, NULL,
+ false, false, false,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0,
+ };
+ /* Key usage:dig-sig:critical */
+- static struct testTLSCertReq cacert7req = {
+- NULL, NULL, "cacert7.pem", "UK",
+- "libvirt CA 7", NULL, NULL, NULL, NULL,
++ static struct testTLSCertReq cacert6req = {
++ NULL, NULL, "cacert6.pem", "UK",
++ "libvirt CA 6", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE,
+ false, false, NULL, NULL,
+@@ -916,9 +230,9 @@ mymain(void)
+ * be rejected. GNUTLS < 3 does not reject it and
+ * we don't anticipate them changing this behaviour
+ */
+- DO_CTX_TEST(true, cacert5req, servercertreq, GNUTLS_VERSION_MAJOR >= 3);
++ DO_CTX_TEST(true, cacert4req, servercertreq, GNUTLS_VERSION_MAJOR >= 3);
++ DO_CTX_TEST(true, cacert5req, servercertreq, true);
+ DO_CTX_TEST(true, cacert6req, servercertreq, true);
+- DO_CTX_TEST(true, cacert7req, servercertreq, true);
+
+
+ /* Various good servers */
+@@ -1200,74 +514,7 @@ mymain(void)
+ DO_CTX_TEST(true, cacertreq, servercertnewreq, true);
+ DO_CTX_TEST(false, cacertreq, clientcertnewreq, true);
+
+-
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL);
+- DO_SESS_TEST_EXT(cacertreq, cacert1req, servercertreq, clientcertreq, true, true, "libvirt.org", NULL);
+-
+- /* When an altname is set, the CN is ignored, so it must be duplicated
+- * as an altname for it to match */
+- static struct testTLSCertReq servercertalt1req = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf",
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
+- /* This intentionally doesn't replicate */
+- static struct testTLSCertReq servercertalt2req = {
+- NULL, NULL, "servercert.pem", "UK",
+- "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf",
+- true, true, false,
+- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+- 0, 0,
+- };
+-
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, true, "wiki.libvirt.org", NULL);
+-
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, true, "libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "www.libvirt.org", NULL);
+- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "wiki.libvirt.org", NULL);
+-
+- const char *const wildcards1[] = {
+- "C=UK,CN=dogfood",
+- NULL,
+- };
+- const char *const wildcards2[] = {
+- "C=UK,CN=libvirt",
+- NULL,
+- };
+- const char *const wildcards3[] = {
+- "C=UK,CN=dogfood",
+- "C=UK,CN=libvirt",
+- NULL,
+- };
+- const char *const wildcards4[] = {
+- "C=UK,CN=libvirtstuff",
+- NULL,
+- };
+- const char *const wildcards5[] = {
+- "C=UK,CN=libvirt*",
+- NULL,
+- };
+- const char *const wildcards6[] = {
+- "C=UK,CN=*virt*",
+- NULL,
+- };
+-
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards1);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards2);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards3);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards4);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5);
+- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6);
+-
+- unlink(keyfile);
+-
+- asn1_delete_structure(&pkix_asn1);
++ testTLSCleanup();
+
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+diff --git a/tests/virnettlshelpers.c b/tests/virnettlshelpers.c
+new file mode 100644
+index 0000000..96b2f6e
+--- /dev/null
++++ b/tests/virnettlshelpers.c
+@@ -0,0 +1,420 @@
++/*
++ * Copyright (C) 2011-2012 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Daniel P. Berrange <berrange@redhat.com>
++ */
++
++#include <config.h>
++
++#include <stdlib.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++
++#include "virnettlshelpers.h"
++#include "viralloc.h"
++#include "virlog.h"
++#include "virfile.h"
++#include "virsocketaddr.h"
++
++#if !defined WIN32 && HAVE_LIBTASN1_H && LIBGNUTLS_VERSION_NUMBER >= 0x020600
++
++# define VIR_FROM_THIS VIR_FROM_RPC
++
++const char *keyfile = abs_builddir "/virnettlscontexttest-key.pem";
++
++/*
++ * These store some static data that is needed when
++ * encoding extensions in the x509 certs
++ */
++ASN1_TYPE pkix_asn1;
++extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
++
++/*
++ * To avoid consuming random entropy to generate keys,
++ * here's one we prepared earlier :-)
++ */
++gnutls_x509_privkey_t privkey;
++# define PRIVATE_KEY \
++ "-----BEGIN PRIVATE KEY-----\n" \
++ "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVcr\n" \
++ "BL40Tm6yq88FBhJNw1aaoCjmtg0l4dWQZ/e9Fimx4ARxFpT+ji4FE\n" \
++ "Cgl9s/SGqC+1nvlkm9ViSo0j7MKDbnDB+VRHDvMAzQhA2X7e8M0n9\n" \
++ "rPolUY2lIVC83q0BBaOBkCj2RSmT2xTEbbC2xLukSrg2WP/ihVOxc\n" \
++ "kXRuyFtzAgMBAAECgYB7slBexDwXrtItAMIH6m/U+LUpNe0Xx48OL\n" \
++ "IOn4a4whNgO/o84uIwygUK27ZGFZT0kAGAk8CdF9hA6ArcbQ62s1H\n" \
++ "myxrUbF9/mrLsQw1NEqpuUk9Ay2Tx5U/wPx35S3W/X2AvR/ZpTnCn\n" \
++ "2q/7ym9fyiSoj86drD7BTvmKXlOnOwQJBAPOFMp4mMa9NGpGuEssO\n" \
++ "m3Uwbp6lhcP0cA9MK+iOmeANpoKWfBdk5O34VbmeXnGYWEkrnX+9J\n" \
++ "bM4wVhnnBWtgBMCQQC+qAEmvwcfhauERKYznMVUVksyeuhxhCe7EK\n" \
++ "mPh+U2+g0WwdKvGDgO0PPt1gq0ILEjspMDeMHVdTwkaVBo/uMhAkA\n" \
++ "Z5SsZyCP2aTOPFDypXRdI4eqRcjaEPOUBq27r3uYb/jeboVb2weLa\n" \
++ "L1MmVuHiIHoa5clswPdWVI2y0em2IGoDAkBPSp/v9VKJEZabk9Frd\n" \
++ "a+7u4fanrM9QrEjY3KhduslSilXZZSxrWjjAJPyPiqFb3M8XXA26W\n" \
++ "nz1KYGnqYKhLcBAkB7dt57n9xfrhDpuyVEv+Uv1D3VVAhZlsaZ5Pp\n" \
++ "dcrhrkJn2sa/+O8OKvdrPSeeu/N5WwYhJf61+CPoenMp7IFci\n" \
++ "-----END PRIVATE KEY-----\n"
++
++/*
++ * This loads the private key we defined earlier
++ */
++static gnutls_x509_privkey_t testTLSLoadKey(void)
++{
++ gnutls_x509_privkey_t key;
++ const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY, strlen(PRIVATE_KEY) };
++ int err;
++
++ if ((err = gnutls_x509_privkey_init(&key)) < 0) {
++ VIR_WARN("Failed to init key %s", gnutls_strerror(err));
++ abort();
++ }
++
++ if ((err = gnutls_x509_privkey_import(key, &data,
++ GNUTLS_X509_FMT_PEM)) < 0) {
++ if (err != GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
++ VIR_WARN("Failed to import key %s", gnutls_strerror(err));
++ abort();
++ }
++
++ if ((err = gnutls_x509_privkey_import_pkcs8(key, &data, GNUTLS_X509_FMT_PEM, NULL, 0)) < 0) {
++ VIR_WARN("Failed to import PKCS8 key %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++
++ return key;
++}
++
++
++void testTLSInit(void)
++{
++ gnutls_global_init();
++
++ if (asn1_array2tree(pkix_asn1_tab, &pkix_asn1, NULL) != ASN1_SUCCESS)
++ abort();
++
++ privkey = testTLSLoadKey();
++ if (virFileWriteStr(keyfile, PRIVATE_KEY, 0600) < 0)
++ abort();
++}
++
++
++void testTLSCleanup(void)
++{
++ asn1_delete_structure(&pkix_asn1);
++ unlink(keyfile);
++}
++
++/*
++ * Turns an ASN1 object into a DER encoded byte array
++ */
++static void testTLSDerEncode(ASN1_TYPE src,
++ const char *src_name,
++ gnutls_datum_t * res)
++{
++ int size;
++ char *data = NULL;
++
++ size = 0;
++ asn1_der_coding(src, src_name, NULL, &size, NULL);
++
++ if (VIR_ALLOC_N(data, size) < 0)
++ abort();
++
++ asn1_der_coding(src, src_name, data, &size, NULL);
++
++ res->data = (unsigned char *)data;
++ res->size = size;
++}
++
++
++/*
++ * This is a fairly lame x509 certificate generator.
++ *
++ * Do not copy/use this code for generating real certificates
++ * since it leaves out many things that you would want in
++ * certificates for real world usage.
++ *
++ * This is good enough only for doing tests of the libvirt
++ * TLS certificate code
++ */
++void
++testTLSGenerateCert(struct testTLSCertReq *req)
++{
++ gnutls_x509_crt_t crt;
++ int err;
++ static char buffer[1024*1024];
++ size_t size = sizeof(buffer);
++ char serial[5] = { 1, 2, 3, 4, 0 };
++ gnutls_datum_t der;
++ time_t start = time(NULL) + (60*60*req->start_offset);
++ time_t expire = time(NULL) + (60*60*(req->expire_offset
++ ? req->expire_offset : 24));
++
++ /*
++ * Prepare our new certificate object
++ */
++ if ((err = gnutls_x509_crt_init(&crt)) < 0) {
++ VIR_WARN("Failed to initialize certificate %s", gnutls_strerror(err));
++ abort();
++ }
++ if ((err = gnutls_x509_crt_set_key(crt, privkey)) < 0) {
++ VIR_WARN("Failed to set certificate key %s", gnutls_strerror(err));
++ abort();
++ }
++
++ /*
++ * A v3 certificate is required in order to be able
++ * set any of the basic constraints, key purpose and
++ * key usage data
++ */
++ gnutls_x509_crt_set_version(crt, 3);
++
++ if (req->country) {
++ if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
++ req->country, strlen(req->country))) < 0) {
++ VIR_WARN("Failed to set certificate country name %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++ if (req->cn) {
++ if ((err = gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
++ req->cn, strlen(req->cn))) < 0) {
++ VIR_WARN("Failed to set certificate common name %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++
++ /*
++ * Setup the subject altnames, which are used
++ * for hostname checks in live sessions
++ */
++ if (req->altname1) {
++ if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
++ req->altname1,
++ strlen(req->altname1),
++ GNUTLS_FSAN_APPEND))) {
++ VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++ if (req->altname2) {
++ if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
++ req->altname2,
++ strlen(req->altname2),
++ GNUTLS_FSAN_APPEND))) {
++ VIR_WARN("Failed to set certificate %s alt name", gnutls_strerror(err));
++ abort();
++ }
++ }
++
++ /*
++ * IP address need to be put into the cert in their
++ * raw byte form, not strings, hence this is a little
++ * more complicated
++ */
++ if (req->ipaddr1) {
++ virSocketAddr addr;
++ char *data;
++ int len;
++ if (virSocketAddrParse(&addr, req->ipaddr1, 0) < 0) {
++ VIR_WARN("Cannot parse %s", req->ipaddr1);
++ abort();
++ }
++
++ if (addr.data.sa.sa_family == AF_INET) {
++ data = (char*)&addr.data.inet4.sin_addr;
++ len = 4;
++ } else {
++ data = (char*)&addr.data.inet6.sin6_addr;
++ len = 16;
++ }
++
++ if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
++ data, len, GNUTLS_FSAN_APPEND))) {
++ VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++ if (req->ipaddr2) {
++ virSocketAddr addr;
++ char *data;
++ int len;
++ if (virSocketAddrParse(&addr, req->ipaddr2, 0) < 0) {
++ VIR_WARN("Cannot parse %s", req->ipaddr2);
++ abort();
++ }
++
++ if (addr.data.sa.sa_family == AF_INET) {
++ data = (char*)&addr.data.inet4.sin_addr;
++ len = 4;
++ } else {
++ data = (char*)&addr.data.inet6.sin6_addr;
++ len = 16;
++ }
++
++ if ((err = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
++ data, len, GNUTLS_FSAN_APPEND))) {
++ VIR_WARN("Failed to set certificate alt name %s", gnutls_strerror(err));
++ abort();
++ }
++ }
++
++
++ /*
++ * Basic constraints are used to decide if the cert
++ * is for a CA or not. We can't use the convenient
++ * gnutls API for setting this, since it hardcodes
++ * the 'critical' field which we want control over
++ */
++ if (req->basicConstraintsEnable) {
++ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
++
++ asn1_create_element(pkix_asn1, "PKIX1.BasicConstraints", &ext);
++ asn1_write_value(ext, "cA", req->basicConstraintsIsCA ? "TRUE" : "FALSE", 1);
++ asn1_write_value(ext, "pathLenConstraint", NULL, 0);
++ testTLSDerEncode(ext, "", &der);
++ if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
++ "2.5.29.19",
++ der.data,
++ der.size,
++ req->basicConstraintsCritical)) < 0) {
++ VIR_WARN("Failed to set certificate basic constraints %s", gnutls_strerror(err));
++ VIR_FREE(der.data);
++ abort();
++ }
++ asn1_delete_structure(&ext);
++ VIR_FREE(der.data);
++ }
++
++ /*
++ * Next up the key usage extension. Again we can't
++ * use the gnutls API since it hardcodes the extension
++ * to be 'critical'
++ */
++ if (req->keyUsageEnable) {
++ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
++ char str[2];
++
++ str[0] = req->keyUsageValue & 0xff;
++ str[1] = (req->keyUsageValue >> 8) & 0xff;
++
++ asn1_create_element(pkix_asn1, "PKIX1.KeyUsage", &ext);
++ asn1_write_value(ext, "", str, 9);
++ testTLSDerEncode(ext, "", &der);
++ if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
++ "2.5.29.15",
++ der.data,
++ der.size,
++ req->keyUsageCritical)) < 0) {
++ VIR_WARN("Failed to set certificate key usage %s", gnutls_strerror(err));
++ VIR_FREE(der.data);
++ abort();
++ }
++ asn1_delete_structure(&ext);
++ VIR_FREE(der.data);
++ }
++
++ /*
++ * Finally the key purpose extension. This time
++ * gnutls has the opposite problem, always hardcoding
++ * it to be non-critical. So once again we have to
++ * set this the hard way building up ASN1 data ourselves
++ */
++ if (req->keyPurposeEnable) {
++ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
++
++ asn1_create_element(pkix_asn1, "PKIX1.ExtKeyUsageSyntax", &ext);
++ if (req->keyPurposeOID1) {
++ asn1_write_value(ext, "", "NEW", 1);
++ asn1_write_value(ext, "?LAST", req->keyPurposeOID1, 1);
++ }
++ if (req->keyPurposeOID2) {
++ asn1_write_value(ext, "", "NEW", 1);
++ asn1_write_value(ext, "?LAST", req->keyPurposeOID2, 1);
++ }
++ testTLSDerEncode(ext, "", &der);
++ if ((err = gnutls_x509_crt_set_extension_by_oid(crt,
++ "2.5.29.37",
++ der.data,
++ der.size,
++ req->keyPurposeCritical)) < 0) {
++ VIR_WARN("Failed to set certificate key purpose %s", gnutls_strerror(err));
++ VIR_FREE(der.data);
++ abort();
++ }
++ asn1_delete_structure(&ext);
++ VIR_FREE(der.data);
++ }
++
++ /*
++ * Any old serial number will do, so lets pick 5
++ */
++ if ((err = gnutls_x509_crt_set_serial(crt, serial, 5)) < 0) {
++ VIR_WARN("Failed to set certificate serial %s", gnutls_strerror(err));
++ abort();
++ }
++
++ if ((err = gnutls_x509_crt_set_activation_time(crt, start)) < 0) {
++ VIR_WARN("Failed to set certificate activation %s", gnutls_strerror(err));
++ abort();
++ }
++ if ((err = gnutls_x509_crt_set_expiration_time(crt, expire)) < 0) {
++ VIR_WARN("Failed to set certificate expiration %s", gnutls_strerror(err));
++ abort();
++ }
++
++
++ /*
++ * If no 'cart' is set then we are self signing
++ * the cert. This is done for CA certs
++ */
++ if ((err = gnutls_x509_crt_sign(crt, req->cacrt ? req->cacrt : crt, privkey) < 0)) {
++ VIR_WARN("Failed to sign certificate %s", gnutls_strerror(err));
++ abort();
++ }
++
++ /*
++ * Finally write the new cert out to disk
++ */
++ if ((err = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &size) < 0)) {
++ VIR_WARN("Failed to export certificate %s", gnutls_strerror(err));
++ abort();
++ }
++
++ if (virFileWriteStr(req->filename, buffer, 0600) < 0) {
++ VIR_WARN("Failed to write certificate %s %s", req->filename, gnutls_strerror(err));
++ abort();
++ }
++
++ req->crt = crt;
++ return;
++}
++
++
++void testTLSDiscardCert(struct testTLSCertReq *req)
++{
++ if (!req->crt)
++ return;
++
++ gnutls_x509_crt_deinit(req->crt);
++ req->crt = NULL;
++
++ if (getenv("VIRT_TEST_DEBUG_CERTS") == NULL)
++ unlink(req->filename);
++}
++
++#endif
+diff --git a/tests/virnettlshelpers.h b/tests/virnettlshelpers.h
+new file mode 100644
+index 0000000..3ea9978
+--- /dev/null
++++ b/tests/virnettlshelpers.h
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2011-2013 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Daniel P. Berrange <berrange@redhat.com>
++ */
++
++#include <gnutls/gnutls.h>
++#include <gnutls/x509.h>
++
++#if !defined WIN32 && HAVE_LIBTASN1_H && LIBGNUTLS_VERSION_NUMBER >= 0x020600
++# include "gnutls_1_0_compat.h"
++
++# include <libtasn1.h>
++
++# include "rpc/virnettlscontext.h"
++
++extern const char *keyfile;
++
++/*
++ * This contains parameter about how to generate
++ * certificates.
++ */
++struct testTLSCertReq {
++ gnutls_x509_crt_t crt;
++ gnutls_x509_crt_t cacrt; /* If not set, then the cert will be self-signed */
++
++ const char *filename;
++
++ /* Identifying information */
++ const char *country;
++ const char *cn;
++ const char *altname1;
++ const char *altname2;
++ const char *ipaddr1;
++ const char *ipaddr2;
++
++ /* Basic constraints */
++ bool basicConstraintsEnable;
++ bool basicConstraintsCritical;
++ bool basicConstraintsIsCA;
++
++ /* Key usage */
++ bool keyUsageEnable;
++ bool keyUsageCritical;
++ int keyUsageValue;
++
++ /* Key purpose (aka Extended key usage) */
++ bool keyPurposeEnable;
++ bool keyPurposeCritical;
++ const char *keyPurposeOID1;
++ const char *keyPurposeOID2;
++
++ /* zero for current time, or non-zero for hours from now */
++ int start_offset;
++ /* zero for 24 hours from now, or non-zero for hours from now */
++ int expire_offset;
++};
++
++void testTLSGenerateCert(struct testTLSCertReq *req);
++void testTLSDiscardCert(struct testTLSCertReq *req);
++
++void testTLSInit(void);
++void testTLSCleanup(void);
++
++#endif
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+new file mode 100644
+index 0000000..9c5b3ca
+--- /dev/null
++++ b/tests/virnettlssessiontest.c
+@@ -0,0 +1,414 @@
++/*
++ * Copyright (C) 2011-2012 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Daniel P. Berrange <berrange@redhat.com>
++ */
++
++#include <config.h>
++
++#include <stdlib.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++
++#include "testutils.h"
++#include "virnettlshelpers.h"
++#include "virutil.h"
++#include "virerror.h"
++#include "viralloc.h"
++#include "virlog.h"
++#include "virfile.h"
++#include "vircommand.h"
++#include "virsocketaddr.h"
++
++#if !defined WIN32 && HAVE_LIBTASN1_H && LIBGNUTLS_VERSION_NUMBER >= 0x020600
++
++# define VIR_FROM_THIS VIR_FROM_RPC
++
++struct testTLSSessionData {
++ struct testTLSCertReq careq;
++ struct testTLSCertReq othercareq;
++ struct testTLSCertReq serverreq;
++ struct testTLSCertReq clientreq;
++ bool expectServerFail;
++ bool expectClientFail;
++ const char *hostname;
++ const char *const* wildcards;
++};
++
++
++static ssize_t testWrite(const char *buf, size_t len, void *opaque)
++{
++ int *fd = opaque;
++
++ return write(*fd, buf, len);
++}
++
++static ssize_t testRead(char *buf, size_t len, void *opaque)
++{
++ int *fd = opaque;
++
++ return read(*fd, buf, len);
++}
++
++/*
++ * This tests validation checking of peer certificates
++ *
++ * This is replicating the checks that are done for an
++ * active TLS session after handshake completes. To
++ * simulate that we create our TLS contexts, skipping
++ * sanity checks. When then get a socketpair, and
++ * initiate a TLS session across them. Finally do
++ * do actual cert validation tests
++ */
++static int testTLSSessionInit(const void *opaque)
++{
++ struct testTLSSessionData *data = (struct testTLSSessionData *)opaque;
++ virNetTLSContextPtr clientCtxt = NULL;
++ virNetTLSContextPtr serverCtxt = NULL;
++ virNetTLSSessionPtr clientSess = NULL;
++ virNetTLSSessionPtr serverSess = NULL;
++ int ret = -1;
++ int channel[2];
++ bool clientShake = false;
++ bool serverShake = false;
++
++
++ /* We'll use this for our fake client-server connection */
++ if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) < 0)
++ abort();
++
++ /*
++ * We have an evil loop to do the handshake in a single
++ * thread, so we need these non-blocking to avoid deadlock
++ * of ourselves
++ */
++ ignore_value(virSetNonBlock(channel[0]));
++ ignore_value(virSetNonBlock(channel[1]));
++
++
++ /* Generate all the certs we need for this test */
++ testTLSGenerateCert(&data->careq);
++ data->serverreq.cacrt = data->careq.crt;
++ testTLSGenerateCert(&data->serverreq);
++
++ if (data->othercareq.filename) {
++ testTLSGenerateCert(&data->othercareq);
++ data->clientreq.cacrt = data->othercareq.crt;
++ } else {
++ data->clientreq.cacrt = data->careq.crt;
++ }
++ testTLSGenerateCert(&data->clientreq);
++
++
++ /* We skip initial sanity checks here because we
++ * want to make sure that problems are being
++ * detected at the TLS session validation stage
++ */
++ serverCtxt = virNetTLSContextNewServer(data->careq.filename,
++ NULL,
++ data->serverreq.filename,
++ keyfile,
++ data->wildcards,
++ false,
++ true);
++
++ clientCtxt = virNetTLSContextNewClient(data->othercareq.filename ?
++ data->othercareq.filename :
++ data->careq.filename,
++ NULL,
++ data->clientreq.filename,
++ keyfile,
++ false,
++ true);
++
++ if (!serverCtxt) {
++ VIR_WARN("Unexpected failure loading %s against %s",
++ data->careq.filename, data->serverreq.filename);
++ goto cleanup;
++ }
++ if (!clientCtxt) {
++ VIR_WARN("Unexpected failure loading %s against %s",
++ data->othercareq.filename ? data->othercareq.filename :
++ data->careq.filename, data->clientreq.filename);
++ goto cleanup;
++ }
++
++
++ /* Now the real part of the test, setup the sessions */
++ serverSess = virNetTLSSessionNew(serverCtxt, NULL);
++ clientSess = virNetTLSSessionNew(clientCtxt, data->hostname);
++
++ if (!serverSess) {
++ VIR_WARN("Unexpected failure using %s against %s",
++ data->careq.filename, data->serverreq.filename);
++ goto cleanup;
++ }
++ if (!clientSess) {
++ VIR_WARN("Unexpected failure using %s against %s",
++ data->othercareq.filename ? data->othercareq.filename :
++ data->careq.filename, data->clientreq.filename);
++ goto cleanup;
++ }
++
++ /* For handshake to work, we need to set the I/O callbacks
++ * to read/write over the socketpair
++ */
++ virNetTLSSessionSetIOCallbacks(serverSess, testWrite, testRead, &channel[0]);
++ virNetTLSSessionSetIOCallbacks(clientSess, testWrite, testRead, &channel[1]);
++
++ /*
++ * Finally we loop around & around doing handshake on each
++ * session until we get an error, or the handshake completes.
++ * This relies on the socketpair being nonblocking to avoid
++ * deadlocking ourselves upon handshake
++ */
++ do {
++ int rv;
++ if (!serverShake) {
++ rv = virNetTLSSessionHandshake(serverSess);
++ if (rv < 0)
++ goto cleanup;
++ if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
++ serverShake = true;
++ }
++ if (!clientShake) {
++ rv = virNetTLSSessionHandshake(clientSess);
++ if (rv < 0)
++ goto cleanup;
++ if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
++ clientShake = true;
++ }
++ } while (!clientShake && !serverShake);
++
++
++ /* Finally make sure the server validation does what
++ * we were expecting
++ */
++ if (virNetTLSContextCheckCertificate(serverCtxt,
++ serverSess) < 0) {
++ if (!data->expectServerFail) {
++ VIR_WARN("Unexpected server cert check fail");
++ goto cleanup;
++ } else {
++ VIR_DEBUG("Got expected server cert fail");
++ }
++ } else {
++ if (data->expectServerFail) {
++ VIR_WARN("Expected server cert check fail");
++ goto cleanup;
++ } else {
++ VIR_DEBUG("Not unexpected server cert fail");
++ }
++ }
++
++ /*
++ * And the same for the client validation check
++ */
++ if (virNetTLSContextCheckCertificate(clientCtxt,
++ clientSess) < 0) {
++ if (!data->expectClientFail) {
++ VIR_WARN("Unexpected client cert check fail");
++ goto cleanup;
++ } else {
++ VIR_DEBUG("Got expected client cert fail");
++ }
++ } else {
++ if (data->expectClientFail) {
++ VIR_WARN("Expected client cert check fail");
++ goto cleanup;
++ } else {
++ VIR_DEBUG("Not unexpected client cert fail");
++ }
++ }
++
++ ret = 0;
++
++cleanup:
++ virObjectUnref(serverCtxt);
++ virObjectUnref(clientCtxt);
++ virObjectUnref(serverSess);
++ virObjectUnref(clientSess);
++
++ testTLSDiscardCert(&data->careq);
++ if (data->othercareq.filename)
++ testTLSDiscardCert(&data->othercareq);
++ testTLSDiscardCert(&data->clientreq);
++ testTLSDiscardCert(&data->serverreq);
++
++ VIR_FORCE_CLOSE(channel[0]);
++ VIR_FORCE_CLOSE(channel[1]);
++ return ret;
++}
++
++
++static int
++mymain(void)
++{
++ int ret = 0;
++
++ testTLSInit();
++
++# define DO_SESS_TEST(_caReq, _serverReq, _clientReq, _expectServerFail,\
++ _expectClientFail, _hostname, _wildcards) \
++ do { \
++ static struct testTLSSessionData data; \
++ static struct testTLSCertReq other; \
++ data.careq = _caReq; \
++ data.othercareq = other; \
++ data.serverreq = _serverReq; \
++ data.clientreq = _clientReq; \
++ data.expectServerFail = _expectServerFail; \
++ data.expectClientFail = _expectClientFail; \
++ data.hostname = _hostname; \
++ data.wildcards = _wildcards; \
++ if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
++# define DO_SESS_TEST_EXT(_caReq, _othercaReq, _serverReq, _clientReq, \
++ _expectServerFail, _expectClientFail, \
++ _hostname, _wildcards) \
++ do { \
++ static struct testTLSSessionData data; \
++ data.careq = _caReq; \
++ data.othercareq = _othercaReq; \
++ data.serverreq = _serverReq; \
++ data.clientreq = _clientReq; \
++ data.expectServerFail = _expectServerFail; \
++ data.expectClientFail = _expectClientFail; \
++ data.hostname = _hostname; \
++ data.wildcards = _wildcards; \
++ if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
++ /* A perfect CA, perfect client & perfect server */
++
++ /* Basic:CA:critical */
++ static struct testTLSCertReq cacertreq = {
++ NULL, NULL, "cacert.pem", "UK",
++ "libvirt CA", NULL, NULL, NULL, NULL,
++ true, true, true,
++ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
++ false, false, NULL, NULL,
++ 0, 0,
++ };
++ static struct testTLSCertReq cacert1req = {
++ NULL, NULL, "cacert1.pem", "UK",
++ "libvirt CA 1", NULL, NULL, NULL, NULL,
++ true, true, true,
++ false, false, 0,
++ false, false, NULL, NULL,
++ 0, 0,
++ };
++ static struct testTLSCertReq servercertreq = {
++ NULL, NULL, "servercert.pem", "UK",
++ "libvirt.org", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0,
++ };
++ static struct testTLSCertReq clientcertreq = {
++ NULL, NULL, "clientcert.pem", "UK",
++ "libvirt", NULL, NULL, NULL, NULL,
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
++ 0, 0,
++ };
++
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL);
++ DO_SESS_TEST_EXT(cacertreq, cacert1req, servercertreq, clientcertreq, true, true, "libvirt.org", NULL);
++
++ /* When an altname is set, the CN is ignored, so it must be duplicated
++ * as an altname for it to match */
++ static struct testTLSCertReq servercertalt1req = {
++ NULL, NULL, "servercert.pem", "UK",
++ "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf",
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0,
++ };
++ /* This intentionally doesn't replicate */
++ static struct testTLSCertReq servercertalt2req = {
++ NULL, NULL, "servercert.pem", "UK",
++ "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf",
++ true, true, false,
++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
++ 0, 0,
++ };
++
++ DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, true, "wiki.libvirt.org", NULL);
++
++ DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, true, "libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "www.libvirt.org", NULL);
++ DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "wiki.libvirt.org", NULL);
++
++ const char *const wildcards1[] = {
++ "C=UK,CN=dogfood",
++ NULL,
++ };
++ const char *const wildcards2[] = {
++ "C=UK,CN=libvirt",
++ NULL,
++ };
++ const char *const wildcards3[] = {
++ "C=UK,CN=dogfood",
++ "C=UK,CN=libvirt",
++ NULL,
++ };
++ const char *const wildcards4[] = {
++ "C=UK,CN=libvirtstuff",
++ NULL,
++ };
++ const char *const wildcards5[] = {
++ "C=UK,CN=libvirt*",
++ NULL,
++ };
++ const char *const wildcards6[] = {
++ "C=UK,CN=*virt*",
++ NULL,
++ };
++
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards1);
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards2);
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards3);
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards4);
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5);
++ DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6);
++
++ testTLSCleanup();
++
++ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
++}
++
++VIRT_TEST_MAIN(mymain)
++
++#else
++
++int
++main(void)
++{
++ return EXIT_AM_SKIP;
++}
++
++#endif
+--
+1.8.3.2
+
--- /dev/null
+From 74acebeb19b1c0c7a52998b7862806e26ea8fce8 Mon Sep 17 00:00:00 2001
+Message-Id: <74acebeb19b1c0c7a52998b7862806e26ea8fce8.1377873639.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Fri, 30 Aug 2013 11:13:44 +0100
+Subject: [PATCH] Update polkit examples to use 'lookup' method
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+Feedback from the polkit developers indicates that the
+"_detail_XXXX" attributes are a private implementation
+detail. Our examples should be recommending use of the
+"action.lookup('XXX')" method instead.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit 7a7cb0934e25b9ac23cf9b2d318ac801604e0681)
+---
+ docs/aclpolkit.html.in | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/docs/aclpolkit.html.in b/docs/aclpolkit.html.in
+index 3f0689e..1a09139 100644
+--- a/docs/aclpolkit.html.in
++++ b/docs/aclpolkit.html.in
+@@ -344,10 +344,8 @@
+ dealing with local clients connected via the UNIX socket).
+ On the <code>action</code> object, the permission name is
+ accessible via the <code>id</code> attribute, while the
+- object identifying attributes are exposed via a set of
+- attributes with the naming convention <code>_detail_[attrname]</code>.
+- For example, the 'domain_name' attribute would be exposed via
+- a property <code>_detail_domain_name</code>.
++ object identifying attributes are exposed via the
++ <code>lookup</code> method.
+ </p>
+
+ <h3><a name="exconnect">Example: restricting ability to connect to drivers</a></h3>
+@@ -359,7 +357,7 @@
+ use the <code>QEMU</code> driver and not the Xen or LXC
+ drivers which are also available in libvirtd.
+ To achieve this we need to write a rule which checks
+- whether the <code>_detail_connect_driver</code> attribute
++ whether the <code>connect_driver</code> attribute
+ is <code>QEMU</code>, and match on an action
+ name of <code>org.libvirt.api.connect.getattr</code>. Using
+ the javascript rules format, this ends up written as
+@@ -369,7 +367,7 @@
+ polkit.addRule(function(action, subject) {
+ if (action.id == "org.libvirt.api.connect.getattr" &&
+ subject.user == "berrange") {
+- if (action._detail_connect_driver == 'QEMU') {
++ if (action.lookup("connect_driver") == 'QEMU') {
+ return polkit.Result.YES;
+ } else {
+ return polkit.Result.NO;
+@@ -386,8 +384,8 @@ polkit.addRule(function(action, subject) {
+ full read-write mode. The goal is to only allow them to
+ see the domain called <code>demo</code> on the LXC driver.
+ To achieve this we need to write a rule which checks
+- whether the <code>_detail_connect_driver</code> attribute
+- is <code>LXC</code> and the <code>_detail_domain_name</code>
++ whether the <code>connect_driver</code> attribute
++ is <code>LXC</code> and the <code>domain_name</code>
+ attribute is <code>demo</code>, and match on a action
+ name of <code>org.libvirt.api.domain.getattr</code>. Using
+ the javascript rules format, this ends up written as
+@@ -397,8 +395,8 @@ polkit.addRule(function(action, subject) {
+ polkit.addRule(function(action, subject) {
+ if (action.id == "org.libvirt.api.domain.getattr" &&
+ subject.user == "berrange") {
+- if (action._detail_connect_driver == 'LXC' &&
+- action._detail_domain_name == 'demo') {
++ if (action.lookup("connect_driver") == 'LXC' &&
++ action.lookup("domain_name") == 'demo') {
+ return polkit.Result.YES;
+ } else {
+ return polkit.Result.NO;
+--
+1.8.3.2
+
--- /dev/null
+From 9cc48e8b7fbec4f098a65577c4ef2fd37f473d1c Mon Sep 17 00:00:00 2001
+Message-Id: <9cc48e8b7fbec4f098a65577c4ef2fd37f473d1c.1383922565.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Thu, 7 Nov 2013 18:57:02 +0100
+Subject: [PATCH] Use a port from the migration range for NBD as well
+
+Instead of using a port from the remote display range.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1025699
+(cherry picked from commit 3e1e16aa8d4238241a1806cb9bdb3b9ad60db777)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_migration.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index fb5568e..32ffde7 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -1118,7 +1118,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
+ goto cleanup;
+
+ if (!port &&
+- ((virPortAllocatorAcquire(driver->remotePorts, &port) < 0) ||
++ ((virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) ||
+ (qemuMonitorNBDServerStart(priv->mon, listenAddr, port) < 0))) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+--
+1.8.4.2
+
--- /dev/null
+From dbb853b24a6a6e1733c06c5c2742d55f8aeb6a0e Mon Sep 17 00:00:00 2001
+Message-Id: <dbb853b24a6a6e1733c06c5c2742d55f8aeb6a0e.1381871411.git.jdenemar@redhat.com>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 7 Oct 2013 17:17:31 +0100
+Subject: [PATCH] Use 'vnet' as prefix for veth devices
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1014604
+
+The XML parser reserves 'vnet' as a prefix for automatically
+generated NIC device names. Switch the veth device creation
+to use this prefix, so it does not have to worry about clashes
+with user specified names in the XML.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit fe3f108d85be7bffc0bfe08eaa10e24179797724)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virnetdevveth.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
+index 1ccfc54..403961b 100644
+--- a/src/util/virnetdevveth.c
++++ b/src/util/virnetdevveth.c
+@@ -43,10 +43,10 @@ static int virNetDevVethExists(int devNum)
+ {
+ int ret;
+ char *path = NULL;
+- if (virAsprintf(&path, "/sys/class/net/veth%d/", devNum) < 0)
++ if (virAsprintf(&path, "/sys/class/net/vnet%d/", devNum) < 0)
+ return -1;
+ ret = virFileExists(path) ? 1 : 0;
+- VIR_DEBUG("Checked dev veth%d usage: %d", devNum, ret);
++ VIR_DEBUG("Checked dev vnet%d usage: %d", devNum, ret);
+ VIR_FREE(path);
+ return ret;
+ }
+@@ -125,7 +125,7 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ if ((veth1num = virNetDevVethGetFreeNum(vethNum)) < 0)
+ goto cleanup;
+
+- if (virAsprintf(&veth1auto, "veth%d", veth1num) < 0)
++ if (virAsprintf(&veth1auto, "vnet%d", veth1num) < 0)
+ goto cleanup;
+ vethNum = veth1num + 1;
+ }
+@@ -134,7 +134,7 @@ int virNetDevVethCreate(char** veth1, char** veth2)
+ if ((veth2num = virNetDevVethGetFreeNum(vethNum)) < 0)
+ goto cleanup;
+
+- if (virAsprintf(&veth2auto, "veth%d", veth2num) < 0)
++ if (virAsprintf(&veth2auto, "vnet%d", veth2num) < 0)
+ goto cleanup;
+ vethNum = veth2num + 1;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From f9e18d3e5937609ecdfbc8fe35bc0545f8da114c Mon Sep 17 00:00:00 2001
+Message-Id: <f9e18d3e5937609ecdfbc8fe35bc0545f8da114c.1381871412.git.jdenemar@redhat.com>
+From: Daniel Hansel <daniel.hansel@linux.vnet.ibm.com>
+Date: Tue, 15 Oct 2013 14:44:08 +0200
+Subject: [PATCH] build: Add lxc testcase to dist list
+
+Introduced by commit 3f029fb5319b9dc9cc2fbf8d1ba4505ee9e4b1e3 the RPM build
+was broken due to a missing LXC textcase.
+
+Signed-off-by: Daniel Hansel <daniel.hansel@linux.vnet.ibm.com>
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015689
+(cherry picked from commit 6285c17f790a7e5027aed0207fc5d9eb9130cc0e)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 0c6e5ee..4787752 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -68,6 +68,7 @@ EXTRA_DIST = \
+ fchostdata \
+ interfaceschemadata \
+ lxcxml2xmldata \
++ lxcxml2xmloutdata \
+ networkschematest \
+ networkxml2xmlin \
+ networkxml2xmlout \
+--
+1.8.3.2
+
--- /dev/null
+From 59795aee1c0c049c5160457fcd91ca1150bff069 Mon Sep 17 00:00:00 2001
+Message-Id: <59795aee1c0c049c5160457fcd91ca1150bff069.1377873639.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 12 Aug 2013 14:09:10 -0600
+Subject: [PATCH] build: avoid -lgcrypt with newer gnutls
+
+https://bugzilla.redhat.com/show_bug.cgi?id=951637
+
+Newer gnutls uses nettle, rather than gcrypt, which is a lot nicer
+regarding initialization. Yet we were unconditionally initializing
+gcrypt even when gnutls wouldn't be using it, and having two crypto
+libraries linked into libvirt.so is pointless, but mostly harmless
+(it doesn't crash, but does interfere with certification efforts).
+
+There are three distinct version ranges to worry about when
+determining which crypto lib gnutls uses, per these gnutls mails:
+2.12: http://lists.gnu.org/archive/html/gnutls-devel/2011-03/msg00034.html
+3.0: http://lists.gnu.org/archive/html/gnutls-devel/2011-07/msg00035.html
+
+If pkg-config can prove version numbers and/or list the crypto
+library used for static linking, we have our proof; if not, it
+is safer (even if pointless) to continue to use gcrypt ourselves.
+
+* configure.ac (WITH_GNUTLS): Probe whether to add -lgcrypt, and
+define a witness WITH_GNUTLS_GCRYPT.
+* src/libvirt.c (virTLSMutexInit, virTLSMutexDestroy)
+(virTLSMutexLock, virTLSMutexUnlock, virTLSThreadImpl)
+(virGlobalInit): Honor the witness.
+* libvirt.spec.in (BuildRequires): Make gcrypt usage conditional,
+no longer needed in Fedora 19.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 6094b1ff1992e6c7c7b17a2e1a3ddbf29f7f6591)
+---
+ configure.ac | 37 ++++++++++++++++++++++++++++++-------
+ libvirt.spec.in | 2 ++
+ src/libvirt.c | 10 ++++++----
+ 3 files changed, 38 insertions(+), 11 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 084d864..917db6a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1076,12 +1076,26 @@ if test "x$with_gnutls" != "xno"; then
+ LIBS="$LIBS $GNUTLS_LIBS"
+
+ GNUTLS_FOUND=no
++ GNUTLS_GCRYPT=unknown
+ if test -x "$PKG_CONFIG" ; then
++ dnl Triple probe: gnutls < 2.12 only used gcrypt, gnutls >= 3.0 uses
++ dnl only nettle, and versions in between had a configure option.
++ dnl Our goal is to avoid gcrypt if we can prove gnutls uses nettle,
++ dnl but it is a safe fallback to use gcrypt if we can't prove anything.
++ if $PKG_CONFIG --exists 'gnutls >= 3.0'; then
++ GNUTLS_GCRYPT=no
++ elif $PKG_CONFIG --exists 'gnutls >= 2.12'; then
++ GNUTLS_GCRYPT=probe
++ else
++ GNUTLS_GCRYPT=yes
++ fi
+ PKG_CHECK_MODULES(GNUTLS, gnutls >= $GNUTLS_REQUIRED,
+ [GNUTLS_FOUND=yes], [GNUTLS_FOUND=no])
+ fi
+ if test "$GNUTLS_FOUND" = "no"; then
++ dnl pkg-config couldn't help us, assume gcrypt is necessary
+ fail=0
++ GNUTLS_GCRYPT=yes
+ AC_CHECK_HEADER([gnutls/gnutls.h], [], [fail=1])
+ AC_CHECK_LIB([gnutls], [gnutls_handshake],[], [fail=1], [-lgcrypt])
+
+@@ -1098,13 +1112,22 @@ if test "x$with_gnutls" != "xno"; then
+ AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt])
+ fi
+ else
+- dnl Not all versions of gnutls include -lgcrypt, and so we add
+- dnl it explicitly for the calls to gcry_control/check_version
+- GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
+-
+- dnl We're not using gcrypt deprecated features so define
+- dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
+- GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
++ dnl See comments above about when to use gcrypt.
++ if test "$GNUTLS_GCRYPT" = probe; then
++ case `$PKG_CONFIG --libs --static gnutls` in
++ *gcrypt*) GNUTLS_GCRYPT=yes ;;
++ *nettle*) GNUTLS_GCRYPT=no ;;
++ *) GNUTLS_GCRYPT=unknown ;;
++ esac
++ fi
++ if test "$GNUTLS_GCRYPT" = yes || test "$GNUTLS_GCRYPT" = unknown; then
++ GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
++ dnl We're not using gcrypt deprecated features so define
++ dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
++ GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
++ AC_DEFINE_UNQUOTED([WITH_GNUTLS_GCRYPT], 1,
++ [set to 1 if it is known or assumed that GNUTLS uses gcrypt])
++ fi
+
+ dnl gnutls 3.x moved some declarations to a new header
+ AC_CHECK_HEADERS([gnutls/crypto.h], [], [], [[
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 8157488..66e8248 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -55,7 +55,9 @@
+ #include "intprops.h"
+ #include "virconf.h"
+ #if WITH_GNUTLS
+-# include <gcrypt.h>
++# if WITH_GNUTLS_GCRYPT
++# include <gcrypt.h>
++# endif
+ # include "rpc/virnettlscontext.h"
+ #endif
+ #include "vircommand.h"
+@@ -270,7 +272,7 @@ winsock_init(void)
+ #endif
+
+
+-#ifdef WITH_GNUTLS
++#ifdef WITH_GNUTLS_GCRYPT
+ static int virTLSMutexInit(void **priv)
+ {
+ virMutexPtr lock = NULL;
+@@ -323,7 +325,7 @@ static struct gcry_thread_cbs virTLSThreadImpl = {
+ virTLSMutexUnlock,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ };
+-#endif
++#endif /* WITH_GNUTLS_GCRYPT */
+
+ /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99. This
+ * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but
+@@ -407,7 +409,7 @@ virGlobalInit(void)
+ virErrorInitialize() < 0)
+ goto error;
+
+-#ifdef WITH_GNUTLS
++#ifdef WITH_GNUTLS_GCRYPT
+ /*
+ * This sequence of API calls it copied exactly from
+ * gnutls 2.12.23 source lib/gcrypt/init.c, with
+--
+1.8.3.2
+
--- /dev/null
+From 2c7f80e73aa2de65dd92ad3f0d7c7be9dcf7048a Mon Sep 17 00:00:00 2001
+Message-Id: <2c7f80e73aa2de65dd92ad3f0d7c7be9dcf7048a.1383321464.git.jdenemar@redhat.com>
+From: Jim Fehlig <jfehlig@suse.com>
+Date: Wed, 30 Oct 2013 17:01:46 +0000
+Subject: [PATCH] build: fix build of virt-login-shell on systems with older
+ gnutls
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+On systems where gnutls uses libgcrypt, I'm seeing the following
+build failure
+
+libvirt.c:314: error: variable 'virTLSThreadImpl' has initializer but incomplete type
+libvirt.c:319: error: 'GCRY_THREAD_OPTION_PTHREAD' undeclared here (not in a function)
+...
+
+Fix by undefining WITH_GNUTLS_GCRYPT in config-post.h
+(cherry picked from commit 843bdb2f8a3364637cda2911624149525188843f)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ config-post.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/config-post.h b/config-post.h
+index d371e8c..8367200 100644
+--- a/config-post.h
++++ b/config-post.h
+@@ -34,6 +34,7 @@
+ # undef WITH_CURL
+ # undef WITH_DTRACE_PROBES
+ # undef WITH_GNUTLS
++# undef WITH_GNUTLS_GCRYPT
+ # undef WITH_MACVTAP
+ # undef WITH_NUMACTL
+ # undef WITH_SASL
+--
+1.8.4.2
+
--- /dev/null
+From 9968ba922ade8ad48efe502a8c02937ac55e28c4 Mon Sep 17 00:00:00 2001
+Message-Id: <9968ba922ade8ad48efe502a8c02937ac55e28c4.1377873639.git.jdenemar@redhat.com>
+From: Jim Fehlig <jfehlig@suse.com>
+Date: Tue, 13 Aug 2013 15:20:41 +0100
+Subject: [PATCH] build: fix compilation of virt-login-shell.c
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=988491
+
+virt-login-shell.c was failing to compile with
+
+CC virt_login_shell-virt-login-shell.o
+virt-login-shell.c: In function 'main':
+virt-login-shell.c:205:5: error: implicit declaration of function 'setlocale' [-Werror=implicit-function-declaration]
+virt-login-shell.c:205:5: error: nested extern declaration of 'setlocale' [-Werror=nested-externs]
+virt-login-shell.c:205:20: error: 'LC_ALL' undeclared (first use in this function)
+
+(cherry picked from commit 26b8a4dd23716f42f6e3fd5ff41fba30598689e5)
+---
+ tools/virt-login-shell.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
+index ffbc713..b8f1a28 100644
+--- a/tools/virt-login-shell.c
++++ b/tools/virt-login-shell.c
+@@ -27,6 +27,7 @@
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <fnmatch.h>
++#include <locale.h>
+
+ #include "internal.h"
+ #include "virerror.h"
+--
+1.8.3.2
+
--- /dev/null
+From a3d46832cc5a6e2eae8daf86df26747f0ebb49a6 Mon Sep 17 00:00:00 2001
+Message-Id: <a3d46832cc5a6e2eae8daf86df26747f0ebb49a6.1383321464.git.jdenemar@redhat.com>
+From: Jim Fehlig <jfehlig@suse.com>
+Date: Wed, 30 Oct 2013 17:01:45 +0000
+Subject: [PATCH] build: fix linking virt-login-shell
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1015247
+
+After commit 3e2f27e1, I've noticed build failures of virt-login-shell
+when libapparmor-devel is installed on the build host
+
+CCLD virt-login-shell
+../src/.libs/libvirt-setuid-rpc-client.a(libvirt_setuid_rpc_client_la-vircommand.o):
+In function `virExec':
+/home/jfehlig/virt/upstream/libvirt/src/util/vircommand.c:653: undefined
+reference to `aa_change_profile'
+collect2: error: ld returned 1 exit status
+
+I was about to commit an easy fix under the build-breaker rule
+(build-fix-1.patch), but thought to extend the notion of SECDRIVER_LIBS
+to SECDRIVER_CFLAGS, and use both throughout src/Makefile.am where it
+makes sense (build-fix-2.patch).
+
+Should I just stick with the simple fix, or is something along the lines
+of patch 2 preferred?
+
+Regards,
+Jim
+
+>From a0f35945f3127ab70d051101037e821b1759b4bb Mon Sep 17 00:00:00 2001
+From: Jim Fehlig <jfehlig@suse.com>
+Date: Mon, 21 Oct 2013 15:30:02 -0600
+Subject: [PATCH] build: fix virt-login-shell build with apparmor
+
+With libapparmor-devel installed, virt-login-shell fails to link
+
+CCLD virt-login-shell
+../src/.libs/libvirt-setuid-rpc-client.a(libvirt_setuid_rpc_client_la-vircommand.o): In function `virExec':
+/home/jfehlig/virt/upstream/libvirt/src/util/vircommand.c:653: undefined reference to `aa_change_profile'
+collect2: error: ld returned 1 exit status
+
+Fix by linking libvirt_setuid_rpc_client with previously determined
+SECDRIVER_LIBS in src/Makefile.am. While at it, introduce SECDRIVER_CFLAGS
+and use both throughout src/Makefile.am where it makes sense.
+
+Signed-off-by: Jim Fehlig <jfehlig@suse.com>
+(cherry picked from commit 5a0ea4b7b9af2231ed161b94f9af65375c6ee9c2)
+
+Conflicts:
+ src/Makefile.am: Context
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/Makefile.am | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 969d09b..2dddf15 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -46,11 +46,14 @@ nodist_conf_DATA =
+
+ THREAD_LIBS = $(LIB_PTHREAD) $(LTLIBMULTITHREAD)
+
++SECDRIVER_CFLAGS =
+ SECDRIVER_LIBS =
+ if WITH_SECDRIVER_SELINUX
++SECDRIVER_CFLAGS += $(SELINUX_CFLAGS)
+ SECDRIVER_LIBS += $(SELINUX_LIBS)
+ endif
+ if WITH_SECDRIVER_APPARMOR
++SECDRIVER_CFLAGS += $(APPARMOR_CFLAGS)
+ SECDRIVER_LIBS += $(APPARMOR_LIBS)
+ endif
+
+@@ -1975,14 +1978,14 @@ libvirt_setuid_rpc_client_la_SOURCES = \
+ libvirt_setuid_rpc_client_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ $(LIBXML_LIBS) \
+- $(SELINUX_LIBS) \
++ $(SECDRIVER_LIBS) \
+ $(NULL)
+ libvirt_setuid_rpc_client_la_CFLAGS = \
+ -DLIBVIRT_SETUID_RPC_CLIENT \
+ -I$(top_srcdir)/src/conf \
+ -I$(top_srcdir)/src/rpc \
+ $(AM_CFLAGS) \
+- $(SELINUX_CFLAGS) \
++ $(SECDRIVER_CFLAGS) \
+ $(NULL)
+ endif WITH_LXC
+
+@@ -2410,15 +2413,10 @@ libvirt_lxc_CFLAGS = \
+ if WITH_BLKID
+ libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
+ libvirt_lxc_LDADD += $(BLKID_LIBS)
+-endif
+-if WITH_SECDRIVER_SELINUX
+-libvirt_lxc_CFLAGS += $(SELINUX_CFLAGS)
+-endif
+-if WITH_SECDRIVER_APPARMOR
+-libvirt_lxc_CFLAGS += $(APPARMOR_CFLAGS)
+-endif
+-endif
+-endif
++endif WITH_BLKID
++libvirt_lxc_CFLAGS += $(SECDRIVER_CFLAGS)
++endif WITH_LIBVIRTD
++endif WITH_LXC
+ EXTRA_DIST += $(LXC_CONTROLLER_SOURCES)
+
+ if WITH_SECDRIVER_APPARMOR
+--
+1.8.4.2
+
--- /dev/null
+From 737c22fc278f1329a7fe1732cdd5b0a21495006d Mon Sep 17 00:00:00 2001
+Message-Id: <737c22fc278f1329a7fe1732cdd5b0a21495006d.1377873639.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Wed, 14 Aug 2013 10:42:00 -0600
+Subject: [PATCH] build: fix missing max_queued_clients in augeas test file for
+ libvirtd.conf
+
+https://bugzilla.redhat.com/show_bug.cgi?id=981729
+
+Broken in commit 1199edb1d4e3ebbc691bd32d3519a3b662225420
+
+(cherry picked from commit 1ecbff4073bc9299cee587b2db479c54cc75d096)
+---
+ daemon/test_libvirtd.aug.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/daemon/test_libvirtd.aug.in b/daemon/test_libvirtd.aug.in
+index 4e3b878..a7e8515 100644
+--- a/daemon/test_libvirtd.aug.in
++++ b/daemon/test_libvirtd.aug.in
+@@ -35,6 +35,7 @@ module Test_libvirtd =
+ { "2" = "fred@EXAMPLE.COM" }
+ }
+ { "max_clients" = "20" }
++ { "max_queued_clients" = "1000" }
+ { "min_workers" = "5" }
+ { "max_workers" = "20" }
+ { "prio_workers" = "5" }
+--
+1.8.3.2
+
--- /dev/null
+From ed1ef3fb4a2a5f3b710e2f4e215e8e5b45db6558 Mon Sep 17 00:00:00 2001
+Message-Id: <ed1ef3fb4a2a5f3b710e2f4e215e8e5b45db6558.1383922565.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:14 +0100
+Subject: [PATCH] conf: Do better job when comparing features ABI compatibility
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+The ABI compatibility check for domain features didn't check the
+expanded HyperV and APIC EOI values, thus possibly allowing change in
+guest ABI.
+
+Add the check and use typecasted switch statement to warn developers
+when adding a new HyperV feature.
+
+(cherry picked from commit 5702c014b2b1feba7329e8b3dcc3a6be7cb4a88e)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 67 insertions(+), 5 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index dea8130..a1d7385 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -13315,6 +13315,72 @@ virDomainRedirFilterDefCheckABIStability(virDomainRedirFilterDefPtr src,
+ return true;
+ }
+
++
++static bool
++virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
++ virDomainDefPtr dst)
++{
++ size_t i;
++
++ /* basic check */
++ if (src->features != dst->features) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("Target domain features %d does not match source %d"),
++ dst->features, src->features);
++ return false;
++ }
++
++ /* APIC EOI */
++ if (src->apic_eoi != dst->apic_eoi) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("State of APIC EOI differs: "
++ "source: '%s', destination: '%s'"),
++ virDomainFeatureStateTypeToString(src->apic_eoi),
++ virDomainFeatureStateTypeToString(dst->apic_eoi));
++ return false;
++ }
++
++ /* hyperv */
++ if (src->features & (1 << VIR_DOMAIN_FEATURE_HYPERV)) {
++ for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
++ switch ((enum virDomainHyperv) i) {
++ case VIR_DOMAIN_HYPERV_RELAXED:
++ case VIR_DOMAIN_HYPERV_VAPIC:
++ if (src->hyperv_features[i] != dst->hyperv_features[i]) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("State of HyperV enlightenment "
++ "feature '%s' differs: "
++ "source: '%s', destination: '%s'"),
++ virDomainHypervTypeToString(i),
++ virDomainFeatureStateTypeToString(src->hyperv_features[i]),
++ virDomainFeatureStateTypeToString(dst->hyperv_features[i]));
++ return false;
++ }
++
++ break;
++
++ case VIR_DOMAIN_HYPERV_SPINLOCKS:
++ /* spinlock count matters! */
++ if (src->hyperv_spinlocks != dst->hyperv_spinlocks) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("HyperV spinlock retry count differs: "
++ "source: '%u', destination: '%u'"),
++ src->hyperv_spinlocks,
++ dst->hyperv_spinlocks);
++ return false;
++ }
++ break;
++
++ case VIR_DOMAIN_HYPERV_LAST:
++ break;
++ }
++ }
++ }
++
++ return true;
++}
++
++
+ /* This compares two configurations and looks for any differences
+ * which will affect the guest ABI. This is primarily to allow
+ * validation of custom XML config passed in during migration
+@@ -13416,12 +13482,8 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
+ return false;
+ }
+
+- if (src->features != dst->features) {
+- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+- _("Target domain features %d does not match source %d"),
+- dst->features, src->features);
++ if (!virDomainDefFeaturesCheckABIStability(src, dst))
+ return false;
+- }
+
+ if (src->clock.ntimers != dst->clock.ntimers) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+--
+1.8.4.2
+
--- /dev/null
+From 851b4b9bf41d54da89fc78623785280ff0b9b05b Mon Sep 17 00:00:00 2001
+Message-Id: <851b4b9bf41d54da89fc78623785280ff0b9b05b.1380703761.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 26 Sep 2013 14:03:04 +0200
+Subject: [PATCH] conf: Don't crash on invalid chardev source definition of
+ RNGs and other
+
+Since commit 297c99a5 an invalid source definition XML of a character
+device that is used as backend for RNG devices, smartcards and redirdevs
+causes crash of the daemon when parsing such a definition.
+
+The device types mentioned above are not a part of a regular character
+device but are backends for other types. Thus when parsing such device
+NULL is passed as the argument @chr_def. Later when checking the
+validity of the definition @chr_def was dereferenced when parsing a UNIX
+socket backend with missing path of the socket and crashed the daemon.
+
+Sample offending configuration:
+ <devices>
+ ...
+ <rng model='virtio'>
+ <backend model='egd' type='unix'>
+ <source mode='bind' service='1024'/>
+ </backend>
+ </rng>
+ </devices>
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1012196
+(cherry picked from commit 795527548fea79902ea4ce32747e069944cf3e61)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c | 3 ++-
+ .../qemuxml2argv-virtio-rng-egd-crash.xml | 27 ++++++++++++++++++++++
+ tests/qemuxml2argvtest.c | 2 ++
+ 3 files changed, 31 insertions(+), 1 deletion(-)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd-crash.xml
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index b46381f..c391eae 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -7014,7 +7014,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ /* path can be auto generated */
+ if (!path &&
+- chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
++ (!chr_def ||
++ chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing source path attribute for char device"));
+ goto error;
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd-crash.xml b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd-crash.xml
+new file mode 100644
+index 0000000..ce18ea0
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd-crash.xml
+@@ -0,0 +1,27 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <controller type='usb' index='0'/>
++ <controller type='pci' index='0' model='pci-root'/>
++ <memballoon model='virtio'/>
++ <rng model='virtio'>
++ <backend model='egd' type='unix'>
++ <!-- https://bugzilla.redhat.com/show_bug.cgi?id=1012196 -->
++ <source mode='connect' host='1.2.3.4' service='1234'/>
++ </backend>
++ </rng>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index ca72947..aa43145 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -970,6 +970,8 @@ mymain(void)
+ QEMU_CAPS_OBJECT_RNG_RANDOM);
+ DO_TEST("virtio-rng-egd", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_VIRTIO_RNG,
+ QEMU_CAPS_OBJECT_RNG_EGD);
++ DO_TEST_PARSE_ERROR("virtio-rng-egd-crash", QEMU_CAPS_DEVICE,
++ QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_EGD);
+ DO_TEST("virtio-rng-ccw",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_DRIVE, QEMU_CAPS_BOOTINDEX, QEMU_CAPS_VIRTIO_CCW,
+--
+1.8.3.2
+
--- /dev/null
+From ecfbbe86d4d700201e81c093be30c0933f453d18 Mon Sep 17 00:00:00 2001
+Message-Id: <ecfbbe86d4d700201e81c093be30c0933f453d18.1378475168.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 5 Sep 2013 10:06:38 +0200
+Subject: [PATCH] conf: Don't deref NULL actual network in
+ virDomainNetGetActualHostdev()
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003537
+
+In commit 991270db99690 I've used virDomainNetGetActualHostdev() to get
+the actual hostdev from a network when removing the network from the
+list to avoid leaving the hostdev in the list. I didn't notice that this
+function doesn't check if the actual network is allocated and
+dereferences it. This crashes the daemon when cleaning up a domain
+object in early startup phases when the actual network definition isn't
+allocated. When the actual definition isn't present, the hostdev that
+might correspond to it won't be present anyways so it's safe to return
+NULL.
+
+Thanks to Cole Robinson for noticing this problem.
+
+(cherry picked from commit a3d24862df9d717b95fae3951019fa150a9d4e09)
+---
+ src/conf/domain_conf.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 7a80508..53daf73 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -17799,6 +17799,7 @@ virDomainNetGetActualHostdev(virDomainNetDefPtr iface)
+ if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
+ return &iface->data.hostdev.def;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
++ iface->data.network.actual &&
+ iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ return &iface->data.network.actual->data.hostdev.def;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From f564bc7136bd832cba97926f9a5020a090561434 Mon Sep 17 00:00:00 2001
+Message-Id: <f564bc7136bd832cba97926f9a5020a090561434.1383922565.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:16 +0100
+Subject: [PATCH] conf: Mark user provided strings in error messages when
+ parsing XML
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Use apostrophes to denote user provided option names when parsing the
+domain XML.
+
+(cherry picked from commit 59ae97b4d5305e8e13c1ec05f4a22c61a8ef5b4b)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index a1d7385..79dfb05 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -11316,8 +11316,7 @@ virDomainDefParseXML(xmlDocPtr xml,
+ int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name);
+ if (val < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("unexpected feature %s"),
+- nodes[i]->name);
++ _("unexpected feature '%s'"), nodes[i]->name);
+ goto error;
+ }
+ def->features |= (1 << val);
+@@ -11327,7 +11326,7 @@ virDomainDefParseXML(xmlDocPtr xml,
+ int eoi;
+ if ((eoi = virDomainFeatureStateTypeFromString(tmp)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+- _("unknown value for attribute eoi: %s"),
++ _("unknown value for attribute eoi: '%s'"),
+ tmp);
+ goto error;
+ }
+--
+1.8.4.2
+
--- /dev/null
+From bbad015e6ffe6623b55a1c61aeb0a8d3e65bce6a Mon Sep 17 00:00:00 2001
+Message-Id: <bbad015e6ffe6623b55a1c61aeb0a8d3e65bce6a.1383922567.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:33 +0100
+Subject: [PATCH] conf: Refactor storing and usage of feature flags
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Currently we were storing domain feature flags in a bit field as the
+they were either enabled or disabled. New features such as paravirtual
+spinlocks however can be tri-state as the default option may depend on
+hypervisor version.
+
+To allow storing tri-state feature state in the same place instead of
+having to declare dedicated variables for each feature this patch
+refactors the bit field to an array.
+
+(cherry picked from commit de7b5faf43645229c74843032402c0d58a397e88)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c | 159 ++++++++++++++++++++++++++++++---------------
+ src/conf/domain_conf.h | 2 +-
+ src/libxl/libxl_conf.c | 9 ++-
+ src/lxc/lxc_container.c | 6 +-
+ src/qemu/qemu_command.c | 15 ++---
+ src/vbox/vbox_tmpl.c | 45 +++++++------
+ src/xenapi/xenapi_driver.c | 10 +--
+ src/xenapi/xenapi_utils.c | 22 +++----
+ src/xenxs/xen_sxpr.c | 20 +++---
+ src/xenxs/xen_xm.c | 30 ++++-----
+ 10 files changed, 187 insertions(+), 131 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 79dfb05..6664c2a 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -11319,10 +11319,10 @@ virDomainDefParseXML(xmlDocPtr xml,
+ _("unexpected feature '%s'"), nodes[i]->name);
+ goto error;
+ }
+- def->features |= (1 << val);
+- if (val == VIR_DOMAIN_FEATURE_APIC) {
+- tmp = virXPathString("string(./features/apic/@eoi)", ctxt);
+- if (tmp) {
++
++ switch ((enum virDomainFeature) val) {
++ case VIR_DOMAIN_FEATURE_APIC:
++ if ((tmp = virXPathString("string(./features/apic/@eoi)", ctxt))) {
+ int eoi;
+ if ((eoi = virDomainFeatureStateTypeFromString(tmp)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+@@ -11333,11 +11333,23 @@ virDomainDefParseXML(xmlDocPtr xml,
+ def->apic_eoi = eoi;
+ VIR_FREE(tmp);
+ }
++ /* fallthrough */
++ case VIR_DOMAIN_FEATURE_ACPI:
++ case VIR_DOMAIN_FEATURE_PAE:
++ case VIR_DOMAIN_FEATURE_HAP:
++ case VIR_DOMAIN_FEATURE_VIRIDIAN:
++ case VIR_DOMAIN_FEATURE_PRIVNET:
++ case VIR_DOMAIN_FEATURE_HYPERV:
++ def->features[val] = VIR_DOMAIN_FEATURE_STATE_ON;
++ break;
++
++ case VIR_DOMAIN_FEATURE_LAST:
++ break;
+ }
+ }
+ VIR_FREE(nodes);
+
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_HYPERV)) {
++ if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_FEATURE_STATE_ON) {
+ int feature;
+ int value;
+ node = ctxt->node;
+@@ -13321,12 +13333,16 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
+ {
+ size_t i;
+
+- /* basic check */
+- if (src->features != dst->features) {
+- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+- _("Target domain features %d does not match source %d"),
+- dst->features, src->features);
+- return false;
++ for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
++ if (src->features[i] != dst->features[i]) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("State of feature '%s' differs: "
++ "source: '%s', destination: '%s'"),
++ virDomainFeatureTypeToString(i),
++ virDomainFeatureStateTypeToString(src->features[i]),
++ virDomainFeatureStateTypeToString(dst->features[i]));
++ return false;
++ }
+ }
+
+ /* APIC EOI */
+@@ -13340,7 +13356,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
+ }
+
+ /* hyperv */
+- if (src->features & (1 << VIR_DOMAIN_FEATURE_HYPERV)) {
++ if (src->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_FEATURE_STATE_ON) {
+ for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
+ switch ((enum virDomainHyperv) i) {
+ case VIR_DOMAIN_HYPERV_RELAXED:
+@@ -16647,58 +16663,99 @@ virDomainDefFormatInternal(virDomainDefPtr def,
+ virBufferAddLit(buf, " </idmap>\n");
+ }
+
++ for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
++ if (def->features[i] != VIR_DOMAIN_FEATURE_STATE_DEFAULT)
++ break;
++ }
+
+- if (def->features) {
++ if (i != VIR_DOMAIN_FEATURE_LAST) {
+ virBufferAddLit(buf, " <features>\n");
++
+ for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
+- if (def->features & (1 << i) && i != VIR_DOMAIN_FEATURE_HYPERV) {
+- const char *name = virDomainFeatureTypeToString(i);
+- if (!name) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("unexpected feature %zu"), i);
+- goto error;
+- }
+- virBufferAsprintf(buf, " <%s", name);
+- if (i == VIR_DOMAIN_FEATURE_APIC && def->apic_eoi) {
+- virBufferAsprintf(buf,
+- " eoi='%s'",
+- virDomainFeatureStateTypeToString(def->apic_eoi));
+- }
+- virBufferAddLit(buf, "/>\n");
++ const char *name = virDomainFeatureTypeToString(i);
++ size_t j;
++
++ if (!name) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("unexpected feature %zu"), i);
++ goto error;
+ }
+- }
+
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_HYPERV)) {
+- virBufferAddLit(buf, " <hyperv>\n");
+- for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
+- switch ((enum virDomainHyperv) i) {
+- case VIR_DOMAIN_HYPERV_RELAXED:
+- case VIR_DOMAIN_HYPERV_VAPIC:
+- if (def->hyperv_features[i])
+- virBufferAsprintf(buf, " <%s state='%s'/>\n",
+- virDomainHypervTypeToString(i),
+- virDomainFeatureStateTypeToString(
+- def->hyperv_features[i]));
++ switch ((enum virDomainFeature) i) {
++ case VIR_DOMAIN_FEATURE_ACPI:
++ case VIR_DOMAIN_FEATURE_PAE:
++ case VIR_DOMAIN_FEATURE_HAP:
++ case VIR_DOMAIN_FEATURE_VIRIDIAN:
++ case VIR_DOMAIN_FEATURE_PRIVNET:
++ switch ((enum virDomainFeatureState) def->features[i]) {
++ case VIR_DOMAIN_FEATURE_STATE_DEFAULT:
+ break;
+
+- case VIR_DOMAIN_HYPERV_SPINLOCKS:
+- if (def->hyperv_features[i] == 0)
+- break;
++ case VIR_DOMAIN_FEATURE_STATE_ON:
++ virBufferAsprintf(buf, " <%s/>\n", name);
++ break;
++
++ case VIR_DOMAIN_FEATURE_STATE_LAST:
++ case VIR_DOMAIN_FEATURE_STATE_OFF:
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Unexpected state of feature '%s'"), name);
++
++ goto error;
++ break;
++ }
++
++ break;
+
+- virBufferAsprintf(buf, " <spinlocks state='%s'",
+- virDomainFeatureStateTypeToString(
+- def->hyperv_features[i]));
+- if (def->hyperv_features[i] == VIR_DOMAIN_FEATURE_STATE_ON)
+- virBufferAsprintf(buf, " retries='%d'",
+- def->hyperv_spinlocks);
++ case VIR_DOMAIN_FEATURE_APIC:
++ if (def->features[i] == VIR_DOMAIN_FEATURE_STATE_ON) {
++ virBufferAddLit(buf, " <apic");
++ if (def->apic_eoi) {
++ virBufferAsprintf(buf, " eoi='%s'",
++ virDomainFeatureStateTypeToString(def->apic_eoi));
++ }
+ virBufferAddLit(buf, "/>\n");
+- break;
++ }
++ break;
+
+- case VIR_DOMAIN_HYPERV_LAST:
++ case VIR_DOMAIN_FEATURE_HYPERV:
++ if (def->features[i] != VIR_DOMAIN_FEATURE_STATE_ON)
+ break;
++
++ virBufferAddLit(buf, " <hyperv>\n");
++ for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) {
++ switch ((enum virDomainHyperv) j) {
++ case VIR_DOMAIN_HYPERV_RELAXED:
++ case VIR_DOMAIN_HYPERV_VAPIC:
++ if (def->hyperv_features[j])
++ virBufferAsprintf(buf, " <%s state='%s'/>\n",
++ virDomainHypervTypeToString(j),
++ virDomainFeatureStateTypeToString(
++ def->hyperv_features[j]));
++ break;
++
++ case VIR_DOMAIN_HYPERV_SPINLOCKS:
++ if (def->hyperv_features[j] == 0)
++ break;
++
++ virBufferAsprintf(buf, " <spinlocks state='%s'",
++ virDomainFeatureStateTypeToString(
++ def->hyperv_features[j]));
++ if (def->hyperv_features[j] == VIR_DOMAIN_FEATURE_STATE_ON)
++ virBufferAsprintf(buf, " retries='%d'",
++ def->hyperv_spinlocks);
++ virBufferAddLit(buf, "/>\n");
++ break;
++
++ case VIR_DOMAIN_HYPERV_LAST:
++ break;
++ }
+ }
++ virBufferAddLit(buf, " </hyperv>\n");
++ break;
++
++ case VIR_DOMAIN_FEATURE_LAST:
++ break;
+ }
+- virBufferAddLit(buf, " </hyperv>\n");
+ }
+
+ virBufferAddLit(buf, " </features>\n");
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 5ad0318..3d2b3a4 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -1972,7 +1972,7 @@ struct _virDomainDef {
+
+ virDomainOSDef os;
+ char *emulator;
+- int features;
++ int features[VIR_DOMAIN_FEATURE_LAST];
+ /* enum virDomainFeatureState */
+ int apic_eoi;
+ /* These options are of type virDomainFeatureState */
+diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
+index 5273a26..6bfe934 100644
+--- a/src/libxl/libxl_conf.c
++++ b/src/libxl/libxl_conf.c
+@@ -373,11 +373,14 @@ libxlMakeDomBuildInfo(virDomainObjPtr vm, libxl_domain_config *d_config)
+ char bootorder[VIR_DOMAIN_BOOT_LAST + 1];
+
+ libxl_defbool_set(&b_info->u.hvm.pae,
+- def->features & (1 << VIR_DOMAIN_FEATURE_PAE));
++ def->features[VIR_DOMAIN_FEATURE_PAE] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ libxl_defbool_set(&b_info->u.hvm.apic,
+- def->features & (1 << VIR_DOMAIN_FEATURE_APIC));
++ def->features[VIR_DOMAIN_FEATURE_APIC] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ libxl_defbool_set(&b_info->u.hvm.acpi,
+- def->features & (1 << VIR_DOMAIN_FEATURE_ACPI));
++ def->features[VIR_DOMAIN_FEATURE_ACPI] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ for (i = 0; i < def->clock.ntimers; i++) {
+ if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET &&
+ def->clock.timers[i]->present == 1) {
+diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
+index 9479498..01ed93e 100644
+--- a/src/lxc/lxc_container.c
++++ b/src/lxc/lxc_container.c
+@@ -1838,8 +1838,8 @@ static int lxcContainerChild(void *data)
+ }
+
+ /* rename and enable interfaces */
+- if (lxcContainerRenameAndEnableInterfaces(!!(vmDef->features &
+- (1 << VIR_DOMAIN_FEATURE_PRIVNET)),
++ if (lxcContainerRenameAndEnableInterfaces(vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
++ VIR_DOMAIN_FEATURE_STATE_ON,
+ argv->nveths,
+ argv->veths) < 0) {
+ goto cleanup;
+@@ -1929,7 +1929,7 @@ lxcNeedNetworkNamespace(virDomainDefPtr def)
+ size_t i;
+ if (def->nets != NULL)
+ return true;
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET))
++ if (def->features[VIR_DOMAIN_FEATURE_PRIVNET] == VIR_DOMAIN_FEATURE_STATE_ON)
+ return true;
+ for (i = 0; i < def->nhostdevs; i++) {
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES &&
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 0292b72..f14b0f2 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -6574,7 +6574,7 @@ qemuBuildCpuArgStr(const virQEMUDriverPtr driver,
+ have_cpu = true;
+ }
+
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_HYPERV)) {
++ if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_FEATURE_STATE_ON) {
+ if (!have_cpu) {
+ virBufferAdd(&buf, default_model, -1);
+ have_cpu = true;
+@@ -7905,7 +7905,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ }
+
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI)) {
+- if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
++ if (def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_DOMAIN_FEATURE_STATE_ON)
+ virCommandAddArg(cmd, "-no-acpi");
+ }
+
+@@ -10634,7 +10634,7 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
+ if (*feature == '\0')
+ goto syntax;
+
+- dom->features |= (1 << VIR_DOMAIN_FEATURE_HYPERV);
++ dom->features[VIR_DOMAIN_FEATURE_HYPERV] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ if ((f = virDomainHypervTypeFromString(feature)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+@@ -10888,7 +10888,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ goto error;
+ if (strstr(path, "kvm")) {
+ def->virtType = VIR_DOMAIN_VIRT_KVM;
+- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
++ def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+ }
+ }
+
+@@ -10901,8 +10901,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+
+ if ((def->os.arch == VIR_ARCH_I686) ||
+ (def->os.arch == VIR_ARCH_X86_64))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI)
+- /*| (1 << VIR_DOMAIN_FEATURE_APIC)*/;
++ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ #define WANT_VALUE() \
+ const char *val = progargv[++i]; \
+@@ -11196,7 +11195,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ def->disks[def->ndisks++] = disk;
+ disk = NULL;
+ } else if (STREQ(arg, "-no-acpi")) {
+- def->features &= ~(1 << VIR_DOMAIN_FEATURE_ACPI);
++ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_DEFAULT;
+ } else if (STREQ(arg, "-no-reboot")) {
+ def->onReboot = VIR_DOMAIN_LIFECYCLE_DESTROY;
+ } else if (STREQ(arg, "-no-kvm")) {
+@@ -11314,7 +11313,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ def->mem.nosharepages = true;
+ } else if (STRPREFIX(param, "accel=kvm")) {
+ def->virtType = VIR_DOMAIN_VIRT_KVM;
+- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
++ def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+ }
+ }
+ virStringFreeList(list);
+diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
+index 5b17048..3e9f0d9 100644
+--- a/src/vbox/vbox_tmpl.c
++++ b/src/vbox/vbox_tmpl.c
+@@ -2362,7 +2362,6 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) {
+ }
+ }
+
+- def->features = 0;
+ #if VBOX_API_VERSION < 3001
+ machine->vtbl->GetPAEEnabled(machine, &PAEEnabled);
+ #elif VBOX_API_VERSION == 3001
+@@ -2370,21 +2369,18 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) {
+ #elif VBOX_API_VERSION >= 3002
+ machine->vtbl->GetCPUProperty(machine, CPUPropertyType_PAE, &PAEEnabled);
+ #endif
+- if (PAEEnabled) {
+- def->features = def->features | (1 << VIR_DOMAIN_FEATURE_PAE);
+- }
++ if (PAEEnabled)
++ def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ machine->vtbl->GetBIOSSettings(machine, &bios);
+ if (bios) {
+ bios->vtbl->GetACPIEnabled(bios, &ACPIEnabled);
+- if (ACPIEnabled) {
+- def->features = def->features | (1 << VIR_DOMAIN_FEATURE_ACPI);
+- }
++ if (ACPIEnabled)
++ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ bios->vtbl->GetIOAPICEnabled(bios, &IOAPICEnabled);
+- if (IOAPICEnabled) {
+- def->features = def->features | (1 << VIR_DOMAIN_FEATURE_APIC);
+- }
++ if (IOAPICEnabled)
++ def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ VBOX_RELEASE(bios);
+ }
+@@ -5101,40 +5097,43 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) {
+ }
+
+ #if VBOX_API_VERSION < 3001
+- rc = machine->vtbl->SetPAEEnabled(machine, (def->features) &
+- (1 << VIR_DOMAIN_FEATURE_PAE));
++ rc = machine->vtbl->SetPAEEnabled(machine,
++ def->features[VIR_DOMAIN_FEATURE_PAE] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ #elif VBOX_API_VERSION == 3001
+ rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE,
+- (def->features) &
+- (1 << VIR_DOMAIN_FEATURE_PAE));
++ def->features[VIR_DOMAIN_FEATURE_PAE] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ #elif VBOX_API_VERSION >= 3002
+ rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE,
+- (def->features) &
+- (1 << VIR_DOMAIN_FEATURE_PAE));
++ def->features[VIR_DOMAIN_FEATURE_PAE] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ #endif
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not change PAE status to: %s, rc=%08x"),
+- ((def->features) & (1 << VIR_DOMAIN_FEATURE_PAE))
++ (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
+ ? _("Enabled") : _("Disabled"), (unsigned)rc);
+ }
+
+ machine->vtbl->GetBIOSSettings(machine, &bios);
+ if (bios) {
+- rc = bios->vtbl->SetACPIEnabled(bios, (def->features) &
+- (1 << VIR_DOMAIN_FEATURE_ACPI));
++ rc = bios->vtbl->SetACPIEnabled(bios,
++ def->features[VIR_DOMAIN_FEATURE_ACPI] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not change ACPI status to: %s, rc=%08x"),
+- ((def->features) & (1 << VIR_DOMAIN_FEATURE_ACPI))
++ (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
+ ? _("Enabled") : _("Disabled"), (unsigned)rc);
+ }
+- rc = bios->vtbl->SetIOAPICEnabled(bios, (def->features) &
+- (1 << VIR_DOMAIN_FEATURE_APIC));
++ rc = bios->vtbl->SetIOAPICEnabled(bios,
++ def->features[VIR_DOMAIN_FEATURE_APIC] ==
++ VIR_DOMAIN_FEATURE_STATE_ON);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not change APIC status to: %s, rc=%08x"),
+- ((def->features) & (1 << VIR_DOMAIN_FEATURE_APIC))
++ (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
+ ? _("Enabled") : _("Disabled"), (unsigned)rc);
+ }
+ VBOX_RELEASE(bios);
+diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
+index bca19af..5f8ca08 100644
+--- a/src/xenapi/xenapi_driver.c
++++ b/src/xenapi/xenapi_driver.c
+@@ -1474,15 +1474,15 @@ xenapiDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
+ for (i = 0; i < result->size; i++) {
+ if (STREQ(result->contents[i].val, "true")) {
+ if (STREQ(result->contents[i].key, "acpi"))
+- defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_ACPI);
++ defPtr->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
+ else if (STREQ(result->contents[i].key, "apic"))
+- defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_APIC);
++ defPtr->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
+ else if (STREQ(result->contents[i].key, "pae"))
+- defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_PAE);
++ defPtr->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+ else if (STREQ(result->contents[i].key, "hap"))
+- defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_HAP);
++ defPtr->features[VIR_DOMAIN_FEATURE_HAP] = VIR_DOMAIN_FEATURE_STATE_ON;
+ else if (STREQ(result->contents[i].key, "viridian"))
+- defPtr->features = defPtr->features | (1<<VIR_DOMAIN_FEATURE_VIRIDIAN);
++ defPtr->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_DOMAIN_FEATURE_STATE_ON;
+ }
+ }
+ xen_string_string_map_free(result);
+diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
+index 91ae54b..02d4885 100644
+--- a/src/xenapi/xenapi_utils.c
++++ b/src/xenapi/xenapi_utils.c
+@@ -511,18 +511,16 @@ createVMRecordFromXml(virConnectPtr conn, virDomainDefPtr def,
+ if (def->onCrash)
+ (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);
+
+- if (def->features) {
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
+- allocStringMap(&strings, (char *)"acpi", (char *)"true");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
+- allocStringMap(&strings, (char *)"apic", (char *)"true");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
+- allocStringMap(&strings, (char *)"pae", (char *)"true");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
+- allocStringMap(&strings, (char *)"hap", (char *)"true");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_VIRIDIAN))
+- allocStringMap(&strings, (char *)"viridian", (char *)"true");
+- }
++ if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
++ allocStringMap(&strings, (char *)"acpi", (char *)"true");
++ if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
++ allocStringMap(&strings, (char *)"apic", (char *)"true");
++ if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
++ allocStringMap(&strings, (char *)"pae", (char *)"true");
++ if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_DOMAIN_FEATURE_STATE_ON)
++ allocStringMap(&strings, (char *)"hap", (char *)"true");
++ if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_DOMAIN_FEATURE_STATE_ON)
++ allocStringMap(&strings, (char *)"viridian", (char *)"true");
+ if (strings != NULL)
+ (*record)->platform = strings;
+
+diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
+index fbbbaa9..fb01e0d 100644
+--- a/src/xenxs/xen_sxpr.c
++++ b/src/xenxs/xen_sxpr.c
+@@ -1204,15 +1204,15 @@ xenParseSxpr(const struct sexpr *root,
+
+ if (hvm) {
+ if (sexpr_int(root, "domain/image/hvm/acpi"))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
++ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (sexpr_int(root, "domain/image/hvm/apic"))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
++ def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (sexpr_int(root, "domain/image/hvm/pae"))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
++ def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (sexpr_int(root, "domain/image/hvm/hap"))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
++ def->features[VIR_DOMAIN_FEATURE_HAP] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (sexpr_int(root, "domain/image/hvm/viridian"))
+- def->features |= (1 << VIR_DOMAIN_FEATURE_VIRIDIAN);
++ def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_DOMAIN_FEATURE_STATE_ON;
+ }
+
+ /* 12aaf4a2486b (3.0.3) added a second low-priority 'localtime' setting */
+@@ -2335,15 +2335,15 @@ xenFormatSxpr(virConnectPtr conn,
+ }
+ }
+
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
++ if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
+ virBufferAddLit(&buf, "(acpi 1)");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
++ if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
+ virBufferAddLit(&buf, "(apic 1)");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
++ if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
+ virBufferAddLit(&buf, "(pae 1)");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
++ if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_DOMAIN_FEATURE_STATE_ON)
+ virBufferAddLit(&buf, "(hap 1)");
+- if (def->features & (1 << VIR_DOMAIN_FEATURE_VIRIDIAN))
++ if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_DOMAIN_FEATURE_STATE_ON)
+ virBufferAddLit(&buf, "(viridian 1)");
+
+ virBufferAddLit(&buf, "(usb 1)");
+diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c
+index 1ffea84..1a1cd12 100644
+--- a/src/xenxs/xen_xm.c
++++ b/src/xenxs/xen_xm.c
+@@ -398,23 +398,23 @@ xenParseXM(virConfPtr conf, int xendConfigVersion,
+ if (xenXMConfigGetBool(conf, "pae", &val, 0) < 0)
+ goto cleanup;
+ else if (val)
+- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
++ def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (xenXMConfigGetBool(conf, "acpi", &val, 0) < 0)
+ goto cleanup;
+ else if (val)
+- def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
++ def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (xenXMConfigGetBool(conf, "apic", &val, 0) < 0)
+ goto cleanup;
+ else if (val)
+- def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
++ def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (xenXMConfigGetBool(conf, "hap", &val, 0) < 0)
+ goto cleanup;
+ else if (val)
+- def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
++ def->features[VIR_DOMAIN_FEATURE_HAP] = VIR_DOMAIN_FEATURE_STATE_ON;
+ if (xenXMConfigGetBool(conf, "viridian", &val, 0) < 0)
+ goto cleanup;
+ else if (val)
+- def->features |= (1 << VIR_DOMAIN_FEATURE_VIRIDIAN);
++ def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_DOMAIN_FEATURE_STATE_ON;
+
+ if (xenXMConfigGetBool(conf, "hpet", &val, -1) < 0)
+ goto cleanup;
+@@ -1569,29 +1569,29 @@ virConfPtr xenFormatXM(virConnectPtr conn,
+ goto cleanup;
+
+ if (xenXMConfigSetInt(conf, "pae",
+- (def->features &
+- (1 << VIR_DOMAIN_FEATURE_PAE)) ? 1 : 0) < 0)
++ (def->features[VIR_DOMAIN_FEATURE_PAE] ==
++ VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
+ goto cleanup;
+
+ if (xenXMConfigSetInt(conf, "acpi",
+- (def->features &
+- (1 << VIR_DOMAIN_FEATURE_ACPI)) ? 1 : 0) < 0)
++ (def->features[VIR_DOMAIN_FEATURE_ACPI] ==
++ VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
+ goto cleanup;
+
+ if (xenXMConfigSetInt(conf, "apic",
+- (def->features &
+- (1 << VIR_DOMAIN_FEATURE_APIC)) ? 1 : 0) < 0)
++ (def->features[VIR_DOMAIN_FEATURE_APIC] ==
++ VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
+ goto cleanup;
+
+ if (xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4) {
+ if (xenXMConfigSetInt(conf, "hap",
+- (def->features &
+- (1 << VIR_DOMAIN_FEATURE_HAP)) ? 1 : 0) < 0)
++ (def->features[VIR_DOMAIN_FEATURE_HAP] ==
++ VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
+ goto cleanup;
+
+ if (xenXMConfigSetInt(conf, "viridian",
+- (def->features &
+- (1 << VIR_DOMAIN_FEATURE_VIRIDIAN)) ? 1 : 0) < 0)
++ (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] ==
++ VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
+ goto cleanup;
+ }
+
+--
+1.8.4.2
+
--- /dev/null
+From 5ac7b872d91e8cb14fffbadc732b2d214009dd3c Mon Sep 17 00:00:00 2001
+Message-Id: <5ac7b872d91e8cb14fffbadc732b2d214009dd3c.1378475168.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Wed, 4 Sep 2013 10:30:15 +0200
+Subject: [PATCH] conf: Remove the actual hostdev when removing a network
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003537
+
+Commit 50348e6edfa reused the code to remove the hostdev portion of a
+network definition on multiple places but forgot to take into account
+that sometimes the "actual" network is passed and in some cases the
+parent of that.
+
+This patch uses the virDomainNetGetActualHostdev() helper to acquire the
+correct pointer all the time while removing the hostdev portion from the
+list.
+
+(cherry picked from commit 991270db9969026876c3f5911143dab13ab9050d)
+---
+ src/conf/domain_conf.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 1a20232..7a80508 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -9941,14 +9941,14 @@ void
+ virDomainNetRemoveHostdev(virDomainDefPtr def,
+ virDomainNetDefPtr net)
+ {
+- if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+- /* hostdev net devices are normally also be in the hostdevs
+- * array, but might have already been removed by the time we
+- * get here.
+- */
+- virDomainHostdevDefPtr hostdev = &net->data.hostdev.def;
+- size_t i;
++ /* hostdev net devices are normally also be in the hostdevs
++ * array, but might have already been removed by the time we
++ * get here.
++ */
++ virDomainHostdevDefPtr hostdev = virDomainNetGetActualHostdev(net);
++ size_t i;
+
++ if (hostdev) {
+ for (i = 0; i < def->nhostdevs; i++) {
+ if (def->hostdevs[i] == hostdev) {
+ virDomainHostdevRemove(def, i);
+--
+1.8.3.2
+
--- /dev/null
+From de73bf2cf5f37eab8fd19c4a5a773484c6e6b464 Mon Sep 17 00:00:00 2001
+Message-Id: <de73bf2cf5f37eab8fd19c4a5a773484c6e6b464.1377873636.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:18 -0600
+Subject: [PATCH] conf: add default USB controller in qemu post-parse callback
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+The parser shouldn't be doing arch-specific things like adding in
+implicit controllers to the config. This should instead be done in the
+hypervisor's post-parse callback.
+
+This patch removes the auto-add of a usb controller from the domain
+parser, and puts it into the qemu driver's post-parse callback (just
+as is already done with the auto-add of the pci-root controller). In
+the future, any machine/arch that shouldn't have a default usb
+controller added should just set addDefaultUSB = false in this
+function.
+
+We've recently seen that q35 and ARMV7L domains shouldn't get a default USB
+controller, so I've set addDefaultUSB to false for both of those.
+(cherry picked from commit c66da9d224ffba1d972beaf049c00dbebda4e8ea)
+---
+ src/conf/domain_conf.c | 6 ------
+ src/qemu/qemu_domain.c | 14 +++++++++++++-
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 783df96..18c6acf 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -11718,12 +11718,6 @@ virDomainDefParseXML(xmlDocPtr xml,
+ goto error;
+ }
+
+- if (def->virtType == VIR_DOMAIN_VIRT_QEMU ||
+- def->virtType == VIR_DOMAIN_VIRT_KQEMU ||
+- def->virtType == VIR_DOMAIN_VIRT_KVM)
+- if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, -1) < 0)
+- goto error;
+-
+ /* analysis of the resource leases */
+ if ((n = virXPathNodeSet("./devices/lease", ctxt, &nodes)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index da3b768..648121a 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -699,6 +699,7 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ virCapsPtr caps,
+ void *opaque ATTRIBUTE_UNUSED)
+ {
++ bool addDefaultUSB = true;
+ bool addPCIRoot = false;
+
+ /* check for emulator and create a default one if needed */
+@@ -714,8 +715,10 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ break;
+ if (STRPREFIX(def->os.machine, "pc-q35") ||
+ STREQ(def->os.machine, "q35") ||
+- STREQ(def->os.machine, "isapc"))
++ STREQ(def->os.machine, "isapc")) {
++ addDefaultUSB = false;
+ break;
++ }
+ if (!STRPREFIX(def->os.machine, "pc-0.") &&
+ !STRPREFIX(def->os.machine, "pc-1.") &&
+ !STRPREFIX(def->os.machine, "pc-i440") &&
+@@ -725,6 +728,10 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ addPCIRoot = true;
+ break;
+
++ case VIR_ARCH_ARMV7L:
++ addDefaultUSB = false;
++ break;
++
+ case VIR_ARCH_ALPHA:
+ case VIR_ARCH_PPC:
+ case VIR_ARCH_PPC64:
+@@ -737,6 +744,11 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ break;
+ }
+
++ if (addDefaultUSB &&
++ virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, -1) < 0)
++ return -1;
++
+ if (addPCIRoot &&
+ virDomainDefMaybeAddController(
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+--
+1.8.3.2
+
--- /dev/null
+From 933e0aeebdbdc2932a1b11ce338c67bb163268f5 Mon Sep 17 00:00:00 2001
+Message-Id: <933e0aeebdbdc2932a1b11ce338c67bb163268f5.1377873637.git.jdenemar@redhat.com>
+From: Guannan Ren <gren@redhat.com>
+Date: Thu, 8 Aug 2013 16:07:29 +0800
+Subject: [PATCH] conf: add startupPolicy attribute for harddisk
+
+Resovles: https://bugzilla.redhat.com/show_bug.cgi?id=910171
+(cherry picked from commit 93319da42cd1a23245577dda244998f1ff725703)
+
+Add startupPolicy attribute for harddisk with type "file",
+"block" and "dir". 'requisite' is not supported currently for
+harddisk.
+---
+ docs/formatdomain.html.in | 8 ++++++--
+ docs/schemas/domaincommon.rng | 6 ++++++
+ src/conf/domain_conf.c | 31 +++++++++++++++++++++++--------
+ 3 files changed, 35 insertions(+), 10 deletions(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 562d991..fb7d671 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -1620,7 +1620,8 @@
+ policy what to do with the disk if the source file is not accessible.
+ (NB, <code>startupPolicy</code> is not valid for "volume" disk unless
+ the specified storage volume is of "file" type). This is done by the
+- <code>startupPolicy</code> attribute, accepting these values:
++ <code>startupPolicy</code> attribute (<span class="since">Since 0.9.7</span>),
++ accepting these values:
+ <table class="top_table">
+ <tr>
+ <td> mandatory </td>
+@@ -1636,7 +1637,10 @@
+ <td> drop if missing at any start attempt </td>
+ </tr>
+ </table>
+- <span class="since">Since 0.9.7</span>
++ <span class="since">Since 1.1.2</span> the <code>startupPolicy</code> is extended
++ to support hard disks besides cdrom and floppy. On guest cold bootup, if a certain disk
++ is not accessible or its disk chain is broken, with startupPolicy 'optional' the guest
++ will drop this disk. This feature doesn't support migration currently.
+ </dd>
+ <dt><code>mirror</code></dt>
+ <dd>
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 173359c..ac807e6 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -1124,6 +1124,9 @@
+ <ref name="absFilePath"/>
+ </attribute>
+ <optional>
++ <ref name="startupPolicy"/>
++ </optional>
++ <optional>
+ <ref name='devSeclabel'/>
+ </optional>
+ </element>
+@@ -1141,6 +1144,9 @@
+ <attribute name="dir">
+ <ref name="absFilePath"/>
+ </attribute>
++ <optional>
++ <ref name="startupPolicy"/>
++ </optional>
+ <empty/>
+ </element>
+ </optional>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index f46b17e..01f9bd0 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -4796,7 +4796,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
+ switch (def->type) {
+ case VIR_DOMAIN_DISK_TYPE_FILE:
+ source = virXMLPropString(cur, "file");
+- startupPolicy = virXMLPropString(cur, "startupPolicy");
+ break;
+ case VIR_DOMAIN_DISK_TYPE_BLOCK:
+ source = virXMLPropString(cur, "dev");
+@@ -4883,7 +4882,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
+ case VIR_DOMAIN_DISK_TYPE_VOLUME:
+ if (virDomainDiskSourcePoolDefParse(cur, def) < 0)
+ goto error;
+- startupPolicy = virXMLPropString(cur, "startupPolicy");
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -4892,6 +4890,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
+ goto error;
+ }
+
++ startupPolicy = virXMLPropString(cur, "startupPolicy");
++
+ /* People sometimes pass a bogus '' source path
+ when they mean to omit the source element
+ completely (e.g. CDROM without media). This is
+@@ -5464,14 +5464,22 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
+ goto error;
+ }
+
+- if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
+- def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+- virReportError(VIR_ERR_INVALID_ARG,
+- _("Setting disk %s is allowed only for "
+- "cdrom or floppy"),
++ if (def->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
++ virReportError(VIR_ERR_XML_ERROR,
++ _("Setting disk %s is not allowed for "
++ "disk of network type"),
+ startupPolicy);
+ goto error;
+ }
++
++ if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
++ def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
++ val == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) {
++ virReportError(VIR_ERR_XML_ERROR, "%s",
++ _("Setting disk 'requisite' is allowed only for "
++ "cdrom or floppy"));
++ goto error;
++ }
+ def->startupPolicy = val;
+ }
+
+@@ -14121,6 +14129,9 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
+ case VIR_DOMAIN_DISK_TYPE_BLOCK:
+ virBufferEscapeString(buf, " <source dev='%s'",
+ def->src);
++ if (def->startupPolicy)
++ virBufferEscapeString(buf, " startupPolicy='%s'",
++ startupPolicy);
+ if (def->nseclabels) {
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 8);
+@@ -14133,8 +14144,12 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
+ }
+ break;
+ case VIR_DOMAIN_DISK_TYPE_DIR:
+- virBufferEscapeString(buf, " <source dir='%s'/>\n",
++ virBufferEscapeString(buf, " <source dir='%s'",
+ def->src);
++ if (def->startupPolicy)
++ virBufferEscapeString(buf, " startupPolicy='%s'",
++ startupPolicy);
++ virBufferAddLit(buf, "/>\n");
+ break;
+ case VIR_DOMAIN_DISK_TYPE_NETWORK:
+ virBufferAsprintf(buf, " <source protocol='%s'",
+--
+1.8.3.2
+
--- /dev/null
+From ba31d47b940dc748a291e9b68efcf84178ea6800 Mon Sep 17 00:00:00 2001
+Message-Id: <ba31d47b940dc748a291e9b68efcf84178ea6800.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:17 +0100
+Subject: [PATCH] cpu: Add support for loading and storing CPU data
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+This patch adds cpuDataFormat and cpuDataParse APIs to be used in unit
+tests for testing APIs that deal with virCPUData. In the x86 world, this
+means we can now store/load arbitrary CPUID data in the test suite to
+check correctness of CPU related APIs that could not be tested before.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 376261d164b0872bf011e525b4f0f050e942ace5)
+
+Conflicts:
+ src/cpu/cpu.h - virCPUGetModel was not backported (context)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu.c | 41 ++++++++++++++
+ src/cpu/cpu.h | 14 +++++
+ src/cpu/cpu_x86.c | 135 +++++++++++++++++++++++++++++++++++++++--------
+ src/libvirt_private.syms | 2 +
+ 4 files changed, 171 insertions(+), 21 deletions(-)
+
+diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
+index 4124354..7989b45 100644
+--- a/src/cpu/cpu.c
++++ b/src/cpu/cpu.c
+@@ -438,6 +438,47 @@ cpuHasFeature(const virCPUDataPtr data,
+ return driver->hasFeature(data, feature);
+ }
+
++char *
++cpuDataFormat(const virCPUData *data)
++{
++ struct cpuArchDriver *driver;
++
++ VIR_DEBUG("data=%p", data);
++
++ if (!(driver = cpuGetSubDriver(data->arch)))
++ return NULL;
++
++ if (!driver->dataFormat) {
++ virReportError(VIR_ERR_NO_SUPPORT,
++ _("cannot format %s CPU data"),
++ virArchToString(data->arch));
++ return NULL;
++ }
++
++ return driver->dataFormat(data);
++}
++
++virCPUDataPtr
++cpuDataParse(virArch arch,
++ const char *xmlStr)
++{
++ struct cpuArchDriver *driver;
++
++ VIR_DEBUG("arch=%s, xmlStr=%s", virArchToString(arch), xmlStr);
++
++ if (!(driver = cpuGetSubDriver(arch)))
++ return NULL;
++
++ if (!driver->dataParse) {
++ virReportError(VIR_ERR_NO_SUPPORT,
++ _("cannot parse %s CPU data"),
++ virArchToString(arch));
++ return NULL;
++ }
++
++ return driver->dataParse(xmlStr);
++}
++
+ bool
+ cpuModelIsAllowed(const char *model,
+ const char **models,
+diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
+index 4003435..7417f92 100644
+--- a/src/cpu/cpu.h
++++ b/src/cpu/cpu.h
+@@ -91,6 +91,11 @@ typedef int
+ (*cpuArchHasFeature) (const virCPUDataPtr data,
+ const char *feature);
+
++typedef char *
++(*cpuArchDataFormat)(const virCPUData *data);
++
++typedef virCPUDataPtr
++(*cpuArchDataParse) (const char *xmlStr);
+
+ struct cpuArchDriver {
+ const char *name;
+@@ -105,6 +110,8 @@ struct cpuArchDriver {
+ cpuArchBaseline baseline;
+ cpuArchUpdate update;
+ cpuArchHasFeature hasFeature;
++ cpuArchDataFormat dataFormat;
++ cpuArchDataParse dataParse;
+ };
+
+
+@@ -171,4 +178,11 @@ cpuModelIsAllowed(const char *model,
+ const char **models,
+ unsigned int nmodels);
+
++/* cpuDataFormat and cpuDataParse are implemented for unit tests only and
++ * have no real-life usage
++ */
++char *cpuDataFormat(const virCPUData *data);
++virCPUDataPtr cpuDataParse(virArch arch,
++ const char *xmlStr);
++
+ #endif /* __VIR_CPU_H__ */
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index a388f0f..0bc031b 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -666,12 +666,42 @@ x86FeatureNames(const struct x86_map *map,
+
+
+ static int
++x86ParseCPUID(xmlXPathContextPtr ctxt,
++ struct cpuX86cpuid *cpuid)
++{
++ unsigned long fun, eax, ebx, ecx, edx;
++ int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
++
++ memset(cpuid, 0, sizeof(*cpuid));
++
++ fun = eax = ebx = ecx = edx = 0;
++ ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
++ ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
++ ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
++ ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
++ ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
++
++ if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
++ || ret_ecx == -2 || ret_edx == -2)
++ return -1;
++
++ cpuid->function = fun;
++ cpuid->eax = eax;
++ cpuid->ebx = ebx;
++ cpuid->ecx = ecx;
++ cpuid->edx = edx;
++ return 0;
++}
++
++
++static int
+ x86FeatureLoad(xmlXPathContextPtr ctxt,
+ struct x86_map *map)
+ {
+ xmlNodePtr *nodes = NULL;
+ xmlNodePtr ctxt_node = ctxt->node;
+ struct x86_feature *feature;
++ struct cpuX86cpuid cpuid;
+ int ret = 0;
+ size_t i;
+ int n;
+@@ -697,31 +727,13 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
+ goto ignore;
+
+ for (i = 0; i < n; i++) {
+- struct cpuX86cpuid cpuid;
+- unsigned long fun, eax, ebx, ecx, edx;
+- int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
+-
+ ctxt->node = nodes[i];
+- fun = eax = ebx = ecx = edx = 0;
+- ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
+- ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
+- ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
+- ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
+- ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
+-
+- if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
+- || ret_ecx == -2 || ret_edx == -2) {
++ if (x86ParseCPUID(ctxt, &cpuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("Invalid cpuid[%zu] in %s feature"), i, feature->name);
++ _("Invalid cpuid[%zu] in %s feature"),
++ i, feature->name);
+ goto ignore;
+ }
+-
+- cpuid.function = fun;
+- cpuid.eax = eax;
+- cpuid.ebx = ebx;
+- cpuid.ecx = ecx;
+- cpuid.edx = edx;
+-
+ if (x86DataAddCpuid(feature->data, &cpuid))
+ goto error;
+ }
+@@ -1124,6 +1136,85 @@ error:
+ }
+
+
++static char *
++x86CPUDataFormat(const virCPUData *data)
++{
++ struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
++ struct cpuX86cpuid *cpuid;
++ virBuffer buf = VIR_BUFFER_INITIALIZER;
++
++ virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
++ while ((cpuid = x86DataCpuidNext(&iter))) {
++ virBufferAsprintf(&buf,
++ " <cpuid function='0x%08x'"
++ " eax='0x%08x' ebx='0x%08x'"
++ " ecx='0x%08x' edx='0x%08x'/>\n",
++ cpuid->function,
++ cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
++ }
++ virBufferAddLit(&buf, "</cpudata>\n");
++
++ if (virBufferError(&buf)) {
++ virBufferFreeAndReset(&buf);
++ virReportOOMError();
++ return NULL;
++ }
++
++ return virBufferContentAndReset(&buf);
++}
++
++
++static virCPUDataPtr
++x86CPUDataParse(const char *xmlStr)
++{
++ xmlDocPtr xml = NULL;
++ xmlXPathContextPtr ctxt = NULL;
++ xmlNodePtr *nodes = NULL;
++ virCPUDataPtr cpuData = NULL;
++ struct cpuX86Data *data = NULL;
++ struct cpuX86cpuid cpuid;
++ size_t i;
++ int n;
++
++ if (VIR_ALLOC(data) < 0)
++ goto cleanup;
++
++ if (!(xml = virXMLParseStringCtxt(xmlStr, _("CPU data"), &ctxt))) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("cannot parse CPU data"));
++ goto cleanup;
++ }
++ ctxt->node = xmlDocGetRootElement(xml);
++
++ n = virXPathNodeSet("/cpudata[@arch='x86']/data", ctxt, &nodes);
++ if (n < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("no x86 CPU data found"));
++ goto cleanup;
++ }
++
++ for (i = 0; i < n; i++) {
++ ctxt->node = nodes[i];
++ if (x86ParseCPUID(ctxt, &cpuid) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("failed to parse cpuid[%zu]"), i);
++ goto cleanup;
++ }
++ if (x86DataAddCpuid(data, &cpuid) < 0)
++ goto cleanup;
++ }
++
++ cpuData = x86MakeCPUData(VIR_ARCH_X86_64, &data);
++
++cleanup:
++ VIR_FREE(nodes);
++ xmlXPathFreeContext(ctxt);
++ xmlFreeDoc(xml);
++ x86DataFree(data);
++ return cpuData;
++}
++
++
+ /* A helper macro to exit the cpu computation function without writing
+ * redundant code:
+ * MSG: error message
+@@ -1920,4 +2011,6 @@ struct cpuArchDriver cpuDriverX86 = {
+ .baseline = x86Baseline,
+ .update = x86Update,
+ .hasFeature = x86HasFeature,
++ .dataFormat = x86CPUDataFormat,
++ .dataParse = x86CPUDataParse,
+ };
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index ca6275c..722178b 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -715,7 +715,9 @@ cpuBaseline;
+ cpuBaselineXML;
+ cpuCompare;
+ cpuCompareXML;
++cpuDataFormat;
+ cpuDataFree;
++cpuDataParse;
+ cpuDecode;
+ cpuEncode;
+ cpuGuestData;
+--
+1.8.4.2
+
--- /dev/null
+From d5300cc7fb7dbe97af5b910f31d5c35a500c3013 Mon Sep 17 00:00:00 2001
+Message-Id: <d5300cc7fb7dbe97af5b910f31d5c35a500c3013.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:28 +0100
+Subject: [PATCH] cpu: Export few x86-specific APIs
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+This makes virCPUx86DataAddCPUID, virCPUx86DataFree, and
+virCPUx86MakeData available for direct usage outside of cpu driver in
+tests and the new qemu monitor that will request the actual CPU
+definition from a running qemu instance.
+
+(cherry picked from commit 6f6e1f902a5a08ae6925273d7b9f129b6094eb0c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 6 +++---
+ src/cpu/cpu_x86.h | 9 +++++++++
+ src/libvirt_private.syms | 6 ++++++
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 9653160..e5de667 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -203,7 +203,7 @@ x86DataCpuid(const virCPUx86Data *data,
+ }
+
+
+-static void
++void
+ virCPUx86DataFree(virCPUx86Data *data)
+ {
+ if (data == NULL)
+@@ -215,7 +215,7 @@ virCPUx86DataFree(virCPUx86Data *data)
+ }
+
+
+-static virCPUDataPtr
++virCPUDataPtr
+ virCPUx86MakeData(virArch arch, virCPUx86Data **data)
+ {
+ virCPUDataPtr cpuData;
+@@ -295,7 +295,7 @@ x86DataExpand(virCPUx86Data *data,
+ }
+
+
+-static int
++int
+ virCPUx86DataAddCPUID(virCPUx86Data *data,
+ const virCPUx86CPUID *cpuid)
+ {
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 77965b7..af0fa23 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -25,7 +25,16 @@
+ # define __VIR_CPU_X86_H__
+
+ # include "cpu.h"
++# include "cpu_x86_data.h"
+
+ extern struct cpuArchDriver cpuDriverX86;
+
++int virCPUx86DataAddCPUID(virCPUx86Data *data,
++ const virCPUx86CPUID *cpuid);
++
++void virCPUx86DataFree(virCPUx86Data *data);
++
++virCPUDataPtr virCPUx86MakeData(virArch arch,
++ virCPUx86Data **data);
++
+ #endif /* __VIR_CPU_X86_H__ */
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 722178b..0421c5b 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -727,6 +727,12 @@ cpuNodeData;
+ cpuUpdate;
+
+
++# cpu/cpu_x86.h
++virCPUx86DataAddCPUID;
++virCPUx86DataFree;
++virCPUx86MakeData;
++
++
+ # datatypes.h
+ virConnectClass;
+ virDomainClass;
+--
+1.8.4.2
+
--- /dev/null
+From 45c1fda7075b723a1bf292b9bbcb0b27cab9e72c Mon Sep 17 00:00:00 2001
+Message-Id: <45c1fda7075b723a1bf292b9bbcb0b27cab9e72c.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:32 +0100
+Subject: [PATCH] cpu: x86: Add internal CPUID features support and KVM feature
+ bits
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Some of the emulator features are presented in the <features> element in
+the domain XML although they are virtual CPUID feature bits when
+presented to the guest. To avoid confusing the users with these
+features, as they are not configurable via the <cpu> element, this patch
+adds an internal array where those can be stored privately instead of
+exposing them in the XML.
+
+Additionaly KVM feature bits are added as example usage of this code.
+
+(cherry picked from commit 2e8f90802ddc5405121ba1b92f47b885867a325a)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/cpu/cpu_x86_data.h | 12 ++++++++++
+ 2 files changed, 76 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 3bdb3c3..7bd8acb 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -56,6 +56,25 @@ struct x86_feature {
+ struct x86_feature *next;
+ };
+
++struct x86_kvm_feature {
++ const char *name;
++ const virCPUx86CPUID cpuid;
++};
++
++static const struct x86_kvm_feature x86_kvm_features[] =
++{
++ {VIR_CPU_x86_KVM_CLOCKSOURCE, { .function = 0x40000001, .eax = 0x00000001 }},
++ {VIR_CPU_x86_KVM_NOP_IO_DELAY, { .function = 0x40000001, .eax = 0x00000002 }},
++ {VIR_CPU_x86_KVM_MMU_OP, { .function = 0x40000001, .eax = 0x00000004 }},
++ {VIR_CPU_x86_KVM_CLOCKSOURCE2, { .function = 0x40000001, .eax = 0x00000008 }},
++ {VIR_CPU_x86_KVM_ASYNC_PF, { .function = 0x40000001, .eax = 0x00000010 }},
++ {VIR_CPU_x86_KVM_STEAL_TIME, { .function = 0x40000001, .eax = 0x00000020 }},
++ {VIR_CPU_x86_KVM_PV_EOI, { .function = 0x40000001, .eax = 0x00000040 }},
++ {VIR_CPU_x86_KVM_PV_UNHALT, { .function = 0x40000001, .eax = 0x00000080 }},
++ {VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT,
++ { .function = 0x40000001, .eax = 0x01000000 }},
++};
++
+ struct x86_model {
+ char *name;
+ const struct x86_vendor *vendor;
+@@ -1068,6 +1087,48 @@ x86MapLoadCallback(enum cpuMapElement element,
+ }
+
+
++static int
++x86MapLoadInternalFeatures(struct x86_map *map)
++{
++ size_t i;
++ struct x86_feature *feature = NULL;
++
++ for (i = 0; i < ARRAY_CARDINALITY(x86_kvm_features); i++) {
++ const char *name = x86_kvm_features[i].name;
++
++ if (x86FeatureFind(map, name)) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("CPU feature %s already defined"), name);
++ return -1;
++ }
++
++ if (!(feature = x86FeatureNew()))
++ goto error;
++
++ if (VIR_STRDUP(feature->name, name) < 0)
++ goto error;
++
++ if (virCPUx86DataAddCPUID(feature->data, &x86_kvm_features[i].cpuid))
++ goto error;
++
++ if (map->features == NULL) {
++ map->features = feature;
++ } else {
++ feature->next = map->features;
++ map->features = feature;
++ }
++
++ feature = NULL;
++ }
++
++ return 0;
++
++error:
++ x86FeatureFree(feature);
++ return -1;
++}
++
++
+ static struct x86_map *
+ virCPUx86LoadMap(void)
+ {
+@@ -1079,6 +1140,9 @@ virCPUx86LoadMap(void)
+ if (cpuMapLoad("x86", x86MapLoadCallback, map) < 0)
+ goto error;
+
++ if (x86MapLoadInternalFeatures(map) < 0)
++ goto error;
++
+ return map;
+
+ error:
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index 69066f1..88dccf6 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -36,8 +36,20 @@ struct _virCPUx86CPUID {
+ };
+
+ # define CPUX86_BASIC 0x0
++# define CPUX86_KVM 0x40000000
+ # define CPUX86_EXTENDED 0x80000000
+
++# define VIR_CPU_x86_KVM_CLOCKSOURCE "__kvm_clocksource"
++# define VIR_CPU_x86_KVM_NOP_IO_DELAY "__kvm_no_io_delay"
++# define VIR_CPU_x86_KVM_MMU_OP "__kvm_mmu_op"
++# define VIR_CPU_x86_KVM_CLOCKSOURCE2 "__kvm_clocksource2"
++# define VIR_CPU_x86_KVM_ASYNC_PF "__kvm_async_pf"
++# define VIR_CPU_x86_KVM_STEAL_TIME "__kvm_steal_time"
++# define VIR_CPU_x86_KVM_PV_EOI "__kvm_pv_eoi"
++# define VIR_CPU_x86_KVM_PV_UNHALT "__kvm_pv_unhalt"
++# define VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT "__kvm_clocksource_stable"
++
++
+ typedef struct _virCPUx86Data virCPUx86Data;
+ struct _virCPUx86Data {
+ size_t len;
+--
+1.8.4.2
+
--- /dev/null
+From 1ebdad03cee5cafeb0c7d6991d3936426b246090 Mon Sep 17 00:00:00 2001
+Message-Id: <1ebdad03cee5cafeb0c7d6991d3936426b246090.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:27 +0100
+Subject: [PATCH] cpu: x86: Clean up error messages in x86VendorLoad()
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Avoid a line exceeding 80 characters and change argument alignment in
+two error messages.
+
+(cherry picked from commit f2eca83cb66c0f930acf48fd5db6c864d5bb3ba9)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 610f028..9653160 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -542,8 +542,8 @@ x86VendorLoad(xmlXPathContextPtr ctxt,
+
+ vendor->name = virXPathString("string(@name)", ctxt);
+ if (!vendor->name) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- "%s", _("Missing CPU vendor name"));
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Missing CPU vendor name"));
+ goto ignore;
+ }
+
+@@ -556,7 +556,8 @@ x86VendorLoad(xmlXPathContextPtr ctxt,
+ string = virXPathString("string(@string)", ctxt);
+ if (!string) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("Missing vendor string for CPU vendor %s"), vendor->name);
++ _("Missing vendor string for CPU vendor %s"),
++ vendor->name);
+ goto ignore;
+ }
+ if (strlen(string) != VENDOR_STRING_LENGTH) {
+--
+1.8.4.2
+
--- /dev/null
+From a7fe351dd627d6aca3cb00c53bce66df74a98fba Mon Sep 17 00:00:00 2001
+Message-Id: <a7fe351dd627d6aca3cb00c53bce66df74a98fba.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:25 +0100
+Subject: [PATCH] cpu: x86: Fix return types of x86cpuidMatch and
+ x86cpuidMatchMasked
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+These return boolean results.
+
+(cherry picked from commit 57d27a84a39359dba1dd50741cff61c535895e08)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 93a2372..6c599f8 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -90,7 +90,7 @@ struct virCPUx86DataIterator {
+ { data, -1, false }
+
+
+-static int
++static bool
+ x86cpuidMatch(const virCPUx86CPUID *cpuid1,
+ const virCPUx86CPUID *cpuid2)
+ {
+@@ -101,7 +101,7 @@ x86cpuidMatch(const virCPUx86CPUID *cpuid1,
+ }
+
+
+-static int
++static bool
+ x86cpuidMatchMasked(const virCPUx86CPUID *cpuid,
+ const virCPUx86CPUID *mask)
+ {
+--
+1.8.4.2
+
--- /dev/null
+From 968218c6e4261b824efc41515a93fd2fe9878cbc Mon Sep 17 00:00:00 2001
+Message-Id: <968218c6e4261b824efc41515a93fd2fe9878cbc.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:29 +0100
+Subject: [PATCH] cpu: x86: Parse the CPU feature map only once
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Until now the map was loaded from the XML definition file every time a
+operation on the flags was requested. With the introduciton of one shot
+initializers we can store the definition forever (as it will never
+change) instead of parsing it over and over again.
+
+(cherry-picked from commit 629aff378f15df47f93f96b4a2ad780da8aa4785)
+
+Conflicts:
+ src/cpu/cpu_x86.c - d4952d36 was not backported and thus the new
+ flag is not yet in the code
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 65 +++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 39 insertions(+), 26 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e5de667..d4d3731 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -70,6 +70,10 @@ struct x86_map {
+ struct x86_model *models;
+ };
+
++static struct x86_map* virCPUx86Map = NULL;
++int virCPUx86MapOnceInit(void);
++VIR_ONCE_GLOBAL_INIT(virCPUx86Map);
++
+
+ enum compare_result {
+ SUBSET,
+@@ -1119,7 +1123,7 @@ x86MapLoadCallback(enum cpuMapElement element,
+
+
+ static struct x86_map *
+-x86LoadMap(void)
++virCPUx86LoadMap(void)
+ {
+ struct x86_map *map;
+
+@@ -1137,6 +1141,26 @@ error:
+ }
+
+
++int
++virCPUx86MapOnceInit(void)
++{
++ if (!(virCPUx86Map = virCPUx86LoadMap()))
++ return -1;
++
++ return 0;
++}
++
++
++static const struct x86_map *
++virCPUx86GetMap(void)
++{
++ if (virCPUx86MapInitialize() < 0)
++ return NULL;
++
++ return virCPUx86Map;
++}
++
++
+ static char *
+ x86CPUDataFormat(const virCPUData *data)
+ {
+@@ -1247,7 +1271,7 @@ x86Compute(virCPUDefPtr host,
+ virCPUDataPtr *guest,
+ char **message)
+ {
+- struct x86_map *map = NULL;
++ const struct x86_map *map = NULL;
+ struct x86_model *host_model = NULL;
+ struct x86_model *cpu_force = NULL;
+ struct x86_model *cpu_require = NULL;
+@@ -1300,7 +1324,7 @@ x86Compute(virCPUDefPtr host,
+ return VIR_CPU_COMPARE_INCOMPATIBLE;
+ }
+
+- if (!(map = x86LoadMap()) ||
++ if (!(map = virCPUx86GetMap()) ||
+ !(host_model = x86ModelFromCPU(host, map, VIR_CPU_FEATURE_REQUIRE)) ||
+ !(cpu_force = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORCE)) ||
+ !(cpu_require = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_REQUIRE)) ||
+@@ -1376,7 +1400,6 @@ x86Compute(virCPUDefPtr host,
+ }
+
+ cleanup:
+- x86MapFree(map);
+ x86ModelFree(host_model);
+ x86ModelFree(diff);
+ x86ModelFree(cpu_force);
+@@ -1421,13 +1444,13 @@ x86Decode(virCPUDefPtr cpu,
+ const char *preferred)
+ {
+ int ret = -1;
+- struct x86_map *map;
++ const struct x86_map *map;
+ const struct x86_model *candidate;
+ virCPUDefPtr cpuCandidate;
+ virCPUDefPtr cpuModel = NULL;
+ size_t i;
+
+- if (data == NULL || (map = x86LoadMap()) == NULL)
++ if (!data || !(map = virCPUx86GetMap()))
+ return -1;
+
+ candidate = map->models;
+@@ -1508,7 +1531,6 @@ x86Decode(virCPUDefPtr cpu,
+ ret = 0;
+
+ out:
+- x86MapFree(map);
+ virCPUDefFree(cpuModel);
+
+ return ret;
+@@ -1554,14 +1576,13 @@ x86Encode(virArch arch,
+ virCPUDataPtr *forbidden,
+ virCPUDataPtr *vendor)
+ {
+- struct x86_map *map = NULL;
++ const struct x86_map *map = NULL;
+ virCPUx86Data *data_forced = NULL;
+ virCPUx86Data *data_required = NULL;
+ virCPUx86Data *data_optional = NULL;
+ virCPUx86Data *data_disabled = NULL;
+ virCPUx86Data *data_forbidden = NULL;
+ virCPUx86Data *data_vendor = NULL;
+- int ret = -1;
+
+ if (forced)
+ *forced = NULL;
+@@ -1576,7 +1597,7 @@ x86Encode(virArch arch,
+ if (vendor)
+ *vendor = NULL;
+
+- if ((map = x86LoadMap()) == NULL)
++ if ((map = virCPUx86GetMap()) == NULL)
+ goto error;
+
+ if (forced) {
+@@ -1644,12 +1665,7 @@ x86Encode(virArch arch,
+ !(*vendor = virCPUx86MakeData(arch, &data_vendor)))
+ goto error;
+
+- ret = 0;
+-
+-cleanup:
+- x86MapFree(map);
+-
+- return ret;
++ return 0;
+
+ error:
+ virCPUx86DataFree(data_forced);
+@@ -1670,7 +1686,7 @@ error:
+ x86FreeCPUData(*forbidden);
+ if (vendor)
+ x86FreeCPUData(*vendor);
+- goto cleanup;
++ return -1;
+ }
+
+
+@@ -1769,7 +1785,7 @@ x86Baseline(virCPUDefPtr *cpus,
+ const char **models,
+ unsigned int nmodels)
+ {
+- struct x86_map *map = NULL;
++ const struct x86_map *map = NULL;
+ struct x86_model *base_model = NULL;
+ virCPUDefPtr cpu = NULL;
+ size_t i;
+@@ -1777,7 +1793,7 @@ x86Baseline(virCPUDefPtr *cpus,
+ struct x86_model *model = NULL;
+ bool outputVendor = true;
+
+- if (!(map = x86LoadMap()))
++ if (!(map = virCPUx86GetMap()))
+ goto error;
+
+ if (!(base_model = x86ModelFromCPU(cpus[0], map, VIR_CPU_FEATURE_REQUIRE)))
+@@ -1858,7 +1874,6 @@ x86Baseline(virCPUDefPtr *cpus,
+
+ cleanup:
+ x86ModelFree(base_model);
+- x86MapFree(map);
+
+ return cpu;
+
+@@ -1876,10 +1891,10 @@ x86UpdateCustom(virCPUDefPtr guest,
+ {
+ int ret = -1;
+ size_t i;
+- struct x86_map *map;
++ const struct x86_map *map;
+ struct x86_model *host_model = NULL;
+
+- if (!(map = x86LoadMap()) ||
++ if (!(map = virCPUx86GetMap()) ||
+ !(host_model = x86ModelFromCPU(host, map, VIR_CPU_FEATURE_REQUIRE)))
+ goto cleanup;
+
+@@ -1911,7 +1926,6 @@ x86UpdateCustom(virCPUDefPtr guest,
+ ret = 0;
+
+ cleanup:
+- x86MapFree(map);
+ x86ModelFree(host_model);
+ return ret;
+ }
+@@ -1979,11 +1993,11 @@ x86Update(virCPUDefPtr guest,
+ static int x86HasFeature(const virCPUDataPtr data,
+ const char *name)
+ {
+- struct x86_map *map;
++ const struct x86_map *map;
+ struct x86_feature *feature;
+ int ret = -1;
+
+- if (!(map = x86LoadMap()))
++ if (!(map = virCPUx86GetMap()))
+ return -1;
+
+ if (!(feature = x86FeatureFind(map, name)))
+@@ -1992,7 +2006,6 @@ static int x86HasFeature(const virCPUDataPtr data,
+ ret = x86DataIsSubset(data->data.x86, feature->data) ? 1 : 0;
+
+ cleanup:
+- x86MapFree(map);
+ return ret;
+ }
+
+--
+1.8.4.2
+
--- /dev/null
+From 308b4f4f06c3b137f3a133499c6e0fd1029aecd0 Mon Sep 17 00:00:00 2001
+Message-Id: <308b4f4f06c3b137f3a133499c6e0fd1029aecd0.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:24 +0100
+Subject: [PATCH] cpu: x86: Rename data_iterator and DATA_ITERATOR_INIT
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Use virCPUx86DataIterator and virCPUx86DataIteratorInit.
+
+(cherry picked from commit 1bda29d16d3528fd257fce2fec325202c32bc9ed)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 672d6e0..93a2372 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -79,14 +79,14 @@ enum compare_result {
+ };
+
+
+-struct data_iterator {
++struct virCPUx86DataIterator {
+ virCPUx86Data *data;
+ int pos;
+ bool extended;
+ };
+
+
+-#define DATA_ITERATOR_INIT(data) \
++#define virCPUx86DataIteratorInit(data) \
+ { data, -1, false }
+
+
+@@ -147,7 +147,7 @@ x86cpuidAndBits(virCPUx86CPUID *cpuid,
+
+ /* skips all zero CPUID leafs */
+ static virCPUx86CPUID *
+-x86DataCpuidNext(struct data_iterator *iterator)
++x86DataCpuidNext(struct virCPUx86DataIterator *iterator)
+ {
+ virCPUx86CPUID *ret;
+ virCPUx86Data *data = iterator->data;
+@@ -373,7 +373,7 @@ static void
+ x86DataIntersect(virCPUx86Data *data1,
+ const virCPUx86Data *data2)
+ {
+- struct data_iterator iter = DATA_ITERATOR_INIT(data1);
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
+ virCPUx86CPUID *cpuid1;
+ virCPUx86CPUID *cpuid2;
+
+@@ -390,7 +390,7 @@ x86DataIntersect(virCPUx86Data *data1,
+ static bool
+ x86DataIsEmpty(virCPUx86Data *data)
+ {
+- struct data_iterator iter = DATA_ITERATOR_INIT(data);
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data);
+
+ return x86DataCpuidNext(&iter) == NULL;
+ }
+@@ -401,7 +401,7 @@ x86DataIsSubset(const virCPUx86Data *data,
+ const virCPUx86Data *subset)
+ {
+
+- struct data_iterator iter = DATA_ITERATOR_INIT((virCPUx86Data *)subset);
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset);
+ const virCPUx86CPUID *cpuid;
+ const virCPUx86CPUID *cpuidSubset;
+
+@@ -912,8 +912,8 @@ x86ModelCompare(const struct x86_model *model1,
+ const struct x86_model *model2)
+ {
+ enum compare_result result = EQUAL;
+- struct data_iterator iter1 = DATA_ITERATOR_INIT(model1->data);
+- struct data_iterator iter2 = DATA_ITERATOR_INIT(model2->data);
++ struct virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(model1->data);
++ struct virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(model2->data);
+ virCPUx86CPUID *cpuid1;
+ virCPUx86CPUID *cpuid2;
+
+@@ -1139,7 +1139,7 @@ error:
+ static char *
+ x86CPUDataFormat(const virCPUData *data)
+ {
+- struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data->data.x86);
+ virCPUx86CPUID *cpuid;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+--
+1.8.4.2
+
--- /dev/null
+From 678e17ff7fc2c4ef74a832cbfe25ebfd22f7fde4 Mon Sep 17 00:00:00 2001
+Message-Id: <678e17ff7fc2c4ef74a832cbfe25ebfd22f7fde4.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:19 +0100
+Subject: [PATCH] cpu: x86: Rename struct cpuX86Data as virCPUx86Data
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit 0c63d120042d444f178cfdd521aa2a41d49ad570)
+
+Conflicts:
+ src/cpu/cpu_x86.c - d694ae0c55b4cd1349f6 not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu.h | 2 +-
+ src/cpu/cpu_x86.c | 82 +++++++++++++++++++++++++-------------------------
+ src/cpu/cpu_x86_data.h | 3 +-
+ 3 files changed, 44 insertions(+), 43 deletions(-)
+
+diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
+index 7417f92..ad6ccfb 100644
+--- a/src/cpu/cpu.h
++++ b/src/cpu/cpu.h
+@@ -37,7 +37,7 @@ typedef virCPUData *virCPUDataPtr;
+ struct _virCPUData {
+ virArch arch;
+ union {
+- struct cpuX86Data *x86;
++ virCPUx86Data *x86;
+ struct cpuPPCData ppc;
+ /* generic driver needs no data */
+ } data;
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e8e996e..94ba7a4 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -51,7 +51,7 @@ struct x86_vendor {
+
+ struct x86_feature {
+ char *name;
+- struct cpuX86Data *data;
++ virCPUx86Data *data;
+
+ struct x86_feature *next;
+ };
+@@ -59,7 +59,7 @@ struct x86_feature {
+ struct x86_model {
+ char *name;
+ const struct x86_vendor *vendor;
+- struct cpuX86Data *data;
++ virCPUx86Data *data;
+
+ struct x86_model *next;
+ };
+@@ -80,7 +80,7 @@ enum compare_result {
+
+
+ struct data_iterator {
+- struct cpuX86Data *data;
++ virCPUx86Data *data;
+ int pos;
+ bool extended;
+ };
+@@ -150,7 +150,7 @@ static virCPUx86CPUID *
+ x86DataCpuidNext(struct data_iterator *iterator)
+ {
+ virCPUx86CPUID *ret;
+- struct cpuX86Data *data = iterator->data;
++ virCPUx86Data *data = iterator->data;
+
+ if (!data)
+ return NULL;
+@@ -178,7 +178,7 @@ x86DataCpuidNext(struct data_iterator *iterator)
+
+
+ static virCPUx86CPUID *
+-x86DataCpuid(const struct cpuX86Data *data,
++x86DataCpuid(const virCPUx86Data *data,
+ uint32_t function)
+ {
+ virCPUx86CPUID *cpuids;
+@@ -204,7 +204,7 @@ x86DataCpuid(const struct cpuX86Data *data,
+
+
+ static void
+-x86DataFree(struct cpuX86Data *data)
++x86DataFree(virCPUx86Data *data)
+ {
+ if (data == NULL)
+ return;
+@@ -216,7 +216,7 @@ x86DataFree(struct cpuX86Data *data)
+
+
+ static virCPUDataPtr
+-x86MakeCPUData(virArch arch, struct cpuX86Data **data)
++x86MakeCPUData(virArch arch, virCPUx86Data **data)
+ {
+ virCPUDataPtr cpuData;
+
+@@ -241,10 +241,10 @@ x86FreeCPUData(virCPUDataPtr data)
+ }
+
+
+-static struct cpuX86Data *
+-x86DataCopy(const struct cpuX86Data *data)
++static virCPUx86Data *
++x86DataCopy(const virCPUx86Data *data)
+ {
+- struct cpuX86Data *copy = NULL;
++ virCPUx86Data *copy = NULL;
+ size_t i;
+
+ if (VIR_ALLOC(copy) < 0
+@@ -267,7 +267,7 @@ x86DataCopy(const struct cpuX86Data *data)
+
+
+ static int
+-x86DataExpand(struct cpuX86Data *data,
++x86DataExpand(virCPUx86Data *data,
+ int basic_by,
+ int extended_by)
+ {
+@@ -296,7 +296,7 @@ x86DataExpand(struct cpuX86Data *data,
+
+
+ static int
+-x86DataAddCpuid(struct cpuX86Data *data,
++x86DataAddCpuid(virCPUx86Data *data,
+ const virCPUx86CPUID *cpuid)
+ {
+ unsigned int basic_by = 0;
+@@ -324,8 +324,8 @@ x86DataAddCpuid(struct cpuX86Data *data,
+
+
+ static int
+-x86DataAdd(struct cpuX86Data *data1,
+- const struct cpuX86Data *data2)
++x86DataAdd(virCPUx86Data *data1,
++ const virCPUx86Data *data2)
+ {
+ size_t i;
+
+@@ -349,8 +349,8 @@ x86DataAdd(struct cpuX86Data *data1,
+
+
+ static void
+-x86DataSubtract(struct cpuX86Data *data1,
+- const struct cpuX86Data *data2)
++x86DataSubtract(virCPUx86Data *data1,
++ const virCPUx86Data *data2)
+ {
+ size_t i;
+ unsigned int len;
+@@ -370,8 +370,8 @@ x86DataSubtract(struct cpuX86Data *data1,
+
+
+ static void
+-x86DataIntersect(struct cpuX86Data *data1,
+- const struct cpuX86Data *data2)
++x86DataIntersect(virCPUx86Data *data1,
++ const virCPUx86Data *data2)
+ {
+ struct data_iterator iter = DATA_ITERATOR_INIT(data1);
+ virCPUx86CPUID *cpuid1;
+@@ -388,7 +388,7 @@ x86DataIntersect(struct cpuX86Data *data1,
+
+
+ static bool
+-x86DataIsEmpty(struct cpuX86Data *data)
++x86DataIsEmpty(virCPUx86Data *data)
+ {
+ struct data_iterator iter = DATA_ITERATOR_INIT(data);
+
+@@ -397,11 +397,11 @@ x86DataIsEmpty(struct cpuX86Data *data)
+
+
+ static bool
+-x86DataIsSubset(const struct cpuX86Data *data,
+- const struct cpuX86Data *subset)
++x86DataIsSubset(const virCPUx86Data *data,
++ const virCPUx86Data *subset)
+ {
+
+- struct data_iterator iter = DATA_ITERATOR_INIT((struct cpuX86Data *)subset);
++ struct data_iterator iter = DATA_ITERATOR_INIT((virCPUx86Data *)subset);
+ const virCPUx86CPUID *cpuid;
+ const virCPUx86CPUID *cpuidSubset;
+
+@@ -419,7 +419,7 @@ x86DataIsSubset(const struct cpuX86Data *data,
+ static int
+ x86DataToCPUFeatures(virCPUDefPtr cpu,
+ int policy,
+- struct cpuX86Data *data,
++ virCPUx86Data *data,
+ const struct x86_map *map)
+ {
+ const struct x86_feature *feature = map->features;
+@@ -439,7 +439,7 @@ x86DataToCPUFeatures(virCPUDefPtr cpu,
+
+ /* also removes bits corresponding to vendor string from data */
+ static const struct x86_vendor *
+-x86DataToVendor(struct cpuX86Data *data,
++x86DataToVendor(virCPUx86Data *data,
+ const struct x86_map *map)
+ {
+ const struct x86_vendor *vendor = map->vendors;
+@@ -459,13 +459,13 @@ x86DataToVendor(struct cpuX86Data *data,
+
+
+ static virCPUDefPtr
+-x86DataToCPU(const struct cpuX86Data *data,
++x86DataToCPU(const virCPUx86Data *data,
+ const struct x86_model *model,
+ const struct x86_map *map)
+ {
+ virCPUDefPtr cpu;
+- struct cpuX86Data *copy = NULL;
+- struct cpuX86Data *modelData = NULL;
++ virCPUx86Data *copy = NULL;
++ virCPUx86Data *modelData = NULL;
+ const struct x86_vendor *vendor;
+
+ if (VIR_ALLOC(cpu) < 0 ||
+@@ -640,7 +640,7 @@ x86FeatureFind(const struct x86_map *map,
+ static char *
+ x86FeatureNames(const struct x86_map *map,
+ const char *separator,
+- struct cpuX86Data *data)
++ virCPUx86Data *data)
+ {
+ virBuffer ret = VIR_BUFFER_INITIALIZER;
+ bool first = true;
+@@ -1171,7 +1171,7 @@ x86CPUDataParse(const char *xmlStr)
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr *nodes = NULL;
+ virCPUDataPtr cpuData = NULL;
+- struct cpuX86Data *data = NULL;
++ virCPUx86Data *data = NULL;
+ virCPUx86CPUID cpuid;
+ size_t i;
+ int n;
+@@ -1218,7 +1218,7 @@ cleanup:
+ /* A helper macro to exit the cpu computation function without writing
+ * redundant code:
+ * MSG: error message
+- * CPU_DEF: a struct cpuX86Data pointer with flags that are conflicting
++ * CPU_DEF: a virCPUx86Data pointer with flags that are conflicting
+ * RET: return code to set
+ *
+ * This macro generates the error string outputs it into logs.
+@@ -1352,7 +1352,7 @@ x86Compute(virCPUDefPtr host,
+ }
+
+ if (guest != NULL) {
+- struct cpuX86Data *guestData;
++ virCPUx86Data *guestData;
+
+ if ((guest_model = x86ModelCopy(host_model)) == NULL)
+ goto error;
+@@ -1413,7 +1413,7 @@ x86GuestData(virCPUDefPtr host,
+
+ static int
+ x86Decode(virCPUDefPtr cpu,
+- const struct cpuX86Data *data,
++ const virCPUx86Data *data,
+ const char **models,
+ unsigned int nmodels,
+ const char *preferred)
+@@ -1523,13 +1523,13 @@ x86DecodeCPUData(virCPUDefPtr cpu,
+ }
+
+
+-static struct cpuX86Data *
++static virCPUx86Data *
+ x86EncodePolicy(const virCPUDefPtr cpu,
+ const struct x86_map *map,
+ enum virCPUFeaturePolicy policy)
+ {
+ struct x86_model *model;
+- struct cpuX86Data *data = NULL;
++ virCPUx86Data *data = NULL;
+
+ if (!(model = x86ModelFromCPU(cpu, map, policy)))
+ return NULL;
+@@ -1553,12 +1553,12 @@ x86Encode(virArch arch,
+ virCPUDataPtr *vendor)
+ {
+ struct x86_map *map = NULL;
+- struct cpuX86Data *data_forced = NULL;
+- struct cpuX86Data *data_required = NULL;
+- struct cpuX86Data *data_optional = NULL;
+- struct cpuX86Data *data_disabled = NULL;
+- struct cpuX86Data *data_forbidden = NULL;
+- struct cpuX86Data *data_vendor = NULL;
++ virCPUx86Data *data_forced = NULL;
++ virCPUx86Data *data_required = NULL;
++ virCPUx86Data *data_optional = NULL;
++ virCPUx86Data *data_disabled = NULL;
++ virCPUx86Data *data_forbidden = NULL;
++ virCPUx86Data *data_vendor = NULL;
+ int ret = -1;
+
+ if (forced)
+@@ -1734,7 +1734,7 @@ static virCPUDataPtr
+ x86NodeData(void)
+ {
+ virCPUDataPtr cpuData = NULL;
+- struct cpuX86Data *data;
++ virCPUx86Data *data;
+ int ret;
+
+ if (VIR_ALLOC(data) < 0)
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index acb7c32..5910ea9 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -38,7 +38,8 @@ struct _virCPUx86CPUID {
+ # define CPUX86_BASIC 0x0
+ # define CPUX86_EXTENDED 0x80000000
+
+-struct cpuX86Data {
++typedef struct _virCPUx86Data virCPUx86Data;
++struct _virCPUx86Data {
+ size_t basic_len;
+ virCPUx86CPUID *basic;
+ size_t extended_len;
+--
+1.8.4.2
+
--- /dev/null
+From bc040f565387ba084c63c12610e44043a1840f01 Mon Sep 17 00:00:00 2001
+Message-Id: <bc040f565387ba084c63c12610e44043a1840f01.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:18 +0100
+Subject: [PATCH] cpu: x86: Rename struct cpuX86cpuid as virCPUx86CPUID
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit 01fabe2eda94b3bc8f039e6a6cbf0aa29f03700b)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 64 +++++++++++++++++++++++++-------------------------
+ src/cpu/cpu_x86_data.h | 7 +++---
+ 2 files changed, 36 insertions(+), 35 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 0bc031b..e8e996e 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -38,13 +38,13 @@
+
+ #define VENDOR_STRING_LENGTH 12
+
+-static const struct cpuX86cpuid cpuidNull = { 0, 0, 0, 0, 0 };
++static const virCPUx86CPUID cpuidNull = { 0, 0, 0, 0, 0 };
+
+ static const virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 };
+
+ struct x86_vendor {
+ char *name;
+- struct cpuX86cpuid cpuid;
++ virCPUx86CPUID cpuid;
+
+ struct x86_vendor *next;
+ };
+@@ -91,8 +91,8 @@ struct data_iterator {
+
+
+ static int
+-x86cpuidMatch(const struct cpuX86cpuid *cpuid1,
+- const struct cpuX86cpuid *cpuid2)
++x86cpuidMatch(const virCPUx86CPUID *cpuid1,
++ const virCPUx86CPUID *cpuid2)
+ {
+ return (cpuid1->eax == cpuid2->eax &&
+ cpuid1->ebx == cpuid2->ebx &&
+@@ -102,8 +102,8 @@ x86cpuidMatch(const struct cpuX86cpuid *cpuid1,
+
+
+ static int
+-x86cpuidMatchMasked(const struct cpuX86cpuid *cpuid,
+- const struct cpuX86cpuid *mask)
++x86cpuidMatchMasked(const virCPUx86CPUID *cpuid,
++ const virCPUx86CPUID *mask)
+ {
+ return ((cpuid->eax & mask->eax) == mask->eax &&
+ (cpuid->ebx & mask->ebx) == mask->ebx &&
+@@ -113,8 +113,8 @@ x86cpuidMatchMasked(const struct cpuX86cpuid *cpuid,
+
+
+ static void
+-x86cpuidSetBits(struct cpuX86cpuid *cpuid,
+- const struct cpuX86cpuid *mask)
++x86cpuidSetBits(virCPUx86CPUID *cpuid,
++ const virCPUx86CPUID *mask)
+ {
+ cpuid->eax |= mask->eax;
+ cpuid->ebx |= mask->ebx;
+@@ -124,8 +124,8 @@ x86cpuidSetBits(struct cpuX86cpuid *cpuid,
+
+
+ static void
+-x86cpuidClearBits(struct cpuX86cpuid *cpuid,
+- const struct cpuX86cpuid *mask)
++x86cpuidClearBits(virCPUx86CPUID *cpuid,
++ const virCPUx86CPUID *mask)
+ {
+ cpuid->eax &= ~mask->eax;
+ cpuid->ebx &= ~mask->ebx;
+@@ -135,8 +135,8 @@ x86cpuidClearBits(struct cpuX86cpuid *cpuid,
+
+
+ static void
+-x86cpuidAndBits(struct cpuX86cpuid *cpuid,
+- const struct cpuX86cpuid *mask)
++x86cpuidAndBits(virCPUx86CPUID *cpuid,
++ const virCPUx86CPUID *mask)
+ {
+ cpuid->eax &= mask->eax;
+ cpuid->ebx &= mask->ebx;
+@@ -146,10 +146,10 @@ x86cpuidAndBits(struct cpuX86cpuid *cpuid,
+
+
+ /* skips all zero CPUID leafs */
+-static struct cpuX86cpuid *
++static virCPUx86CPUID *
+ x86DataCpuidNext(struct data_iterator *iterator)
+ {
+- struct cpuX86cpuid *ret;
++ virCPUx86CPUID *ret;
+ struct cpuX86Data *data = iterator->data;
+
+ if (!data)
+@@ -177,11 +177,11 @@ x86DataCpuidNext(struct data_iterator *iterator)
+ }
+
+
+-static struct cpuX86cpuid *
++static virCPUx86CPUID *
+ x86DataCpuid(const struct cpuX86Data *data,
+ uint32_t function)
+ {
+- struct cpuX86cpuid *cpuids;
++ virCPUx86CPUID *cpuids;
+ int len;
+ size_t i;
+
+@@ -297,11 +297,11 @@ x86DataExpand(struct cpuX86Data *data,
+
+ static int
+ x86DataAddCpuid(struct cpuX86Data *data,
+- const struct cpuX86cpuid *cpuid)
++ const virCPUx86CPUID *cpuid)
+ {
+ unsigned int basic_by = 0;
+ unsigned int extended_by = 0;
+- struct cpuX86cpuid **cpuids;
++ virCPUx86CPUID **cpuids;
+ unsigned int pos;
+
+ if (cpuid->function < CPUX86_EXTENDED) {
+@@ -374,8 +374,8 @@ x86DataIntersect(struct cpuX86Data *data1,
+ const struct cpuX86Data *data2)
+ {
+ struct data_iterator iter = DATA_ITERATOR_INIT(data1);
+- struct cpuX86cpuid *cpuid1;
+- struct cpuX86cpuid *cpuid2;
++ virCPUx86CPUID *cpuid1;
++ virCPUx86CPUID *cpuid2;
+
+ while ((cpuid1 = x86DataCpuidNext(&iter))) {
+ cpuid2 = x86DataCpuid(data2, cpuid1->function);
+@@ -402,8 +402,8 @@ x86DataIsSubset(const struct cpuX86Data *data,
+ {
+
+ struct data_iterator iter = DATA_ITERATOR_INIT((struct cpuX86Data *)subset);
+- const struct cpuX86cpuid *cpuid;
+- const struct cpuX86cpuid *cpuidSubset;
++ const virCPUx86CPUID *cpuid;
++ const virCPUx86CPUID *cpuidSubset;
+
+ while ((cpuidSubset = x86DataCpuidNext(&iter))) {
+ if (!(cpuid = x86DataCpuid(data, cpuidSubset->function)) ||
+@@ -443,7 +443,7 @@ x86DataToVendor(struct cpuX86Data *data,
+ const struct x86_map *map)
+ {
+ const struct x86_vendor *vendor = map->vendors;
+- struct cpuX86cpuid *cpuid;
++ virCPUx86CPUID *cpuid;
+
+ while (vendor) {
+ if ((cpuid = x86DataCpuid(data, vendor->cpuid.function)) &&
+@@ -667,7 +667,7 @@ x86FeatureNames(const struct x86_map *map,
+
+ static int
+ x86ParseCPUID(xmlXPathContextPtr ctxt,
+- struct cpuX86cpuid *cpuid)
++ virCPUx86CPUID *cpuid)
+ {
+ unsigned long fun, eax, ebx, ecx, edx;
+ int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
+@@ -701,7 +701,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
+ xmlNodePtr *nodes = NULL;
+ xmlNodePtr ctxt_node = ctxt->node;
+ struct x86_feature *feature;
+- struct cpuX86cpuid cpuid;
++ virCPUx86CPUID cpuid;
+ int ret = 0;
+ size_t i;
+ int n;
+@@ -914,8 +914,8 @@ x86ModelCompare(const struct x86_model *model1,
+ enum compare_result result = EQUAL;
+ struct data_iterator iter1 = DATA_ITERATOR_INIT(model1->data);
+ struct data_iterator iter2 = DATA_ITERATOR_INIT(model2->data);
+- struct cpuX86cpuid *cpuid1;
+- struct cpuX86cpuid *cpuid2;
++ virCPUx86CPUID *cpuid1;
++ virCPUx86CPUID *cpuid2;
+
+ while ((cpuid1 = x86DataCpuidNext(&iter1))) {
+ enum compare_result match = SUPERSET;
+@@ -1140,7 +1140,7 @@ static char *
+ x86CPUDataFormat(const virCPUData *data)
+ {
+ struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
+- struct cpuX86cpuid *cpuid;
++ virCPUx86CPUID *cpuid;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+@@ -1172,7 +1172,7 @@ x86CPUDataParse(const char *xmlStr)
+ xmlNodePtr *nodes = NULL;
+ virCPUDataPtr cpuData = NULL;
+ struct cpuX86Data *data = NULL;
+- struct cpuX86cpuid cpuid;
++ virCPUx86CPUID cpuid;
+ size_t i;
+ int n;
+
+@@ -1674,7 +1674,7 @@ error:
+
+ #if HAVE_CPUID
+ static inline void
+-cpuidCall(struct cpuX86cpuid *cpuid)
++cpuidCall(virCPUx86CPUID *cpuid)
+ {
+ # if __x86_64__
+ asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */
+@@ -1708,11 +1708,11 @@ cpuidCall(struct cpuX86cpuid *cpuid)
+
+
+ static int
+-cpuidSet(uint32_t base, struct cpuX86cpuid **set)
++cpuidSet(uint32_t base, virCPUx86CPUID **set)
+ {
+ uint32_t max;
+ uint32_t i;
+- struct cpuX86cpuid cpuid = { base, 0, 0, 0, 0 };
++ virCPUx86CPUID cpuid = { base, 0, 0, 0, 0 };
+
+ cpuidCall(&cpuid);
+ max = cpuid.eax - base;
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index dc972a6..acb7c32 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -26,7 +26,8 @@
+
+ # include <stdint.h>
+
+-struct cpuX86cpuid {
++typedef struct _virCPUx86CPUID virCPUx86CPUID;
++struct _virCPUx86CPUID {
+ uint32_t function;
+ uint32_t eax;
+ uint32_t ebx;
+@@ -39,9 +40,9 @@ struct cpuX86cpuid {
+
+ struct cpuX86Data {
+ size_t basic_len;
+- struct cpuX86cpuid *basic;
++ virCPUx86CPUID *basic;
+ size_t extended_len;
+- struct cpuX86cpuid *extended;
++ virCPUx86CPUID *extended;
+ };
+
+ #endif /* __VIR_CPU_X86_DATA_H__ */
+--
+1.8.4.2
+
--- /dev/null
+From 17af84e23715e70e28068d57ad3313601278156f Mon Sep 17 00:00:00 2001
+Message-Id: <17af84e23715e70e28068d57ad3313601278156f.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:23 +0100
+Subject: [PATCH] cpu: x86: Rename x86DataAddCpuid as virCPUx86DataAddCPUID
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit 955be92773297a6a2f9f0d223481120ff17f29fb)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index a857559..672d6e0 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -296,8 +296,8 @@ x86DataExpand(virCPUx86Data *data,
+
+
+ static int
+-x86DataAddCpuid(virCPUx86Data *data,
+- const virCPUx86CPUID *cpuid)
++virCPUx86DataAddCPUID(virCPUx86Data *data,
++ const virCPUx86CPUID *cpuid)
+ {
+ unsigned int basic_by = 0;
+ unsigned int extended_by = 0;
+@@ -734,7 +734,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
+ i, feature->name);
+ goto ignore;
+ }
+- if (x86DataAddCpuid(feature->data, &cpuid))
++ if (virCPUx86DataAddCPUID(feature->data, &cpuid))
+ goto error;
+ }
+
+@@ -1200,7 +1200,7 @@ x86CPUDataParse(const char *xmlStr)
+ _("failed to parse cpuid[%zu]"), i);
+ goto cleanup;
+ }
+- if (x86DataAddCpuid(data, &cpuid) < 0)
++ if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
+ goto cleanup;
+ }
+
+@@ -1618,7 +1618,7 @@ x86Encode(virArch arch,
+
+ if (v &&
+ (VIR_ALLOC(data_vendor) < 0 ||
+- x86DataAddCpuid(data_vendor, &v->cpuid) < 0)) {
++ virCPUx86DataAddCPUID(data_vendor, &v->cpuid) < 0)) {
+ goto error;
+ }
+ }
+@@ -1843,7 +1843,7 @@ x86Baseline(virCPUDefPtr *cpus,
+ goto error;
+ }
+
+- if (vendor && x86DataAddCpuid(base_model->data, &vendor->cpuid) < 0)
++ if (vendor && virCPUx86DataAddCPUID(base_model->data, &vendor->cpuid) < 0)
+ goto error;
+
+ if (x86Decode(cpu, base_model->data, models, nmodels, NULL) < 0)
+--
+1.8.4.2
+
--- /dev/null
+From db9bc36fa1fe8d999514304a67992f78a298dcd7 Mon Sep 17 00:00:00 2001
+Message-Id: <db9bc36fa1fe8d999514304a67992f78a298dcd7.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:20 +0100
+Subject: [PATCH] cpu: x86: Rename x86DataFree() as virCPUx86DataFree()
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit a3e224e2d9945832473d8993d2c7c3fbded7fd0c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 94ba7a4..083cfee 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -204,7 +204,7 @@ x86DataCpuid(const virCPUx86Data *data,
+
+
+ static void
+-x86DataFree(virCPUx86Data *data)
++virCPUx86DataFree(virCPUx86Data *data)
+ {
+ if (data == NULL)
+ return;
+@@ -236,7 +236,7 @@ x86FreeCPUData(virCPUDataPtr data)
+ if (!data)
+ return;
+
+- x86DataFree(data->data.x86);
++ virCPUx86DataFree(data->data.x86);
+ VIR_FREE(data);
+ }
+
+@@ -250,7 +250,7 @@ x86DataCopy(const virCPUx86Data *data)
+ if (VIR_ALLOC(copy) < 0
+ || VIR_ALLOC_N(copy->basic, data->basic_len) < 0
+ || VIR_ALLOC_N(copy->extended, data->extended_len) < 0) {
+- x86DataFree(copy);
++ virCPUx86DataFree(copy);
+ return NULL;
+ }
+
+@@ -489,8 +489,8 @@ x86DataToCPU(const virCPUx86Data *data,
+ goto error;
+
+ cleanup:
+- x86DataFree(modelData);
+- x86DataFree(copy);
++ virCPUx86DataFree(modelData);
++ virCPUx86DataFree(copy);
+ return cpu;
+
+ error:
+@@ -614,7 +614,7 @@ x86FeatureFree(struct x86_feature *feature)
+ return;
+
+ VIR_FREE(feature->name);
+- x86DataFree(feature->data);
++ virCPUx86DataFree(feature->data);
+ VIR_FREE(feature);
+ }
+
+@@ -784,7 +784,7 @@ x86ModelFree(struct x86_model *model)
+ return;
+
+ VIR_FREE(model->name);
+- x86DataFree(model->data);
++ virCPUx86DataFree(model->data);
+ VIR_FREE(model);
+ }
+
+@@ -997,7 +997,7 @@ x86ModelLoad(xmlXPathContextPtr ctxt,
+ VIR_FREE(name);
+
+ model->vendor = ancestor->vendor;
+- x86DataFree(model->data);
++ virCPUx86DataFree(model->data);
+ if (!(model->data = x86DataCopy(ancestor->data)))
+ goto error;
+ }
+@@ -1210,7 +1210,7 @@ cleanup:
+ VIR_FREE(nodes);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml);
+- x86DataFree(data);
++ virCPUx86DataFree(data);
+ return cpuData;
+ }
+
+@@ -1368,7 +1368,7 @@ x86Compute(virCPUDefPtr host,
+
+ if (!(guestData = x86DataCopy(guest_model->data)) ||
+ !(*guest = x86MakeCPUData(arch, &guestData))) {
+- x86DataFree(guestData);
++ virCPUx86DataFree(guestData);
+ goto error;
+ }
+ }
+@@ -1650,12 +1650,12 @@ cleanup:
+ return ret;
+
+ error:
+- x86DataFree(data_forced);
+- x86DataFree(data_required);
+- x86DataFree(data_optional);
+- x86DataFree(data_disabled);
+- x86DataFree(data_forbidden);
+- x86DataFree(data_vendor);
++ virCPUx86DataFree(data_forced);
++ virCPUx86DataFree(data_required);
++ virCPUx86DataFree(data_optional);
++ virCPUx86DataFree(data_disabled);
++ virCPUx86DataFree(data_forbidden);
++ virCPUx86DataFree(data_vendor);
+ if (forced)
+ x86FreeCPUData(*forced);
+ if (required)
+@@ -1754,7 +1754,7 @@ x86NodeData(void)
+ return cpuData;
+
+ error:
+- x86DataFree(data);
++ virCPUx86DataFree(data);
+
+ return NULL;
+ }
+--
+1.8.4.2
+
--- /dev/null
+From 7b128f96ee56a69a12bd00c16f8bce218a31daf7 Mon Sep 17 00:00:00 2001
+Message-Id: <7b128f96ee56a69a12bd00c16f8bce218a31daf7.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:22 +0100
+Subject: [PATCH] cpu: x86: Rename x86MakeCPUData as virCPUx86MakeData
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit 4a530268c03b5596532de3ff0b9e036d8e20e5c5)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e8e1990..a857559 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -216,7 +216,7 @@ virCPUx86DataFree(virCPUx86Data *data)
+
+
+ static virCPUDataPtr
+-x86MakeCPUData(virArch arch, virCPUx86Data **data)
++virCPUx86MakeData(virArch arch, virCPUx86Data **data)
+ {
+ virCPUDataPtr cpuData;
+
+@@ -1204,7 +1204,7 @@ x86CPUDataParse(const char *xmlStr)
+ goto cleanup;
+ }
+
+- cpuData = x86MakeCPUData(VIR_ARCH_X86_64, &data);
++ cpuData = virCPUx86MakeData(VIR_ARCH_X86_64, &data);
+
+ cleanup:
+ VIR_FREE(nodes);
+@@ -1367,7 +1367,7 @@ x86Compute(virCPUDefPtr host,
+ x86DataSubtract(guest_model->data, cpu_disable->data);
+
+ if (!(guestData = x86DataCopy(guest_model->data)) ||
+- !(*guest = x86MakeCPUData(arch, &guestData))) {
++ !(*guest = virCPUx86MakeData(arch, &guestData))) {
+ virCPUx86DataFree(guestData);
+ goto error;
+ }
+@@ -1624,22 +1624,22 @@ x86Encode(virArch arch,
+ }
+
+ if (forced &&
+- !(*forced = x86MakeCPUData(arch, &data_forced)))
++ !(*forced = virCPUx86MakeData(arch, &data_forced)))
+ goto error;
+ if (required &&
+- !(*required = x86MakeCPUData(arch, &data_required)))
++ !(*required = virCPUx86MakeData(arch, &data_required)))
+ goto error;
+ if (optional &&
+- !(*optional = x86MakeCPUData(arch, &data_optional)))
++ !(*optional = virCPUx86MakeData(arch, &data_optional)))
+ goto error;
+ if (disabled &&
+- !(*disabled = x86MakeCPUData(arch, &data_disabled)))
++ !(*disabled = virCPUx86MakeData(arch, &data_disabled)))
+ goto error;
+ if (forbidden &&
+- !(*forbidden = x86MakeCPUData(arch, &data_forbidden)))
++ !(*forbidden = virCPUx86MakeData(arch, &data_forbidden)))
+ goto error;
+ if (vendor &&
+- !(*vendor = x86MakeCPUData(arch, &data_vendor)))
++ !(*vendor = virCPUx86MakeData(arch, &data_vendor)))
+ goto error;
+
+ ret = 0;
+@@ -1748,7 +1748,7 @@ x86NodeData(virArch arch)
+ goto error;
+ data->extended_len = ret;
+
+- if (!(cpuData = x86MakeCPUData(arch, &data)))
++ if (!(cpuData = virCPUx86MakeData(arch, &data)))
+ goto error;
+
+ return cpuData;
+--
+1.8.4.2
+
--- /dev/null
+From 19b983fe7b1037f18ab291d655b01adc5986b642 Mon Sep 17 00:00:00 2001
+Message-Id: <19b983fe7b1037f18ab291d655b01adc5986b642.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:26 +0100
+Subject: [PATCH] cpu: x86: Use whitespace to clarify context and use
+ consistent labels
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+(cherry picked from commit 6355e2630c1e7a97a753488c568a96bce2cb61f7)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 6c599f8..610f028 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1295,6 +1295,7 @@ x86Compute(virCPUDefPtr host,
+ "CPU vendor %s"),
+ cpu->vendor) < 0)
+ goto error;
++
+ return VIR_CPU_COMPARE_INCOMPATIBLE;
+ }
+
+@@ -1311,7 +1312,7 @@ x86Compute(virCPUDefPtr host,
+ if (!x86DataIsEmpty(cpu_forbid->data)) {
+ virX86CpuIncompatible(N_("Host CPU provides forbidden features"),
+ cpu_forbid->data);
+- goto out;
++ goto cleanup;
+ }
+
+ /* first remove features that were inherited from the CPU model and were
+@@ -1326,7 +1327,7 @@ x86Compute(virCPUDefPtr host,
+ virX86CpuIncompatible(N_("Host CPU does not provide required "
+ "features"),
+ cpu_require->data);
+- goto out;
++ goto cleanup;
+ }
+
+ ret = VIR_CPU_COMPARE_IDENTICAL;
+@@ -1348,7 +1349,7 @@ x86Compute(virCPUDefPtr host,
+ virX86CpuIncompatible(N_("Host CPU does not strictly match guest CPU: "
+ "Extra features"),
+ diff->data);
+- goto out;
++ goto cleanup;
+ }
+
+ if (guest != NULL) {
+@@ -1373,7 +1374,7 @@ x86Compute(virCPUDefPtr host,
+ }
+ }
+
+-out:
++cleanup:
+ x86MapFree(map);
+ x86ModelFree(host_model);
+ x86ModelFree(diff);
+@@ -1388,7 +1389,7 @@ out:
+
+ error:
+ ret = VIR_CPU_COMPARE_ERROR;
+- goto out;
++ goto cleanup;
+ }
+ #undef virX86CpuIncompatible
+
+--
+1.8.4.2
+
--- /dev/null
+From f8da43ba082eb3b6beea90147ad0222dc4870a25 Mon Sep 17 00:00:00 2001
+Message-Id: <f8da43ba082eb3b6beea90147ad0222dc4870a25.1383922566.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:30 +0100
+Subject: [PATCH] cpu_x86: Refactor storage of CPUID data to add support for
+ KVM features
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+The CPUID functions were stored in multiple arrays according to a
+specified prefix of those. This made it very hard to add another prefix
+to store KVM CPUID features (0x40000000). Instead of hardcoding a third
+array this patch changes the approach used:
+
+The code is refactored to use a single array where the CPUID functions
+are stored ordered by the cpuid function so that they don't depend on
+the specific prefix and don't waste memory. The code is also less
+complex using this approach. A trateoff to this is the change from O(N)
+complexity to O(N^2) in x86DataAdd and x86DataSubtract. The rest of the
+functions were already using O(N^2) algorithms.
+
+(cherry picked from commit f80a11c9214fdd0e2eb489fc1481de6bba0c3a5c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/cpu/cpu_x86.c | 213 ++++++++++++++++++-------------------------------
+ src/cpu/cpu_x86_data.h | 8 +-
+ 2 files changed, 80 insertions(+), 141 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index d4d3731..3bdb3c3 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -84,14 +84,13 @@ enum compare_result {
+
+
+ struct virCPUx86DataIterator {
+- virCPUx86Data *data;
++ const virCPUx86Data *data;
+ int pos;
+- bool extended;
+ };
+
+
+ #define virCPUx86DataIteratorInit(data) \
+- { data, -1, false }
++ { data, -1 }
+
+
+ static bool
+@@ -120,6 +119,9 @@ static void
+ x86cpuidSetBits(virCPUx86CPUID *cpuid,
+ const virCPUx86CPUID *mask)
+ {
++ if (!mask)
++ return;
++
+ cpuid->eax |= mask->eax;
+ cpuid->ebx |= mask->ebx;
+ cpuid->ecx |= mask->ecx;
+@@ -131,6 +133,9 @@ static void
+ x86cpuidClearBits(virCPUx86CPUID *cpuid,
+ const virCPUx86CPUID *mask)
+ {
++ if (!mask)
++ return;
++
+ cpuid->eax &= ~mask->eax;
+ cpuid->ebx &= ~mask->ebx;
+ cpuid->ecx &= ~mask->ecx;
+@@ -142,42 +147,45 @@ static void
+ x86cpuidAndBits(virCPUx86CPUID *cpuid,
+ const virCPUx86CPUID *mask)
+ {
++ if (!mask)
++ return;
++
+ cpuid->eax &= mask->eax;
+ cpuid->ebx &= mask->ebx;
+ cpuid->ecx &= mask->ecx;
+ cpuid->edx &= mask->edx;
+ }
+
++static int
++virCPUx86CPUIDSorter(const void *a, const void *b)
++{
++ virCPUx86CPUID *da = (virCPUx86CPUID *) a;
++ virCPUx86CPUID *db = (virCPUx86CPUID *) b;
++
++ if (da->function > db->function)
++ return 1;
++ else if (da->function < db->function)
++ return -1;
++
++ return 0;
++}
++
+
+ /* skips all zero CPUID leafs */
+ static virCPUx86CPUID *
+ x86DataCpuidNext(struct virCPUx86DataIterator *iterator)
+ {
+- virCPUx86CPUID *ret;
+- virCPUx86Data *data = iterator->data;
++ const virCPUx86Data *data = iterator->data;
+
+ if (!data)
+ return NULL;
+
+- do {
+- ret = NULL;
+- iterator->pos++;
+-
+- if (!iterator->extended) {
+- if (iterator->pos < data->basic_len)
+- ret = data->basic + iterator->pos;
+- else {
+- iterator->extended = true;
+- iterator->pos = 0;
+- }
+- }
+-
+- if (iterator->extended && iterator->pos < data->extended_len) {
+- ret = data->extended + iterator->pos;
+- }
+- } while (ret && x86cpuidMatch(ret, &cpuidNull));
++ while (++iterator->pos < data->len) {
++ if (!x86cpuidMatch(data->data + iterator->pos, &cpuidNull))
++ return data->data + iterator->pos;
++ }
+
+- return ret;
++ return NULL;
+ }
+
+
+@@ -185,36 +193,23 @@ static virCPUx86CPUID *
+ x86DataCpuid(const virCPUx86Data *data,
+ uint32_t function)
+ {
+- virCPUx86CPUID *cpuids;
+- int len;
+ size_t i;
+
+- if (function < CPUX86_EXTENDED) {
+- cpuids = data->basic;
+- len = data->basic_len;
+- i = function;
+- }
+- else {
+- cpuids = data->extended;
+- len = data->extended_len;
+- i = function - CPUX86_EXTENDED;
++ for (i = 0; i < data->len; i++) {
++ if (data->data[i].function == function)
++ return data->data + i;
+ }
+
+- if (i < len && !x86cpuidMatch(cpuids + i, &cpuidNull))
+- return cpuids + i;
+- else
+- return NULL;
++ return NULL;
+ }
+
+-
+ void
+ virCPUx86DataFree(virCPUx86Data *data)
+ {
+ if (data == NULL)
+ return;
+
+- VIR_FREE(data->basic);
+- VIR_FREE(data->extended);
++ VIR_FREE(data->data);
+ VIR_FREE(data);
+ }
+
+@@ -251,77 +246,36 @@ x86DataCopy(const virCPUx86Data *data)
+ virCPUx86Data *copy = NULL;
+ size_t i;
+
+- if (VIR_ALLOC(copy) < 0
+- || VIR_ALLOC_N(copy->basic, data->basic_len) < 0
+- || VIR_ALLOC_N(copy->extended, data->extended_len) < 0) {
++ if (VIR_ALLOC(copy) < 0 ||
++ VIR_ALLOC_N(copy->data, data->len) < 0) {
+ virCPUx86DataFree(copy);
+ return NULL;
+ }
+
+- copy->basic_len = data->basic_len;
+- for (i = 0; i < data->basic_len; i++)
+- copy->basic[i] = data->basic[i];
+-
+- copy->extended_len = data->extended_len;
+- for (i = 0; i < data->extended_len; i++)
+- copy->extended[i] = data->extended[i];
++ copy->len = data->len;
++ for (i = 0; i < data->len; i++)
++ copy->data[i] = data->data[i];
+
+ return copy;
+ }
+
+
+-static int
+-x86DataExpand(virCPUx86Data *data,
+- int basic_by,
+- int extended_by)
+-{
+- size_t i;
+-
+- if (basic_by > 0) {
+- size_t len = data->basic_len;
+- if (VIR_EXPAND_N(data->basic, data->basic_len, basic_by) < 0)
+- return -1;
+-
+- for (i = 0; i < basic_by; i++)
+- data->basic[len + i].function = len + i;
+- }
+-
+- if (extended_by > 0) {
+- size_t len = data->extended_len;
+- if (VIR_EXPAND_N(data->extended, data->extended_len, extended_by) < 0)
+- return -1;
+-
+- for (i = 0; i < extended_by; i++)
+- data->extended[len + i].function = len + i + CPUX86_EXTENDED;
+- }
+-
+- return 0;
+-}
+-
+-
+ int
+ virCPUx86DataAddCPUID(virCPUx86Data *data,
+ const virCPUx86CPUID *cpuid)
+ {
+- unsigned int basic_by = 0;
+- unsigned int extended_by = 0;
+- virCPUx86CPUID **cpuids;
+- unsigned int pos;
+-
+- if (cpuid->function < CPUX86_EXTENDED) {
+- pos = cpuid->function;
+- basic_by = pos + 1 - data->basic_len;
+- cpuids = &data->basic;
+- } else {
+- pos = cpuid->function - CPUX86_EXTENDED;
+- extended_by = pos + 1 - data->extended_len;
+- cpuids = &data->extended;
+- }
++ virCPUx86CPUID *existing;
+
+- if (x86DataExpand(data, basic_by, extended_by) < 0)
+- return -1;
++ if ((existing = x86DataCpuid(data, cpuid->function))) {
++ x86cpuidSetBits(existing, cpuid);
++ } else {
++ if (VIR_APPEND_ELEMENT_COPY(data->data, data->len,
++ *((virCPUx86CPUID *)cpuid)) < 0)
++ return -1;
+
+- x86cpuidSetBits((*cpuids) + pos, cpuid);
++ qsort(data->data, data->len,
++ sizeof(virCPUx86CPUID), virCPUx86CPUIDSorter);
++ }
+
+ return 0;
+ }
+@@ -331,21 +285,19 @@ static int
+ x86DataAdd(virCPUx86Data *data1,
+ const virCPUx86Data *data2)
+ {
+- size_t i;
+-
+- if (x86DataExpand(data1,
+- data2->basic_len - data1->basic_len,
+- data2->extended_len - data1->extended_len) < 0)
+- return -1;
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2);
++ virCPUx86CPUID *cpuid1;
++ virCPUx86CPUID *cpuid2;
+
+- for (i = 0; i < data2->basic_len; i++) {
+- x86cpuidSetBits(data1->basic + i,
+- data2->basic + i);
+- }
++ while ((cpuid2 = x86DataCpuidNext(&iter))) {
++ cpuid1 = x86DataCpuid(data1, cpuid2->function);
+
+- for (i = 0; i < data2->extended_len; i++) {
+- x86cpuidSetBits(data1->extended + i,
+- data2->extended + i);
++ if (cpuid1) {
++ x86cpuidSetBits(cpuid1, cpuid2);
++ } else {
++ if (virCPUx86DataAddCPUID(data1, cpuid2) < 0)
++ return -1;
++ }
+ }
+
+ return 0;
+@@ -356,19 +308,13 @@ static void
+ x86DataSubtract(virCPUx86Data *data1,
+ const virCPUx86Data *data2)
+ {
+- size_t i;
+- unsigned int len;
+-
+- len = MIN(data1->basic_len, data2->basic_len);
+- for (i = 0; i < len; i++) {
+- x86cpuidClearBits(data1->basic + i,
+- data2->basic + i);
+- }
++ struct virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
++ virCPUx86CPUID *cpuid1;
++ virCPUx86CPUID *cpuid2;
+
+- len = MIN(data1->extended_len, data2->extended_len);
+- for (i = 0; i < len; i++) {
+- x86cpuidClearBits(data1->extended + i,
+- data2->extended + i);
++ while ((cpuid1 = x86DataCpuidNext(&iter))) {
++ cpuid2 = x86DataCpuid(data2, cpuid1->function);
++ x86cpuidClearBits(cpuid1, cpuid2);
+ }
+ }
+
+@@ -1726,25 +1672,23 @@ cpuidCall(virCPUx86CPUID *cpuid)
+
+
+ static int
+-cpuidSet(uint32_t base, virCPUx86CPUID **set)
++cpuidSet(uint32_t base, virCPUx86Data *data)
+ {
+ uint32_t max;
+ uint32_t i;
+ virCPUx86CPUID cpuid = { base, 0, 0, 0, 0 };
+
+ cpuidCall(&cpuid);
+- max = cpuid.eax - base;
++ max = cpuid.eax;
+
+- if (VIR_ALLOC_N(*set, max + 1) < 0)
+- return -1;
+-
+- for (i = 0; i <= max; i++) {
+- cpuid.function = base | i;
++ for (i = base; i <= max; i++) {
++ cpuid.function = i;
+ cpuidCall(&cpuid);
+- (*set)[i] = cpuid;
++ if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++ return -1;
+ }
+
+- return max + 1;
++ return 0;
+ }
+
+
+@@ -1753,18 +1697,15 @@ x86NodeData(virArch arch)
+ {
+ virCPUDataPtr cpuData = NULL;
+ virCPUx86Data *data;
+- int ret;
+
+ if (VIR_ALLOC(data) < 0)
+ return NULL;
+
+- if ((ret = cpuidSet(CPUX86_BASIC, &data->basic)) < 0)
++ if (cpuidSet(CPUX86_BASIC, data) < 0)
+ goto error;
+- data->basic_len = ret;
+
+- if ((ret = cpuidSet(CPUX86_EXTENDED, &data->extended)) < 0)
++ if (cpuidSet(CPUX86_EXTENDED, data) < 0)
+ goto error;
+- data->extended_len = ret;
+
+ if (!(cpuData = virCPUx86MakeData(arch, &data)))
+ goto error;
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index 5910ea9..69066f1 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -1,7 +1,7 @@
+ /*
+ * cpu_x86_data.h: x86 specific CPU data
+ *
+- * Copyright (C) 2009-2010 Red Hat, Inc.
++ * Copyright (C) 2009-2010, 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -40,10 +40,8 @@ struct _virCPUx86CPUID {
+
+ typedef struct _virCPUx86Data virCPUx86Data;
+ struct _virCPUx86Data {
+- size_t basic_len;
+- virCPUx86CPUID *basic;
+- size_t extended_len;
+- virCPUx86CPUID *extended;
++ size_t len;
++ virCPUx86CPUID *data;
+ };
+
+ #endif /* __VIR_CPU_X86_DATA_H__ */
+--
+1.8.4.2
+
--- /dev/null
+From 1a7c313db4a96319d1a02774846882982b39da40 Mon Sep 17 00:00:00 2001
+Message-Id: <1a7c313db4a96319d1a02774846882982b39da40.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:47 +0200
+Subject: [PATCH] docs: Clean 09adfdc62de2b up
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+(cherry picked from commit 8563b091fff4856a0cee7b568e52ff5b64d96ed3)
+---
+ docs/formatdomain.html.in | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index fb4238e..3fd83c9 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -677,8 +677,9 @@
+ <dd> The optional <code>hard_limit</code> element is the maximum memory
+ the guest can use. The units for this value are kibibytes (i.e. blocks
+ of 1024 bytes). <strong>However, users of QEMU and KVM are strongly
+- advised not to set this limit as domain may get killed by the kernel.
+- To determine the memory needed for a process to run is
++ advised not to set this limit as domain may get killed by the kernel
++ if the guess is too low. To determine the memory needed for a process
++ to run is an
+ <a href="http://en.wikipedia.org/wiki/Undecidable_problem">
+ undecidable problem</a>.</strong></dd>
+ <dt><code>soft_limit</code></dt>
+--
+1.8.3.2
+
--- /dev/null
+From 681c50c34fb55f06d4a41f12dc84c4c6e6f22bfb Mon Sep 17 00:00:00 2001
+Message-Id: <681c50c34fb55f06d4a41f12dc84c4c6e6f22bfb.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:46 +0200
+Subject: [PATCH] docs: Discourage users to set hard_limit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+In one of my previous patches I am removing the hard_limit heuristic to
+guess the correct value if none set. However, it turned out, this limit
+is hard to guess even for users. We should advise them to not set the
+limit as their domains may be OOM killed. Sigh.
+(cherry picked from commit 09adfdc62de2bbba71580839f735ec07a356c762)
+---
+ docs/formatdomain.html.in | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index a1803df..fb4238e 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -676,7 +676,11 @@
+ <dt><code>hard_limit</code></dt>
+ <dd> The optional <code>hard_limit</code> element is the maximum memory
+ the guest can use. The units for this value are kibibytes (i.e. blocks
+- of 1024 bytes)</dd>
++ of 1024 bytes). <strong>However, users of QEMU and KVM are strongly
++ advised not to set this limit as domain may get killed by the kernel.
++ To determine the memory needed for a process to run is
++ <a href="http://en.wikipedia.org/wiki/Undecidable_problem">
++ undecidable problem</a>.</strong></dd>
+ <dt><code>soft_limit</code></dt>
+ <dd> The optional <code>soft_limit</code> element is the memory limit to
+ enforce during memory contention. The units for this value are
+--
+1.8.3.2
+
--- /dev/null
+From b46a1a6517874144f0cdf918f8148503bb5771e1 Mon Sep 17 00:00:00 2001
+Message-Id: <b46a1a6517874144f0cdf918f8148503bb5771e1.1382534061.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Tue, 22 Oct 2013 16:09:06 +0100
+Subject: [PATCH] docs: Expand description of host-model CPU mode
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1014682
+
+host-model is a nice idea but it's current implementation make it
+useless on some hosts so it should be used with care.
+
+(cherry picked from commit 34adf622a352cbb80a98162a0f9ac3f9de3f95cb)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/formatdomain.html.in | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 512e0df..132c16c 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -922,7 +922,16 @@
+ model even if the destination host contains more capable CPUs for
+ the running instance of the guest; but shutting down and restarting
+ the guest may present different hardware to the guest according to
+- the capabilities of the new host.</dd>
++ the capabilities of the new host. <strong>Beware</strong>, due to the
++ way libvirt detects host CPU and due to the fact libvirt does not
++ talk to QEMU/KVM when creating the CPU model, CPU configuration
++ created using <code>host-model</code> may not work as expected. The
++ guest CPU may differ from the configuration and it may also confuse
++ guest OS by using a combination of CPU features and other parameters
++ (such as CPUID level) that don't work. Until these issues are fixed,
++ it's a good idea to avoid using <code>host-model</code> and use
++ <code>custom</code> mode with just the CPU model from host
++ capabilities XML.</dd>
+ <dt><code>host-passthrough</code></dt>
+ <dd>With this mode, the CPU visible to the guest should be exactly
+ the same as the host CPU even in the aspects that libvirt does not
+--
+1.8.4
+
--- /dev/null
+From 44d8ec7532a065d3c0ea81d5e357456d03bff910 Mon Sep 17 00:00:00 2001
+Message-Id: <44d8ec7532a065d3c0ea81d5e357456d03bff910.1377873642.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:29 -0400
+Subject: [PATCH] docs: Reformat <disk> attribute description in formatdomain
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000169
+
+Reformat the description to more cleanly delineate the attributes
+for a <disk> element.
+
+(cherry picked from commit fc82f0addec21e1fc8b184a9b303c8e7a0dca37f)
+---
+ docs/formatdomain.html.in | 121 +++++++++++++++++++++++++++-------------------
+ 1 file changed, 71 insertions(+), 50 deletions(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 203e557..a1803df 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -1557,56 +1557,77 @@
+ <dl>
+ <dt><code>disk</code></dt>
+ <dd>The <code>disk</code> element is the main container for describing
+- disks. The <code>type</code> attribute is either "file",
+- "block", "dir", "network", or "volume"
+- and refers to the underlying source for the disk. The optional
+- <code>device</code> attribute indicates how the disk is to be exposed
+- to the guest OS. Possible values for this attribute are
+- "floppy", "disk", "cdrom", and "lun", defaulting to
+- "disk". "lun" (<span class="since">since 0.9.10</span>) is only
+- valid when type is "block" and the target element's "bus"
+- attribute is "virtio", and behaves identically to "disk",
+- except that generic SCSI commands from the guest are accepted
+- and passed through to the physical device
+- - also note that device='lun' will only be recognized for
+- actual raw devices, never for individual partitions or LVM
+- partitions (in those cases, the kernel will reject the generic
+- SCSI commands, making it identical to device='disk').
+- The optional <code>rawio</code> attribute
+- (<span class="since">since 0.9.10</span>) indicates whether
+- the disk is needs rawio capability; valid settings are "yes"
+- or "no" (default is "no"). If any one disk in a domain has
+- rawio='yes', rawio capability will be enabled for all disks in
+- the domain (because, in the case of QEMU, this capability can
+- only be set on a per-process basis). This attribute is only
+- valid when device is "lun". NB, <code>rawio</code> intends to
+- confine the capability per-device, however, current QEMU
+- implementation gives the domain process broader capability
+- than that (per-process basis, affects all the domain disks).
+- To confine the capability as much as possible for QEMU driver
+- as this stage, <code>sgio</code> is recommended, it's more
+- secure than <code>rawio</code>.
+- The optional <code>sgio</code> (<span class="since">since 1.0.2</span>)
+- attribute indicates whether the kernel will filter unprivileged
+- SG_IO commands for the disk, valid settings are "filtered" or
+- "unfiltered". Defaults to "filtered". Similar to <code>rawio</code>,
+- <code>sgio</code> is only valid for device 'lun'.
+- The optional <code>snapshot</code> attribute indicates the default
+- behavior of the disk during disk snapshots: "internal"
+- requires a file format such as qcow2 that can store both the
+- snapshot and the data changes since the snapshot;
+- "external" will separate the snapshot from the live data; and
+- "no" means the disk will not participate in snapshots.
+- Read-only disks default to "no", while the default for other
+- disks depends on the hypervisor's capabilities. Some
+- hypervisors allow a per-snapshot choice as well,
+- during <a href="formatsnapshot.html">domain snapshot
+- creation</a>. Not all snapshot modes are supported;
+- for example, <code>snapshot='yes'</code> with a transient disk
+- generally does not make sense. <span class="since">Since 0.0.3;
+- "device" attribute since 0.1.4;
+- "network" attribute since 0.8.7; "snapshot" since
+- 0.9.5</span></dd>
++ disks (<span class="since">since 0.0.3</span>).
++ <dl>
++ <dt><code>type</code> attribute
++ <span class="since">since 0.0.3</span></dt>
++ <dd>
++ Valid values are "file", "block",
++ "dir" (<span class="since">since 0.7.5</span>),
++ "network" (<span class="since">since 0.8.7</span>), or
++ "volume" (<span class="since">since 1.0.5</span>)
++ and refer to the underlying source for the disk.
++ </dd>
++ <dt><code>device</code> attribute
++ <span class="since">since 0.1.4</span></dt>
++ <dd>
++ Indicates how the disk is to be exposed to the guest OS. Possible
++ values for this attribute are "floppy", "disk", "cdrom", and "lun",
++ defaulting to "disk".
++ <p>
++ Using "lun" (<span class="since">since 0.9.10</span>) is only
++ valid when type is "block" and the target element's "bus"
++ attribute is "virtio", and behaves identically to "disk",
++ except that generic SCSI commands from the guest are accepted
++ and passed through to the physical device. Also note that
++ device='lun' will only be recognized for actual raw devices,
++ but never for individual partitions or LVM partitions (in those
++ cases, the kernel will reject the generic SCSI commands, making
++ it identical to device='disk').
++ </p>
++ </dd>
++ <dt><code>rawio</code> attribute
++ <span class="since">since 0.9.10</span></dt>
++ <dd>
++ Indicates whether the disk is needs rawio capability; valid
++ settings are "yes" or "no" (default is "no"). If any one disk
++ in a domain has rawio='yes', rawio capability will be enabled
++ for all disks in the domain (because, in the case of QEMU, this
++ capability can only be set on a per-process basis). This attribute
++ is only valid when device is "lun". NB, <code>rawio</code> intends
++ to confine the capability per-device, however, current QEMU
++ implementation gives the domain process broader capability
++ than that (per-process basis, affects all the domain disks).
++ To confine the capability as much as possible for QEMU driver
++ as this stage, <code>sgio</code> is recommended, it's more
++ secure than <code>rawio</code>.
++ </dd>
++ <dt><code>sgio</code> attribute
++ <span class="since">since 1.0.2</span></dt>
++ <dd>
++ Indicates whether the kernel will filter unprivileged
++ SG_IO commands for the disk, valid settings are "filtered" or
++ "unfiltered". Defaults to "filtered". Similar to <code>rawio</code>,
++ <code>sgio</code> is only valid for device 'lun'.
++ </dd>
++ <dt><code>snapshot</code> attribute
++ <span class="since">since 0.9.5</span></dt>
++ <dd>
++ Indicates the default behavior of the disk during disk snapshots:
++ "internal" requires a file format such as qcow2 that can store
++ both the snapshot and the data changes since the snapshot;
++ "external" will separate the snapshot from the live data; and
++ "no" means the disk will not participate in snapshots. Read-only
++ disks default to "no", while the default for other disks depends
++ on the hypervisor's capabilities. Some hypervisors allow a
++ per-snapshot choice as well, during
++ <a href="formatsnapshot.html">domain snapshot creation</a>.
++ Not all snapshot modes are supported; for example,
++ <code>snapshot='yes'</code> with a transient disk generally
++ does not make sense.
++ </dd>
++ </dl>
++ </dd>
+ <dt><code>source</code></dt>
+ <dd>Representation of the disk <code>source</code> depends on the
+ disk <code>type</code> attribute value as follows:
+--
+1.8.3.2
+
--- /dev/null
+From e2f88bd51503615700467ed4a15331e79d21d0fe Mon Sep 17 00:00:00 2001
+Message-Id: <e2f88bd51503615700467ed4a15331e79d21d0fe.1377873641.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:27 -0400
+Subject: [PATCH] docs: Update formatsecrets to include more examples of each
+ type
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000169
+
+Update formatsecret docs to describe the various options and provide examples
+in order to set up secrets for each type of secret.
+
+(cherry picked from commit 4ba052907848b85d5f61144707b101ad82314674)
+---
+ docs/formatsecret.html.in | 180 ++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 166 insertions(+), 14 deletions(-)
+
+diff --git a/docs/formatsecret.html.in b/docs/formatsecret.html.in
+index 3e306b5..651f722 100644
+--- a/docs/formatsecret.html.in
++++ b/docs/formatsecret.html.in
+@@ -46,18 +46,51 @@
+ </dd>
+ </dl>
+
+- <h3>Usage type "volume"</h3>
++ <h3><a name="VolumeUsageType">Usage type "volume"</a></h3>
+
+ <p>
+ This secret is associated with a volume, and it is safe to delete the
+ secret after the volume is deleted. The <code><usage
+ type='volume'></code> element must contain a
+ single <code>volume</code> element that specifies the key of the volume
+- this secret is associated with.
++ this secret is associated with. For example, create a volume-secret.xml
++ file as follows:
+ </p>
+
+- <h3>Usage type "ceph"</h3>
++ <pre>
++ <secret ephemeral='no' private='yes'>
++ <description>Super secret name of my first puppy</description>
++ <uuid>0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f</uuid>
++ <usage type='volume'>
++ <volume>/var/lib/libvirt/images/puppyname.img</volume>
++ </usage>
++ </secret>
++ </pre>
++
++ <p>
++ Define the secret and set the pass phrase as follows:
++ </p>
++ <pre>
++ # virsh secret-define volume-secret.xml
++ Secret 0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f created
++ #
++ # MYSECRET=`printf %s "open sesame" | base64`
++ # virsh secret-set-value 0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f $MYSECRET
++ Secret value set
++ #
++ </pre>
++
++ <p>
++ The volume type secret can then be used in the XML for a storage volume
++ <a href="formatstorageencryption.html">encryption</a> as follows:
++ </p>
++ <pre>
++ <encryption format='qcow'>
++ <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/>
++ </encryption>
++ </pre>
+
++ <h3><a name="CephUsageType">Usage type "ceph"</a></h3>
+ <p>
+ This secret is associated with a Ceph RBD (rados block device).
+ The <code><usage type='ceph'></code> element must contain
+@@ -66,30 +99,149 @@
+ this usage name via the <code><auth></code> element of
+ a <a href="formatdomain.html#elementsDisks">disk device</a> or
+ a <a href="formatstorage.html">storage pool (rbd)</a>.
+- <span class="since">Since 0.9.7</span>.
++ <span class="since">Since 0.9.7</span>. The following is an example
++ of the steps to be taken. First create a ceph-secret.xml file:
++ </p>
++
++ <pre>
++ <secret ephemeral='no' private='yes'>
++ <description>CEPH passphrase example</description>
++ <auth type='ceph' username='myname'/>
++ <usage type='ceph'>
++ <name>ceph_example</name>
++ </usage>
++ </secret>
++ </pre>
++
++ <p>
++ Next, use <code>virsh secret-define ceph-secret.xml</code> to define
++ the secret and <code>virsh secret-set-value</code> using the generated
++ UUID value and a base64 generated secret value in order to define the
++ chosen secret pass phrase.
++ </p>
++ <pre>
++ # virsh secret-define ceph-secret.xml
++ Secret 1b40a534-8301-45d5-b1aa-11894ebb1735 created
++ #
++ # virsh secret-list
++ UUID Usage
++ -----------------------------------------------------------
++ 1b40a534-8301-45d5-b1aa-11894ebb1735 cephx ceph_example
++ #
++ # CEPHPHRASE=`printf %s "pass phrase" | base64`
++ # virsh secret-set-value 1b40a534-8301-45d5-b1aa-11894ebb1735 $CEPHPHRASE
++ Secret value set
++
++ #
++ </pre>
++
++ <p>
++ The ceph secret can then be used by UUID or by the
++ usage name via the <code><auth></code> element in a domain's
++ <a href="formatdomain.html#elementsDisks"><code><disk></code></a>
++ element as follows:
+ </p>
++ <pre>
++ <auth username='myname'>
++ <secret type='ceph' usage='ceph_example'/>
++ </auth>
++ </pre>
++
++ <p>
++ As well as the <code><auth></code> element in a
++ <a href="formatstorage.html">storage pool (rbd)</a>
++ <code><source></code> element as follows:
++ </p>
++ <pre>
++ <auth type='ceph' username='myname'>
++ <secret usage='ceph_example'/>
++ </auth>
++ </pre>
+
+- <h3>Usage type "iscsi"</h3>
++ <h3><a name="iSCSIUsageType">Usage type "iscsi"</a></h3>
+
+ <p>
+ This secret is associated with an iSCSI target for CHAP authentication.
+ The <code><usage type='iscsi'></code> element must contain
+ a single <code>target</code> element that specifies a usage name
+- for the secret. The iSCSI secret can then be used by UUID or by
++ for the secret. The iSCSI secret can then be used by UUID or by
+ this usage name via the <code><auth></code> element of
+ a <a href="formatdomain.html#elementsDisks">disk device</a> or
+ a <a href="formatstorage.html">storage pool (iscsi)</a>.
+- <span class="since">Since 1.0.4</span>.
++ <span class="since">Since 1.0.4</span>. The following is an example
++ of the XML that may be used to generate a secret for iSCSI CHAP
++ authentication. Assume the following sample entry in an iSCSI
++ authentication file:
++ </p>
++ <pre>
++ <target iqn.2013-07.com.example:iscsi-pool>
++ backing-store /home/tgtd/iscsi-pool/disk1
++ backing-store /home/tgtd/iscsi-pool/disk2
++ incominguser myname mysecret
++ </target>
++ </pre>
++ <p>
++ Define an iscsi-secret.xml file to describe the secret. Use the
++ <code>incominguser</code> username used in your iSCSI authentication
++ configuration file as the value for the <code>username</code> attribute.
++ The <code>description</code> attribute should contain configuration
++ specific data. The <code>target</code> name may be any name of your
++ choosing to be used as the <code>usage</code> when used in the pool
++ or disk XML description.
+ </p>
+-
+- <h2><a name="example">Example</a></h2>
+-
+ <pre>
+ <secret ephemeral='no' private='yes'>
+- <description>LUKS passphrase for the main hard drive of our mail server</description>
+- <usage type='volume'>
+- <volume>/var/lib/libvirt/images/mail.img</volume>
++ <description>Passphrase for the iSCSI example.com server</description>
++ <auth type='chap' username='myname'/>
++ <usage type='iscsi'>
++ <target>libvirtiscsi</target>
+ </usage>
+- </secret></pre>
++ </secret>
++ </pre>
++
++ <p>
++ Next, use <code>virsh secret-define iscsi-secret.xml</code> to define
++ the secret and <code>virsh secret-set-value</code> using the generated
++ UUID value and a base64 generated secret value in order to define the
++ chosen secret pass phrase. The pass phrase must match the password
++ used in the iSCSI authentication configuration file.
++ </p>
++ <pre>
++ # virsh secret-define secret.xml
++ Secret c4dbe20b-b1a3-4ac1-b6e6-2ac97852ebb6 created
++
++ # virsh secret-list
++ UUID Usage
++ -----------------------------------------------------------
++ c4dbe20b-b1a3-4ac1-b6e6-2ac97852ebb6 iscsi libvirtiscsi
++
++ # MYSECRET=`printf %s "mysecret" | base64`
++ # virsh secret-set-value c4dbe20b-b1a3-4ac1-b6e6-2ac97852ebb6 $MYSECRET
++ Secret value set
++ #
++ </pre>
++
++ <p>
++ The iSCSI secret can then be used by UUID or by the
++ usage name via the <code><auth></code> element in a domain's
++ <a href="formatdomain.html#elementsDisks"><code><disk></code></a>
++ element as follows:
++ </p>
++ <pre>
++ <auth username='myname'>
++ <secret type='iscsi' usage='libvirtiscsi'/>
++ </auth>
++ </pre>
++
++ <p>
++ As well as the <code><auth></code> element in a
++ <a href="formatstorage.html">storage pool (iscsi)</a>
++ <code><source></code> element as follows:
++ </p>
++ <pre>
++ <auth type='chap' username='myname'>
++ <secret usage='libvirtiscsi'/>
++ </auth>
++ </pre>
+ </body>
+ </html>
+--
+1.8.3.2
+
--- /dev/null
+From 567bf763b2c650b9c14c7a88a2759bd19ab40ddc Mon Sep 17 00:00:00 2001
+Message-Id: <567bf763b2c650b9c14c7a88a2759bd19ab40ddc.1377873642.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:28 -0400
+Subject: [PATCH] docs: Update iSCSI storage pool example
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000169
+
+Update the iSCSI storage pool example to include the secret
+
+(cherry picked from commit c753749c27fb48d481e64953d59668731e5e2dbd)
+---
+ docs/formatstorage.html.in | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
+index f4d561f..278f89b 100644
+--- a/docs/formatstorage.html.in
++++ b/docs/formatstorage.html.in
+@@ -480,7 +480,10 @@
+ <name>virtimages</name>
+ <source>
+ <host name="iscsi.example.com"/>
+- <device path="demo-target"/>
++ <device path="iqn.2013-06.com.example:iscsi-pool"/>
++ <auth type='chap' username='myuser'>
++ <secret usage='libvirtiscsi'/>
++ </auth>
+ </source>
+ <target>
+ <path>/dev/disk/by-path</path>
+--
+1.8.3.2
+
--- /dev/null
+From 002a473e60b72997b5b1b96f9d96de3ec9081ef4 Mon Sep 17 00:00:00 2001
+Message-Id: <002a473e60b72997b5b1b96f9d96de3ec9081ef4.1377873641.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:26 -0400
+Subject: [PATCH] docs: Update the formatdomain disk examples
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000169
+
+Add more iSCSI examples including having a secret attached. There are 4 new
+examples; one for each way to have an iSCSI - a network disk using virtio,
+a passthrough network lun using scsi, a volume disk using "mode='host'",
+and a volume disk using "mode='direct'"
+
+(cherry picked from commit cb3b7dce7ce7186f8ef438724fabfec11855e3fd)
+---
+ docs/formatdomain.html.in | 165 ++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 122 insertions(+), 43 deletions(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index fb7d671..203e557 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -1514,6 +1514,43 @@
+ <source pool='blk-pool0' volume='blk-pool0-vol0'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
++ <disk type='network' device='disk'>
++ <driver name='qemu' type='raw'/>
++ <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/2'>
++ <host name='example.com' port='3260'/>
++ </source>
++ <auth username='myuser'>
++ <secret type='chap' usage='libvirtiscsi'/>
++ </auth>
++ <target dev='vda' bus='virtio'/>
++ </disk>
++ <disk type='network' device='lun'>
++ <driver name='qemu' type='raw'/>
++ <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/1'>
++ iqn.2013-07.com.example:iscsi-pool
++ <host name='example.com' port='3260'/>
++ </source>
++ <auth username='myuser'>
++ <secret type='chap' usage='libvirtiscsi'/>
++ </auth>
++ <target dev='sda' bus='scsi'/>
++ </disk>
++ <disk type='volume' device='disk'>
++ <driver name='qemu' type='raw'/>
++ <source pool='iscsi-pool' volume='unit:0:0:1' mode='host'/>
++ <auth username='myuser'>
++ <secret type='chap' usage='libvirtiscsi'/>
++ </auth>
++ <target dev='vda' bus='virtio'/>
++ </disk>
++ <disk type='volume' device='disk'>
++ <driver name='qemu' type='raw'/>
++ <source pool='iscsi-pool' volume='unit:0:0:2' mode='direct'/>
++ <auth username='myuser'>
++ <secret type='chap' usage='libvirtiscsi'/>
++ </auth>
++ <target dev='vda' bus='virtio'/>
++ </disk>
+ </devices>
+ ...</pre>
+
+@@ -1521,7 +1558,7 @@
+ <dt><code>disk</code></dt>
+ <dd>The <code>disk</code> element is the main container for describing
+ disks. The <code>type</code> attribute is either "file",
+- "block", "dir", or "network"
++ "block", "dir", "network", or "volume"
+ and refers to the underlying source for the disk. The optional
+ <code>device</code> attribute indicates how the disk is to be exposed
+ to the guest OS. Possible values for this attribute are
+@@ -1571,57 +1608,96 @@
+ "network" attribute since 0.8.7; "snapshot" since
+ 0.9.5</span></dd>
+ <dt><code>source</code></dt>
+- <dd>If the disk <code>type</code> is "file", then
+- the <code>file</code> attribute specifies the fully-qualified
+- path to the file holding the disk. If the disk
+- <code>type</code> is "block", then the <code>dev</code>
+- attribute specifies the path to the host device to serve as
+- the disk. With "file", "block", and "volume", one or more optional
++ <dd>Representation of the disk <code>source</code> depends on the
++ disk <code>type</code> attribute value as follows:
++ <dl>
++ <dt><code>type='file'</code>
++ <span class="since">since 0.0.3</span></dt>
++ <dd>
++ The <code>file</code> attribute specifies the fully-qualified
++ path to the file holding the disk.
++ </dd>
++ <dt><code>type='block'</code>
++ <span class="since">since 0.0.3</span></dt>
++ <dd>
++ The <code>dev</code> attribute specifies the path to the
++ host device to serve as the disk.
++ </dd>
++ <dt><code>type='dir'</code>
++ <span class="since">since 0.7.5</span></dt>
++ <dd>
++ The <code>dir</code> attribute specifies the fully-qualified path
++ to the directory to use as the disk.
++ </dd>
++ <dt><code>type='network'</code>
++ <span class="since">since 0.8.7</span></dt>
++ <dd>
++ The <code>protocol</code> attribute specifies the protocol to
++ access to the requested image. Possible values are "nbd",
++ "iscsi", "rbd", "sheepdog" or "gluster". If the
++ <code>protocol</code> attribute is "rbd", "sheepdog" or
++ "gluster", an additional attribute <code>name</code> is
++ mandatory to specify which volume/image will be used. For "nbd",
++ the <code>name</code> attribute is optional. For "iscsi"
++ (<span class="since">since 1.0.4</span>), the <code>name</code>
++ attribute may include a logical unit number, separated from the
++ target's name by a slash (e.g.,
++ <code>iqn.2013-07.com.example:iscsi-pool/1</code>). If not
++ specified, the default LUN is zero.
++ </dd>
++ <dt><code>type='volume'</code>
++ <span class="since">since 1.0.5</span></dt>
++ <dd>
++ The underlying disk source is represented by attributes
++ <code>pool</code> and <code>volume</code>. Attribute
++ <code>pool</code> specifies the name of the
++ <a href="formatstorage.html">storage pool</a> (managed
++ by libvirt) where the disk source resides. Attribute
++ <code>volume</code> specifies the name of storage volume (managed
++ by libvirt) used as the disk source. The value for the
++ <code>volume</code> attribute will be the output from the "Name"
++ column of a <code>virsh vol-list [pool-name]</code> command.
++ <p>
++ Use the attribute <code>mode</code>
++ (<span class="since">since 1.1.1</span>) to indicate how to
++ represent the LUN as the disk source. Valid values are
++ "direct" and "host". If <code>mode</code> is not specified,
++ the default is to use "host".
++
++ Using "direct" as the <code>mode</code> value indicates to use
++ the <a href="formatstorage.html">storage pool's</a>
++ <code>source</code> element <code>host</code> attribute as
++ the disk source to generate the libiscsi URI (e.g.
++ 'file=iscsi://example.com:3260/iqn.2013-07.com.example:iscsi-pool/1').
++
++ Using "host" as the <code>mode</code> value indicates to use the
++ LUN's path as it shows up on host (e.g.
++ 'file=/dev/disk/by-path/ip-example.com:3260-iscsi-iqn.2013-07.com.example:iscsi-pool-lun-1').
++ </p>
++ </dd>
++ </dl>
++ With "file", "block", and "volume", one or more optional
+ sub-elements <code>seclabel</code>, <a href="#seclabel">described
+ below</a> (and <span class="since">since 0.9.9</span>), can be
+ used to override the domain security labeling policy for just
+ that source file. (NB, for "volume" type disk, <code>seclabel</code>
+ is only valid when the specified storage volume is of 'file' or
+- 'block' type). If the disk <code>type</code> is "dir", then the
+- <code>dir</code> attribute specifies the fully-qualified path
+- to the directory to use as the disk. If the disk <code>type</code>
+- is "network", then the <code>protocol</code> attribute specifies
+- the protocol to access to the requested image; possible values
+- are "nbd", "iscsi", "rbd", "sheepdog" or "gluster". If the
+- <code>protocol</code> attribute is "rbd", "sheepdog" or "gluster", an
+- additional attribute <code>name</code> is mandatory to specify which
+- volume/image will be used; for "nbd" it is optional. For "iscsi",
+- the <code>name</code> attribute may include a logical unit number,
+- separated from the target's name by a slash (for example,
+- <code>iqn.1992-01.com.example/1</code>); the default LUN is zero.
++ 'block' type).
++ <p>
+ When the disk <code>type</code> is "network", the <code>source</code>
+ may have zero or more <code>host</code> sub-elements used to
+- specify the hosts to connect. If the disk <code>type</code> is
+- "volume", the underlying disk source is represented by attributes
+- <code>pool</code> and <code>volume</code>. Attribute <code>pool</code>
+- specifies the name of storage pool (managed by libvirt) where the disk
+- source resides, and attribute <code>volume</code> specifies the name of
+- storage volume (managed by libvirt) used as the disk source. For a
+- "volume" type disk, if the underlying storage pool is "iscsi", attribute
+- <code>mode</code> (<span class="since">since 1.1.1</span>) can be used
+- to indicate how to represent the LUN as the disk source. The value
+- "host" indicates to use the LUN's path as it shows up on host, e.g.
+- /dev/disk/by-path/ip-10.11.12.9:3260-iscsi-iqn.2013-06.fc:iscsi.iscsi0-lun-1).
+- The value "direct" indicates to use the storage pool's
+- <code>source</code> element <code>host</code> attribute as the
+- disk source for the libiscsi URI, e.g.
+- file=iscsi://demo.org:6000/iqn.1992-01.com.example/1.
+- <span class="since">Since 0.0.3; <code>type='dir'</code> since
+- 0.7.5; <code>type='network'</code> since
+- 0.8.7; <code>protocol='iscsi'</code> since 1.0.4;
+- <code>type='volume'</code> since 1.0.5;</span><br/>
++ specify the hosts to connect.
++ </p>
++ <p>
+ For a "file" or "volume" disk type which represents a cdrom or floppy
+ (the <code>device</code> attribute), it is possible to define
+ policy what to do with the disk if the source file is not accessible.
+ (NB, <code>startupPolicy</code> is not valid for "volume" disk unless
+ the specified storage volume is of "file" type). This is done by the
+- <code>startupPolicy</code> attribute (<span class="since">Since 0.9.7</span>),
++ <code>startupPolicy</code> attribute
++ (<span class="since">since 0.9.7</span>),
+ accepting these values:
++ </p>
+ <table class="top_table">
+ <tr>
+ <td> mandatory </td>
+@@ -1637,10 +1713,13 @@
+ <td> drop if missing at any start attempt </td>
+ </tr>
+ </table>
+- <span class="since">Since 1.1.2</span> the <code>startupPolicy</code> is extended
+- to support hard disks besides cdrom and floppy. On guest cold bootup, if a certain disk
+- is not accessible or its disk chain is broken, with startupPolicy 'optional' the guest
+- will drop this disk. This feature doesn't support migration currently.
++ <p>
++ <span class="since">Since 1.1.2</span> the <code>startupPolicy</code>
++ is extended to support hard disks besides cdrom and floppy. On guest
++ cold bootup, if a certain disk is not accessible or its disk chain is
++ broken, with startupPolicy 'optional' the guest will drop this disk.
++ This feature doesn't support migration currently.
++ </p>
+ </dd>
+ <dt><code>mirror</code></dt>
+ <dd>
+--
+1.8.3.2
+
--- /dev/null
+From 519a408e23e7a6bb55d5ef459d107d3869f7b2f8 Mon Sep 17 00:00:00 2001
+Message-Id: <519a408e23e7a6bb55d5ef459d107d3869f7b2f8.1377873642.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Wed, 21 Aug 2013 08:16:48 -0600
+Subject: [PATCH] migration: do not restore labels on failed migration
+
+7.0: https://bugzilla.redhat.com/show_bug.cgi?id=822052
+6.5: https://bugzilla.redhat.com/show_bug.cgi?id=895826
+
+When doing a live migration, if the destination fails for any
+reason after the point in which files should be labeled, then
+the cleanup of the destination would restore the labels to their
+defaults, even though the source is still trying to continue
+running with the image open. Bug 822052 mentioned one source
+of live migration failure - a mismatch in SELinux virt_use_nfs
+settings (on for source, off for destination); but I found other
+situations that would also trigger it (for example, having a
+graphics device tied to port 5999 on the source, and a different
+domain on the destination already using that port, so that the
+destination cannot reuse the port).
+
+In short, just as cleanup of the source on a successful migration
+must not relabel files (because the destination would be crippled
+by the relabel), cleanup of the destination on a failed migration
+must not relabel files (because the source would be crippled).
+
+* src/qemu/qemu_process.c (qemuProcessStart): Set flag to avoid
+label restoration when cleaning up on failed migration.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit e4ddcf09fb3efa4c5014e0c3259a05beb0f719a8)
+---
+ src/qemu/qemu_process.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 6a28356..1d8df58 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3467,6 +3467,10 @@ int qemuProcessStart(virConnectPtr conn,
+ * restore any security label as we would overwrite labels
+ * we did not set. */
+ stop_flags = VIR_QEMU_PROCESS_STOP_NO_RELABEL;
++ /* If we fail while doing incoming migration, then we must not
++ * relabel, as the source is still using the files. */
++ if (migrateFrom)
++ stop_flags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
+
+ hookData.conn = conn;
+ hookData.vm = vm;
+--
+1.8.3.2
+
--- /dev/null
+From 6b1a948213c7db3eede8350f534ec3813e8b296e Mon Sep 17 00:00:00 2001
+Message-Id: <6b1a948213c7db3eede8350f534ec3813e8b296e.1379193141.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Thu, 12 Sep 2013 06:32:06 -0600
+Subject: [PATCH] netcf driver: use a single netcf handle for all connections
+
+This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=983026
+
+The netcf interface driver previously had no state driver associated
+with it - as a connection was opened, it would create a new netcf
+instance just for that connection, and close it when it was
+finished. the problem with this is that each connection to libvirt
+used up a netlink socket, and there is a per process maximum of ~1000
+netlink sockets.
+
+The solution is to create a state driver to go along with the netcf
+driver. The state driver will opens a netcf instance, then all
+connections share that same netcf instance, thus only a single
+netlink socket will be used no matter how many connections are mde to
+libvirtd.
+
+This was rather simple to do - a new virObjectLockable class is
+created for the single driverState object, which is created in
+netcfStateInitialize and contains the single netcf handle; instead of
+creating a new object for each client connection, netcfInterfaceOpen
+now just increments the driverState object's reference count and puts
+a pointer to it into the connection's privateData. Similarly,
+netcfInterfaceClose() just un-refs the driverState object (as does
+netcfStateCleanup()), and virNetcfInterfaceDriverStateDispose()
+handles closing the netcf instance. Since all the functions already
+have locking around them, the static lock functions used by all
+functions just needed to be changed to call virObjectLock() and
+virObjectUnlock() instead of directly calling the virMutex* functions.
+
+(cherry picked from commit 822fe1367dd55e3de7c3c044ee02fd733ab3415a)
+---
+ src/interface/interface_backend_netcf.c | 230 +++++++++++++++++++++-----------
+ 1 file changed, 150 insertions(+), 80 deletions(-)
+
+diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interface_backend_netcf.c
+index f47669e..fac059d 100644
+--- a/src/interface/interface_backend_netcf.c
++++ b/src/interface/interface_backend_netcf.c
+@@ -41,21 +41,114 @@
+ /* Main driver state */
+ typedef struct
+ {
+- virMutex lock;
++ virObjectLockable parent;
+ struct netcf *netcf;
+ } virNetcfDriverState, *virNetcfDriverStatePtr;
+
++static virClassPtr virNetcfDriverStateClass;
++static void virNetcfDriverStateDispose(void *obj);
+
+-static void interfaceDriverLock(virNetcfDriverStatePtr driver)
++static int
++virNetcfDriverStateOnceInit(void)
++{
++ if (!(virNetcfDriverStateClass = virClassNew(virClassForObjectLockable(),
++ "virNetcfDriverState",
++ sizeof(virNetcfDriverState),
++ virNetcfDriverStateDispose)))
++ return -1;
++ return 0;
++}
++
++VIR_ONCE_GLOBAL_INIT(virNetcfDriverState)
++
++static virNetcfDriverStatePtr driverState = NULL;
++
++
++static void
++virNetcfDriverStateDispose(void *obj)
+ {
+- virMutexLock(&driver->lock);
++ virNetcfDriverStatePtr driver = obj;
++
++ if (driver->netcf)
++ ncf_close(driver->netcf);
++}
++
++
++static int
++netcfStateInitialize(bool privileged ATTRIBUTE_UNUSED,
++ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
++ void *opaque ATTRIBUTE_UNUSED)
++{
++ if (virNetcfDriverStateInitialize() < 0)
++ return -1;
++
++ if (!(driverState = virObjectLockableNew(virNetcfDriverStateClass)))
++ return -1;
++
++ /* open netcf */
++ if (ncf_init(&driverState->netcf, NULL) != 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("failed to initialize netcf"));
++ virObjectUnref(driverState);
++ driverState = NULL;
++ return -1;
++ }
++ return 0;
+ }
+
+-static void interfaceDriverUnlock(virNetcfDriverStatePtr driver)
++
++static int
++netcfStateCleanup(void)
+ {
+- virMutexUnlock(&driver->lock);
++ if (!driverState) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Attempt to close netcf state driver already closed"));
++ return -1;
++ }
++
++ if (virObjectUnref(driverState)) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Attempt to close netcf state driver "
++ "with open connections"));
++ return -1;
++ }
++ driverState = NULL;
++ return 0;
+ }
+
++
++static int
++netcfStateReload(void)
++{
++ int ret = -1;
++
++ if (!driverState)
++ return 0;
++
++ virObjectLock(driverState);
++ ncf_close(driverState->netcf);
++ if (ncf_init(&driverState->netcf, NULL) != 0)
++ {
++ /* this isn't a good situation, because we can't shut down the
++ * driver as there may still be connections to it. If we set
++ * the netcf handle to NULL, any subsequent calls to netcf
++ * will just fail rather than causing a crash. Not ideal, but
++ * livable (since this should never happen).
++ */
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("failed to re-init netcf"));
++ driverState->netcf = NULL;
++ goto cleanup;
++ }
++
++ ret = 0;
++cleanup:
++ virObjectUnlock(driverState);
++
++ return ret;
++}
++
++
+ /*
+ * Get a minimal virInterfaceDef containing enough metadata
+ * for access control checks to be performed. Currently
+@@ -148,61 +241,30 @@ static struct netcf_if *interfaceDriverGetNetcfIF(struct netcf *ncf, virInterfac
+ return iface;
+ }
+
+-static virDrvOpenStatus netcfInterfaceOpen(virConnectPtr conn,
+- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+- unsigned int flags)
++static virDrvOpenStatus
++netcfInterfaceOpen(virConnectPtr conn,
++ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
++ unsigned int flags)
+ {
+- virNetcfDriverStatePtr driverState;
+-
+ virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+- if (VIR_ALLOC(driverState) < 0)
+- goto alloc_error;
+-
+- /* initialize non-0 stuff in driverState */
+- if (virMutexInit(&driverState->lock) < 0)
+- {
+- /* what error to report? */
+- goto mutex_error;
+- }
+-
+- /* open netcf */
+- if (ncf_init(&driverState->netcf, NULL) != 0)
+- {
+- /* what error to report? */
+- goto netcf_error;
+- }
++ if (!driverState)
++ return VIR_DRV_OPEN_ERROR;
+
++ virObjectRef(driverState);
+ conn->interfacePrivateData = driverState;
+ return VIR_DRV_OPEN_SUCCESS;
+-
+-netcf_error:
+- if (driverState->netcf)
+- {
+- ncf_close(driverState->netcf);
+- }
+- virMutexDestroy(&driverState->lock);
+-mutex_error:
+- VIR_FREE(driverState);
+-alloc_error:
+- return VIR_DRV_OPEN_ERROR;
+ }
+
+-static int netcfInterfaceClose(virConnectPtr conn)
++static int
++netcfInterfaceClose(virConnectPtr conn)
+ {
+
+ if (conn->interfacePrivateData != NULL)
+ {
+- virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+-
+- /* close netcf instance */
+- ncf_close(driver->netcf);
+- /* destroy lock */
+- virMutexDestroy(&driver->lock);
+- /* free driver state */
+- VIR_FREE(driver);
++ virObjectUnref(conn->interfacePrivateData);
++ conn->interfacePrivateData = NULL;
+ }
+- conn->interfacePrivateData = NULL;
+ return 0;
+ }
+
+@@ -408,11 +470,11 @@ static int netcfConnectNumOfInterfaces(virConnectPtr conn)
+ if (virConnectNumOfInterfacesEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ count = netcfConnectNumOfInterfacesImpl(conn,
+ NETCF_IFACE_ACTIVE,
+ virConnectNumOfInterfacesCheckACL);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return count;
+ }
+
+@@ -424,12 +486,12 @@ static int netcfConnectListInterfaces(virConnectPtr conn, char **const names, in
+ if (virConnectListInterfacesEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ count = netcfConnectListInterfacesImpl(conn,
+ NETCF_IFACE_ACTIVE,
+ names, nnames,
+ virConnectListInterfacesCheckACL);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return count;
+
+ }
+@@ -442,11 +504,11 @@ static int netcfConnectNumOfDefinedInterfaces(virConnectPtr conn)
+ if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ count = netcfConnectNumOfInterfacesImpl(conn,
+ NETCF_IFACE_INACTIVE,
+ virConnectNumOfDefinedInterfacesCheckACL);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return count;
+ }
+
+@@ -458,12 +520,12 @@ static int netcfConnectListDefinedInterfaces(virConnectPtr conn, char **const na
+ if (virConnectListDefinedInterfacesEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ count = netcfConnectListInterfacesImpl(conn,
+ NETCF_IFACE_INACTIVE,
+ names, nnames,
+ virConnectListDefinedInterfacesCheckACL);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return count;
+
+ }
+@@ -490,7 +552,7 @@ netcfConnectListAllInterfaces(virConnectPtr conn,
+ if (virConnectListAllInterfacesEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ /* List all interfaces, in case of we might support new filter flags
+ * except active|inactive in future.
+@@ -621,7 +683,7 @@ cleanup:
+ VIR_FREE(tmp_iface_objs);
+ }
+
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -634,7 +696,7 @@ static virInterfacePtr netcfInterfaceLookupByName(virConnectPtr conn,
+ virInterfacePtr ret = NULL;
+ virInterfaceDefPtr def = NULL;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ iface = ncf_lookup_by_name(driver->netcf, name);
+ if (!iface) {
+ const char *errmsg, *details;
+@@ -662,7 +724,7 @@ static virInterfacePtr netcfInterfaceLookupByName(virConnectPtr conn,
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -675,7 +737,7 @@ static virInterfacePtr netcfInterfaceLookupByMACString(virConnectPtr conn,
+ virInterfacePtr ret = NULL;
+ virInterfaceDefPtr def = NULL;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+ niface = ncf_lookup_by_mac_string(driver->netcf, macstr, 1, &iface);
+
+ if (niface < 0) {
+@@ -711,7 +773,7 @@ static virInterfacePtr netcfInterfaceLookupByMACString(virConnectPtr conn,
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -726,7 +788,7 @@ static char *netcfInterfaceGetXMLDesc(virInterfacePtr ifinfo,
+
+ virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ iface = interfaceDriverGetNetcfIF(driver->netcf, ifinfo);
+ if (!iface) {
+@@ -768,7 +830,7 @@ cleanup:
+ ncf_if_free(iface);
+ VIR_FREE(xmlstr);
+ virInterfaceDefFree(ifacedef);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -784,7 +846,7 @@ static virInterfacePtr netcfInterfaceDefineXML(virConnectPtr conn,
+
+ virCheckFlags(0, NULL);
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ ifacedef = virInterfaceDefParseString(xml);
+ if (!ifacedef) {
+@@ -818,7 +880,7 @@ cleanup:
+ ncf_if_free(iface);
+ VIR_FREE(xmlstr);
+ virInterfaceDefFree(ifacedef);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -828,7 +890,7 @@ static int netcfInterfaceUndefine(virInterfacePtr ifinfo) {
+ virInterfaceDefPtr def = NULL;
+ int ret = -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ iface = interfaceDriverGetNetcfIF(driver->netcf, ifinfo);
+ if (!iface) {
+@@ -857,7 +919,7 @@ static int netcfInterfaceUndefine(virInterfacePtr ifinfo) {
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -871,7 +933,7 @@ static int netcfInterfaceCreate(virInterfacePtr ifinfo,
+
+ virCheckFlags(0, -1);
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ iface = interfaceDriverGetNetcfIF(driver->netcf, ifinfo);
+ if (!iface) {
+@@ -900,7 +962,7 @@ static int netcfInterfaceCreate(virInterfacePtr ifinfo,
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -914,7 +976,7 @@ static int netcfInterfaceDestroy(virInterfacePtr ifinfo,
+
+ virCheckFlags(0, -1);
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ iface = interfaceDriverGetNetcfIF(driver->netcf, ifinfo);
+ if (!iface) {
+@@ -943,7 +1005,7 @@ static int netcfInterfaceDestroy(virInterfacePtr ifinfo,
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -955,7 +1017,7 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo)
+ virInterfaceDefPtr def = NULL;
+ int ret = -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ iface = interfaceDriverGetNetcfIF(driver->netcf, ifinfo);
+ if (!iface) {
+@@ -985,7 +1047,7 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo)
+ cleanup:
+ ncf_if_free(iface);
+ virInterfaceDefFree(def);
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -1000,7 +1062,7 @@ static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
+ if (virInterfaceChangeBeginEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ ret = ncf_change_begin(driver->netcf, 0);
+ if (ret < 0) {
+@@ -1012,7 +1074,7 @@ static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
+ details ? details : "");
+ }
+
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -1026,7 +1088,7 @@ static int netcfInterfaceChangeCommit(virConnectPtr conn, unsigned int flags)
+ if (virInterfaceChangeCommitEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ ret = ncf_change_commit(driver->netcf, 0);
+ if (ret < 0) {
+@@ -1038,7 +1100,7 @@ static int netcfInterfaceChangeCommit(virConnectPtr conn, unsigned int flags)
+ details ? details : "");
+ }
+
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+
+@@ -1052,7 +1114,7 @@ static int netcfInterfaceChangeRollback(virConnectPtr conn, unsigned int flags)
+ if (virInterfaceChangeRollbackEnsureACL(conn) < 0)
+ return -1;
+
+- interfaceDriverLock(driver);
++ virObjectLock(driver);
+
+ ret = ncf_change_rollback(driver->netcf, 0);
+ if (ret < 0) {
+@@ -1064,13 +1126,13 @@ static int netcfInterfaceChangeRollback(virConnectPtr conn, unsigned int flags)
+ details ? details : "");
+ }
+
+- interfaceDriverUnlock(driver);
++ virObjectUnlock(driver);
+ return ret;
+ }
+ #endif /* HAVE_NETCF_TRANSACTIONS */
+
+ static virInterfaceDriver interfaceDriver = {
+- "netcf",
++ .name = INTERFACE_DRIVER_NAME,
+ .interfaceOpen = netcfInterfaceOpen, /* 0.7.0 */
+ .interfaceClose = netcfInterfaceClose, /* 0.7.0 */
+ .connectNumOfInterfaces = netcfConnectNumOfInterfaces, /* 0.7.0 */
+@@ -1093,11 +1155,19 @@ static virInterfaceDriver interfaceDriver = {
+ #endif /* HAVE_NETCF_TRANSACTIONS */
+ };
+
++static virStateDriver interfaceStateDriver = {
++ .name = INTERFACE_DRIVER_NAME,
++ .stateInitialize = netcfStateInitialize,
++ .stateCleanup = netcfStateCleanup,
++ .stateReload = netcfStateReload,
++};
++
+ int netcfIfaceRegister(void) {
+ if (virRegisterInterfaceDriver(&interfaceDriver) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to register netcf interface driver"));
+ return -1;
+ }
++ virRegisterStateDriver(&interfaceStateDriver);
+ return 0;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From e3be969238c715142642a1429630f2f0bcb5b293 Mon Sep 17 00:00:00 2001
+Message-Id: <e3be969238c715142642a1429630f2f0bcb5b293.1383922565.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Wed, 6 Nov 2013 04:47:59 -0700
+Subject: [PATCH] network: fix connections count in case of allocate failure
+
+This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1020135
+
+If networkAllocateActualDevice() had failed due to a pool of hostdev
+or direct devices being depleted, the calling function could still
+call networkReleaseActualDevice() as part of its cleanup, and that
+function would then unconditionally decrement the connections count
+for the network, even though it hadn't been incremented (due to
+failure of allocate). This *was* necessary because the .actual member
+of the netdef was allocated with a "lazy" algorithm, only being
+created if there was a need to store data there (e.g. if a device was
+allocated from a pool, or bandwidth was allocated for the device), so
+there was no simple way for networkReleaseActualDevice() to tell if
+something really had been allocated (i.e. if "connections++" had been
+executed).
+
+This patch changes networkAllocateDevice() to *always* allocate an
+actual device for any netdef of type='network', even if it isn't
+needed for any other reason. This has no ill effects anywhere else in
+the code (except for using a small amount of memory), and
+networkReleaseActualDevice() can then determine if there was a
+previous successful allocate by checking for .actual != NULL (if not,
+it skips the "connections--").
+
+(cherry picked from commit b4e0299d4ff059c8707a760b7ec2063ccd57cc21)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/network/bridge_driver.c | 41 +++++++++++------------------------------
+ 1 file changed, 11 insertions(+), 30 deletions(-)
+
+diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
+index ea09663..c900478 100644
+--- a/src/network/bridge_driver.c
++++ b/src/network/bridge_driver.c
+@@ -3841,6 +3841,9 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ }
+ netdef = network->def;
+
++ if (VIR_ALLOC(iface->data.network.actual) < 0)
++ goto error;
++
+ /* portgroup can be present for any type of network, in particular
+ * for bandwidth information, so we need to check for that and
+ * fill it in appropriately for all forward types.
+@@ -3857,14 +3860,9 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ else if (portgroup && portgroup->bandwidth)
+ bandwidth = portgroup->bandwidth;
+
+- if (bandwidth) {
+- if (!iface->data.network.actual &&
+- VIR_ALLOC(iface->data.network.actual) < 0)
+- goto error;
+- if (virNetDevBandwidthCopy(&iface->data.network.actual->bandwidth,
+- bandwidth) < 0)
+- goto error;
+- }
++ if (bandwidth && virNetDevBandwidthCopy(&iface->data.network.actual->bandwidth,
++ bandwidth) < 0)
++ goto error;
+
+ /* copy appropriate vlan info to actualNet */
+ if (iface->vlan.nTags > 0)
+@@ -3874,13 +3872,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ else if (netdef->vlan.nTags > 0)
+ vlan = &netdef->vlan;
+
+- if (vlan) {
+- if (!iface->data.network.actual &&
+- VIR_ALLOC(iface->data.network.actual) < 0)
+- goto error;
+- if (virNetDevVlanCopy(&iface->data.network.actual->vlan, vlan) < 0)
+- goto error;
+- }
++ if (vlan && virNetDevVlanCopy(&iface->data.network.actual->vlan, vlan) < 0)
++ goto error;
+
+ if ((netdef->forward.type == VIR_NETWORK_FORWARD_NONE) ||
+ (netdef->forward.type == VIR_NETWORK_FORWARD_NAT) ||
+@@ -3889,8 +3882,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ *NETWORK; we just keep the info from the portgroup in
+ * iface->data.network.actual
+ */
+- if (iface->data.network.actual)
+- iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
++ iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
+
+ if (networkPlugBandwidth(network, iface) < 0)
+ goto error;
+@@ -3902,10 +3894,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ * is VIR_DOMAIN_NET_TYPE_BRIDGE
+ */
+
+- if (!iface->data.network.actual &&
+- VIR_ALLOC(iface->data.network.actual) < 0)
+- goto error;
+-
+ iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_BRIDGE;
+ if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
+ netdef->bridge) < 0)
+@@ -3938,10 +3926,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+
+ virDomainHostdevSubsysPciBackendType backend;
+
+- if (!iface->data.network.actual &&
+- VIR_ALLOC(iface->data.network.actual) < 0)
+- goto error;
+-
+ iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_HOSTDEV;
+ if (netdef->forward.npfs > 0 && netdef->forward.nifs <= 0 &&
+ networkCreateInterfacePool(netdef) < 0) {
+@@ -4025,10 +4009,6 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
+ * VIR_DOMAIN_NET_TYPE_DIRECT.
+ */
+
+- if (!iface->data.network.actual &&
+- VIR_ALLOC(iface->data.network.actual) < 0)
+- goto error;
+-
+ /* Set type=direct and appropriate <source mode='xxx'/> */
+ iface->data.network.actual->type = actualType = VIR_DOMAIN_NET_TYPE_DIRECT;
+ switch (netdef->forward.type) {
+@@ -4503,7 +4483,8 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
+ }
+
+ success:
+- netdef->connections--;
++ if (iface->data.network.actual)
++ netdef->connections--;
+ VIR_DEBUG("Releasing network %s, %d connections",
+ netdef->name, netdef->connections);
+ ret = 0;
+--
+1.8.4.2
+
--- /dev/null
+From 7567ea478b7235bc19569c8da99a30b56af6473e Mon Sep 17 00:00:00 2001
+Message-Id: <7567ea478b7235bc19569c8da99a30b56af6473e.1381871412.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:23 +0100
+Subject: [PATCH] nwfilter: Don't fail to start if DBus isn't available
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=927072
+
+When the daemon is compiled with firewalld support but the DBus message
+bus isn't started in the system, the initialization of the nwfilter
+driver fails even if there are fallback options.
+
+(cherry picked from commit e0e61b4cf75f246b9bc50452a307e1e4d996df4c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/nwfilter/nwfilter_driver.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
+index ce75c82..d25c6f2 100644
+--- a/src/nwfilter/nwfilter_driver.c
++++ b/src/nwfilter/nwfilter_driver.c
+@@ -175,7 +175,8 @@ nwfilterStateInitialize(bool privileged,
+ DBusConnection *sysbus = NULL;
+
+ #if WITH_DBUS
+- sysbus = virDBusGetSystemBus();
++ if (virDBusHasSystemBus())
++ sysbus = virDBusGetSystemBus();
+ #endif /* WITH_DBUS */
+
+ if (VIR_ALLOC(driverState) < 0)
+@@ -184,6 +185,7 @@ nwfilterStateInitialize(bool privileged,
+ if (virMutexInit(&driverState->lock) < 0)
+ goto err_free_driverstate;
+
++ /* remember that we are going to use firewalld */
+ driverState->watchingFirewallD = (sysbus != NULL);
+ driverState->privileged = privileged;
+
+@@ -209,7 +211,8 @@ nwfilterStateInitialize(bool privileged,
+ * startup the DBus late so we don't get a reload signal while
+ * initializing
+ */
+- if (nwfilterDriverInstallDBusMatches(sysbus) < 0) {
++ if (sysbus &&
++ nwfilterDriverInstallDBusMatches(sysbus) < 0) {
+ VIR_ERROR(_("DBus matches could not be installed. Disabling nwfilter "
+ "driver"));
+ /*
+@@ -217,6 +220,8 @@ nwfilterStateInitialize(bool privileged,
+ * may have caused the ebiptables driver to use the firewall tool
+ * but now that the watches don't work, we just disable the nwfilter
+ * driver
++ *
++ * This may only happen if the system bus is available.
+ */
+ goto error;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 025c32f0b7f6f968e1b33442b68c2e65e11bc43f Mon Sep 17 00:00:00 2001
+Message-Id: <025c32f0b7f6f968e1b33442b68c2e65e11bc43f.1383922565.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 8 Nov 2013 05:42:33 -0700
+Subject: [PATCH] pci: properly handle out-of-order SRIOV virtual functions
+
+This resolves:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1025397
+
+When virPCIGetVirtualFunctions created the list of an SRIOV Physical
+Function's (PF) Virtual Functions (VF), it had assumed that the order
+of "virtfn*" links returned by readdir() from the PF's sysfs directory
+was already in the correct order. Experience has shown that this is
+not always the case - it can be in alphabetical order (which would
+e.g. place virtfn11 before virtfn2) or even some seemingly random
+order (see the example in the bugzilla report)
+
+This results in 1) incorrect assumptions made by consumers of the
+output of the virt_functions list of virsh nodedev-dumpxml, and 2)
+setting MAC address and vlan tag on the wrong VF (since libvirt uses
+netlink to set mac address and vlan tag, netlink requires the VF#, and
+the function virPCIGetVirtualFunctionIndex() returns the wrong index
+due to the improperly ordered VF list).
+
+The solution provided by this patch is for virPCIGetVirtualFunctions
+to no longer scan the entire device directory in its natural order,
+but instead to check for links individually by name "virtfn%d" where
+%d starts at 0 and increases with each success. Since VFs are created
+contiguously by the kernel, this will guarantee that all VFs are
+found, and placed in the arry in the correct order.
+
+One note of use to the uninitiated is that VIR_APPEND_ELEMENT always
+either increments *num_virtual_functions or fails, so no this isn't an
+endless loop.
+
+(NB: the SRIOV_* defines at the top of virpci.c were removed
+because they are unnecessary and/or not used.)
+
+(cherry picked from commit 88c1fcd5e7b6568fdb1a06e0d9001c37d5e1cb78)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virpci.c | 76 ++++++++++++++++++-------------------------------------
+ 1 file changed, 24 insertions(+), 52 deletions(-)
+
+diff --git a/src/util/virpci.c b/src/util/virpci.c
+index 87ea81b..39bbac8 100644
+--- a/src/util/virpci.c
++++ b/src/util/virpci.c
+@@ -49,10 +49,6 @@
+ #define PCI_ID_LEN 10 /* "XXXX XXXX" */
+ #define PCI_ADDR_LEN 13 /* "XXXX:XX:XX.X" */
+
+-#define SRIOV_FOUND 0
+-#define SRIOV_NOT_FOUND 1
+-#define SRIOV_ERROR -1
+-
+ struct _virPCIDevice {
+ unsigned int domain;
+ unsigned int bus;
+@@ -2379,6 +2375,7 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path,
+ return ret;
+ }
+
++
+ /*
+ * Returns virtual functions of a physical function
+ */
+@@ -2389,10 +2386,8 @@ virPCIGetVirtualFunctions(const char *sysfs_path,
+ {
+ int ret = -1;
+ size_t i;
+- DIR *dir = NULL;
+- struct dirent *entry = NULL;
+ char *device_link = NULL;
+- char errbuf[64];
++ virPCIDeviceAddress *config_addr = NULL;
+
+ VIR_DEBUG("Attempting to get SR IOV virtual functions for device"
+ "with sysfs path '%s'", sysfs_path);
+@@ -2400,65 +2395,42 @@ virPCIGetVirtualFunctions(const char *sysfs_path,
+ *virtual_functions = NULL;
+ *num_virtual_functions = 0;
+
+- dir = opendir(sysfs_path);
+- if (dir == NULL) {
+- memset(errbuf, '\0', sizeof(errbuf));
+- virReportSystemError(errno,
+- _("Failed to open dir '%s'"),
+- sysfs_path);
+- return ret;
+- }
+-
+- while ((entry = readdir(dir))) {
+- if (STRPREFIX(entry->d_name, "virtfn")) {
+- virPCIDeviceAddress *config_addr = NULL;
+-
+- if (virBuildPath(&device_link, sysfs_path, entry->d_name) == -1) {
+- virReportOOMError();
+- goto error;
+- }
++ do {
++ /* look for virtfn%d links until one isn't found */
++ if (virAsprintf(&device_link, "%s/virtfn%zu", sysfs_path, *num_virtual_functions) < 0)
++ goto error;
+
+- VIR_DEBUG("Number of virtual functions: %zu",
+- *num_virtual_functions);
++ if (!virFileExists(device_link))
++ break;
+
+- if (virPCIGetDeviceAddressFromSysfsLink(device_link,
+- &config_addr) !=
+- SRIOV_FOUND) {
+- VIR_WARN("Failed to get SRIOV function from device "
+- "link '%s'", device_link);
+- VIR_FREE(device_link);
+- continue;
+- }
++ if (virPCIGetDeviceAddressFromSysfsLink(device_link, &config_addr) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Failed to get SRIOV function from device link '%s'"),
++ device_link);
++ goto error;
++ }
+
+- if (VIR_REALLOC_N(*virtual_functions,
+- *num_virtual_functions + 1) < 0) {
+- VIR_FREE(config_addr);
+- goto error;
+- }
++ VIR_DEBUG("Found virtual function %zu", *num_virtual_functions);
++ if (VIR_APPEND_ELEMENT(*virtual_functions, *num_virtual_functions, config_addr) < 0)
++ goto error;
++ VIR_FREE(device_link);
+
+- (*virtual_functions)[*num_virtual_functions] = config_addr;
+- (*num_virtual_functions)++;
+- VIR_FREE(device_link);
+- }
+- }
++ } while (1);
+
+ ret = 0;
+-
+ cleanup:
+ VIR_FREE(device_link);
+- if (dir)
+- closedir(dir);
++ VIR_FREE(config_addr);
+ return ret;
+
+ error:
+- if (*virtual_functions) {
+- for (i = 0; i < *num_virtual_functions; i++)
+- VIR_FREE((*virtual_functions)[i]);
+- VIR_FREE(*virtual_functions);
+- }
++ for (i = 0; i < *num_virtual_functions; i++)
++ VIR_FREE((*virtual_functions)[i]);
++ VIR_FREE(*virtual_functions);
+ goto cleanup;
+ }
+
++
+ /*
+ * Returns 1 if vf device is a virtual function, 0 if not, -1 on error
+ */
+--
+1.8.4.2
+
--- /dev/null
+From 3abbed1a7393b4e59152bda1b37f67b8c440f5b6 Mon Sep 17 00:00:00 2001
+Message-Id: <3abbed1a7393b4e59152bda1b37f67b8c440f5b6.1378475168.git.jdenemar@redhat.com>
+From: Guan Qiang <hzguanqiang@corp.netease.com>
+Date: Wed, 4 Sep 2013 13:09:49 -0600
+Subject: [PATCH] python: Fix a PyList usage mistake
+
+7.0: https://bugzilla.redhat.com/show_bug.cgi?id=1002558
+
+Fix PyList usage mistake in Function libvirt_lxc_virDomainLxcOpenNamespace.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1002383
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit c26181495f3c98870d0794052246718f5d3d8dd6)
+---
+ python/libvirt-lxc-override.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/python/libvirt-lxc-override.c b/python/libvirt-lxc-override.c
+index 03bf2df..f76ff4b 100644
+--- a/python/libvirt-lxc-override.c
++++ b/python/libvirt-lxc-override.c
+@@ -80,7 +80,7 @@ libvirt_lxc_virDomainLxcOpenNamespace(PyObject *self ATTRIBUTE_UNUSED,
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+- py_retval = PyList_New(c_retval);
++ py_retval = PyList_New(0);
+ for (i = 0; i < c_retval; i++) {
+ PyObject *item = NULL;
+
+--
+1.8.3.2
+
--- /dev/null
+From 8d2d51fab95e51c9e4625ef4f5424db2f6a548eb Mon Sep 17 00:00:00 2001
+Message-Id: <8d2d51fab95e51c9e4625ef4f5424db2f6a548eb.1383922566.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:31 +0100
+Subject: [PATCH] qemu: Add monitor APIs to fetch CPUID data from QEMU
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+The qemu monitor supports retrieval of actual CPUID bits presented to
+the guest using QMP monitor. Add APIs to extract these information and
+tests for them.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 3afde0756ff1b87912f36268fd80617c34f1164a)
+
+ Conflicts:
+ tests/qemumonitorjsontest.c: recent changes to the testsuite changed
+ arguments for virTestRun and instantiation of the monitor test
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_monitor.c | 31 +++++
+ src/qemu/qemu_monitor.h | 4 +
+ src/qemu/qemu_monitor_json.c | 133 +++++++++++++++++++++
+ src/qemu/qemu_monitor_json.h | 2 +
+ tests/Makefile.am | 1 +
+ .../qemumonitorjson-getcpu-full.data | 5 +
+ .../qemumonitorjson-getcpu-full.json | 46 +++++++
+ .../qemumonitorjson-getcpu-host.data | 6 +
+ .../qemumonitorjson-getcpu-host.json | 45 +++++++
+ tests/qemumonitorjsontest.c | 75 ++++++++++++
+ 10 files changed, 348 insertions(+)
+ create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
+ create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json
+ create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
+ create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index cf4f954..4384ab4 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -3922,3 +3922,34 @@ qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd)
+
+ return 0;
+ }
++
++
++/**
++ * qemuMonitorJSONGetGuestCPU:
++ * @mon: Pointer to the monitor
++ * @arch: arch of the guest
++ *
++ * Retrieve the definition of the guest CPU from a running qemu instance.
++ *
++ * Returns the cpu definition object. On error returns NULL.
++ */
++virCPUDataPtr
++qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
++ virArch arch)
++{
++ VIR_DEBUG("mon=%p, arch='%s'", mon, virArchToString(arch));
++
++ if (!mon) {
++ virReportError(VIR_ERR_INVALID_ARG, "%s",
++ _("monitor must not be NULL"));
++ return NULL;
++ }
++
++ if (!mon->json) {
++ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
++ _("JSON monitor is required"));
++ return NULL;
++ }
++
++ return qemuMonitorJSONGetGuestCPU(mon, arch);
++}
+diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
+index 85ae533..3e113f3 100644
+--- a/src/qemu/qemu_monitor.h
++++ b/src/qemu/qemu_monitor.h
+@@ -32,6 +32,7 @@
+ # include "virhash.h"
+ # include "virjson.h"
+ # include "device_conf.h"
++# include "cpu/cpu.h"
+
+ typedef struct _qemuMonitor qemuMonitor;
+ typedef qemuMonitor *qemuMonitorPtr;
+@@ -719,6 +720,9 @@ int qemuMonitorGetDeviceAliases(qemuMonitorPtr mon,
+
+ int qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd);
+
++virCPUDataPtr qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
++ virArch arch);
++
+ /**
+ * When running two dd process and using <> redirection, we need a
+ * shell that will not truncate files. These two strings serve that
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index 12f7e69..ef5c08a 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -42,6 +42,7 @@
+ #include "virerror.h"
+ #include "virjson.h"
+ #include "virstring.h"
++#include "cpu/cpu_x86.h"
+
+ #ifdef WITH_DTRACE_PROBES
+ # include "libvirt_qemu_probes.h"
+@@ -49,6 +50,7 @@
+
+ #define VIR_FROM_THIS VIR_FROM_QEMU
+
++#define QOM_CPU_PATH "/machine/unattached/device[0]"
+
+ #define LINE_ENDING "\r\n"
+
+@@ -5453,3 +5455,134 @@ cleanup:
+ VIR_FREE(paths);
+ return ret;
+ }
++
++
++static int
++qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
++ virCPUx86CPUID *cpuid)
++{
++ const char *reg;
++ unsigned long long fun;
++ unsigned long long features;
++
++ memset(cpuid, 0, sizeof(*cpuid));
++
++ if (!(reg = virJSONValueObjectGetString(data, "cpuid-register"))) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("missing cpuid-register in CPU data"));
++ return -1;
++ }
++ if (virJSONValueObjectGetNumberUlong(data, "cpuid-input-eax", &fun) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("missing or invalid cpuid-input-eax in CPU data"));
++ return -1;
++ }
++ if (virJSONValueObjectGetNumberUlong(data, "features", &features) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("missing or invalid features in CPU data"));
++ return -1;
++ }
++
++ cpuid->function = fun;
++ if (STREQ(reg, "EAX")) {
++ cpuid->eax = features;
++ } else if (STREQ(reg, "EBX")) {
++ cpuid->ebx = features;
++ } else if (STREQ(reg, "ECX")) {
++ cpuid->ecx = features;
++ } else if (STREQ(reg, "EDX")) {
++ cpuid->edx = features;
++ } else {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("unknown CPU register '%s'"), reg);
++ return -1;
++ }
++
++ return 0;
++}
++
++
++static virCPUDataPtr
++qemuMonitorJSONGetCPUx86Data(qemuMonitorPtr mon,
++ const char *property)
++{
++ virJSONValuePtr cmd;
++ virJSONValuePtr reply = NULL;
++ virJSONValuePtr data;
++ virCPUx86Data *x86Data = NULL;
++ virCPUx86CPUID cpuid;
++ size_t i;
++ virCPUDataPtr ret = NULL;
++ int n;
++
++ if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
++ "s:path", QOM_CPU_PATH,
++ "s:property", property,
++ NULL)))
++ return NULL;
++
++ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
++ goto cleanup;
++
++ if (qemuMonitorJSONCheckError(cmd, reply))
++ goto cleanup;
++
++ if (!(data = virJSONValueObjectGet(reply, "return"))) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("qom-get reply was missing return data"));
++ goto cleanup;
++ }
++
++ if ((n = virJSONValueArraySize(data)) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("%s CPU property did not return an array"),
++ property);
++ goto cleanup;
++ }
++
++ if (VIR_ALLOC(x86Data) < 0)
++ goto cleanup;
++
++ for (i = 0; i < n; i++) {
++ if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
++ &cpuid) < 0 ||
++ virCPUx86DataAddCPUID(x86Data, &cpuid) < 0)
++ goto cleanup;
++ }
++
++ if (!(ret = virCPUx86MakeData(VIR_ARCH_X86_64, &x86Data)))
++ goto cleanup;
++
++cleanup:
++ virJSONValueFree(cmd);
++ virJSONValueFree(reply);
++ virCPUx86DataFree(x86Data);
++ return ret;
++}
++
++
++/**
++ * qemuMonitorJSONGetGuestCPU:
++ * @mon: Pointer to the monitor
++ * @arch: arch of the guest
++ *
++ * Retrieve the definition of the guest CPU from a running qemu instance.
++ *
++ * Returns the cpu definition object. On error returns NULL.
++ */
++virCPUDataPtr
++qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
++ virArch arch)
++{
++ switch (arch) {
++ case VIR_ARCH_X86_64:
++ case VIR_ARCH_I686:
++ return qemuMonitorJSONGetCPUx86Data(mon, "feature-words");
++
++ default:
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("CPU definition retrieval isn't supported for '%s'"),
++ virArchToString(arch));
++ return NULL;
++ }
++}
+diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
+index 51cf19c..2fdc28f 100644
+--- a/src/qemu/qemu_monitor_json.h
++++ b/src/qemu/qemu_monitor_json.h
+@@ -29,6 +29,7 @@
+
+ # include "qemu_monitor.h"
+ # include "virbitmap.h"
++# include "cpu/cpu.h"
+
+ int qemuMonitorJSONIOProcess(qemuMonitorPtr mon,
+ const char *data,
+@@ -426,4 +427,5 @@ int qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon,
+ int qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon,
+ char ***aliases);
+
++virCPUDataPtr qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon, virArch arch);
+ #endif /* QEMU_MONITOR_JSON_H */
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index b794005..d095595 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -82,6 +82,7 @@ EXTRA_DIST = \
+ oomtrace.pl \
+ qemuhelpdata \
+ qemuhotplugtestdata \
++ qemumonitorjsondata \
+ qemuxml2argvdata \
+ qemuxml2xmloutdata \
+ qemuxmlnsdata \
+diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
+new file mode 100644
+index 0000000..bba8d31
+--- /dev/null
++++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
+@@ -0,0 +1,5 @@
++<cpudata arch='x86'>
++ <cpuid function='0x00000001' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x078bfbfd'/>
++ <cpuid function='0x40000001' eax='0x0100003b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++ <cpuid function='0x80000001' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/>
++</cpudata>
+diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json
+new file mode 100644
+index 0000000..29c00b4
+--- /dev/null
++++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json
+@@ -0,0 +1,46 @@
++{
++ "return": [
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 2147483658,
++ "features": 0
++ },
++ {
++ "cpuid-register": "EAX",
++ "cpuid-input-eax": 1073741825,
++ "features": 16777275
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 3221225473,
++ "features": 0
++ },
++ {
++ "cpuid-register": "ECX",
++ "cpuid-input-eax": 2147483649,
++ "features": 1
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 2147483649,
++ "features": 672139264
++ },
++ {
++ "cpuid-register": "EBX",
++ "cpuid-input-ecx": 0,
++ "cpuid-input-eax": 7,
++ "features": 0
++ },
++ {
++ "cpuid-register": "ECX",
++ "cpuid-input-eax": 1,
++ "features": 2545558051
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 1,
++ "features": 126614525
++ }
++ ],
++ "id": "libvirt-6"
++}
+diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
+new file mode 100644
+index 0000000..98b9e7c
+--- /dev/null
++++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
+@@ -0,0 +1,6 @@
++<cpudata arch='x86'>
++ <cpuid function='0x00000001' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2223' edx='0x0f8bfbff'/>
++ <cpuid function='0x00000007' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/>
++ <cpuid function='0x40000001' eax='0x0100007b' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++ <cpuid function='0x80000001' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2993fbff'/>
++</cpudata>
+diff --git a/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json
+new file mode 100644
+index 0000000..b5fb9f3
+--- /dev/null
++++ b/tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json
+@@ -0,0 +1,45 @@
++{
++ "return": [
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 2147483658,
++ "features": 0
++ },
++ {
++ "cpuid-register": "EAX",
++ "cpuid-input-eax": 1073741825,
++ "features": 16777339
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 3221225473,
++ "features": 0
++ },
++ {
++ "cpuid-register": "ECX",
++ "cpuid-input-eax": 2147483649,
++ "features": 1
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 2147483649,
++ "features": 697564159
++ },
++ {
++ "cpuid-register": "EBX",
++ "cpuid-input-ecx": 0,
++ "cpuid-input-eax": 7,
++ "features": 2
++ },
++ {
++ "cpuid-register": "ECX",
++ "cpuid-input-eax": 1,
++ "features": 2545558051
++ },
++ {
++ "cpuid-register": "EDX",
++ "cpuid-input-eax": 1,
++ "features": 260832255
++ }
++ ]
++}
+diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
+index 9e66059..f709de7 100644
+--- a/tests/qemumonitorjsontest.c
++++ b/tests/qemumonitorjsontest.c
+@@ -27,6 +27,7 @@
+ #include "virthread.h"
+ #include "virerror.h"
+ #include "virstring.h"
++#include "cpu/cpu.h"
+
+
+ #define VIR_FROM_THIS VIR_FROM_NONE
+@@ -943,6 +944,69 @@ cleanup:
+ }
+
+
++
++struct testCPUData {
++ const char *name;
++ virDomainXMLOptionPtr xmlopt;
++};
++
++
++static int
++testQemuMonitorJSONGetCPUData(const void *opaque)
++{
++ const struct testCPUData *data = opaque;
++ qemuMonitorTestPtr test = qemuMonitorTestNew(true, data->xmlopt);
++ virCPUDataPtr cpuData = NULL;
++ char *jsonFile = NULL;
++ char *dataFile = NULL;
++ char *jsonStr = NULL;
++ char *expected = NULL;
++ char *actual = NULL;
++ int ret = -1;
++
++ if (!test)
++ return -1;
++
++ if (virAsprintf(&jsonFile,
++ "%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.json",
++ abs_srcdir, data->name) < 0 ||
++ virAsprintf(&dataFile,
++ "%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.data",
++ abs_srcdir, data->name) < 0)
++ goto cleanup;
++
++ if (virtTestLoadFile(jsonFile, &jsonStr) < 0 ||
++ virtTestLoadFile(dataFile, &expected) < 0)
++ goto cleanup;
++
++ if (qemuMonitorTestAddItem(test, "qom-get", jsonStr) < 0)
++ goto cleanup;
++
++ if (!(cpuData = qemuMonitorJSONGetGuestCPU(qemuMonitorTestGetMonitor(test),
++ VIR_ARCH_X86_64)))
++ goto cleanup;
++
++ if (!(actual = cpuDataFormat(cpuData)))
++ goto cleanup;
++
++ if (STRNEQ(expected, actual)) {
++ virtTestDifference(stderr, expected, actual);
++ goto cleanup;
++ }
++
++ ret = 0;
++cleanup:
++ VIR_FREE(jsonFile);
++ VIR_FREE(dataFile);
++ VIR_FREE(jsonStr);
++ VIR_FREE(expected);
++ VIR_FREE(actual);
++ cpuDataFree(cpuData);
++ qemuMonitorTestFree(test);
++ return ret;
++}
++
++
+ static int
+ mymain(void)
+ {
+@@ -964,6 +1028,14 @@ mymain(void)
+ if (virtTestRun(# name, 1, testQemuMonitorJSON ## name, xmlopt) < 0) \
+ ret = -1
+
++#define DO_TEST_CPU_DATA(name) \
++ do { \
++ struct testCPUData data = { name, xmlopt }; \
++ const char *label = "GetCPUData(" name ")"; \
++ if (virtTestRun(label, 1, testQemuMonitorJSONGetCPUData, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
+ DO_TEST(GetStatus);
+ DO_TEST(GetVersion);
+ DO_TEST(GetMachines);
+@@ -978,6 +1050,9 @@ mymain(void)
+ DO_TEST(SetObjectProperty);
+ DO_TEST(GetDeviceAliases);
+
++ DO_TEST_CPU_DATA("host");
++ DO_TEST_CPU_DATA("full");
++
+ virObjectUnref(xmlopt);
+
+ return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+--
+1.8.4.2
+
--- /dev/null
+From d1026b0bd63883eb1d992963559ef645f634c8fa Mon Sep 17 00:00:00 2001
+Message-Id: <d1026b0bd63883eb1d992963559ef645f634c8fa.1383922567.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:34 +0100
+Subject: [PATCH] qemu: Add support for paravirtual spinlocks in the guest
+
+The linux kernel recently added support for paravirtual spinlock
+handling to avoid performance regressions on overcomitted hosts. This
+feature needs to be turned in the hypervisor so that the guest OS is
+notified about the possible support.
+
+This patch adds a new feature "paravirt-spinlock" to the XML and
+supporting code to enable the "kvm_pv_unhalt" pseudo CPU feature in
+qemu.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+(cherry picked from commit e0dc851164d57f26ec10ceed022fe913f76ba24c)
+
+ Conflicts:
+ tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args:
+ tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args:
+ commit a216e6487255d not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/formatdomain.html.in | 8 +++++
+ docs/schemas/domaincommon.rng | 10 +++++-
+ src/conf/domain_conf.c | 36 +++++++++++++++++++++-
+ src/conf/domain_conf.h | 1 +
+ src/qemu/qemu_command.c | 13 ++++++++
+ .../qemuxml2argv-pv-spinlock-disabled.args | 5 +++
+ .../qemuxml2argv-pv-spinlock-disabled.xml | 26 ++++++++++++++++
+ .../qemuxml2argv-pv-spinlock-enabled.args | 5 +++
+ .../qemuxml2argv-pv-spinlock-enabled.xml | 26 ++++++++++++++++
+ tests/qemuxml2argvtest.c | 2 ++
+ tests/qemuxml2xmltest.c | 2 ++
+ 11 files changed, 132 insertions(+), 2 deletions(-)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 132c16c..913c011 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -1191,6 +1191,7 @@
+ <vapic state='on'/>
+ <spinlocks state='on' retries='4096'</spinlocks>
+ </hyperv>
++ <pvspinlock/>
+
+ </features>
+ ...</pre>
+@@ -1262,6 +1263,13 @@
+ </tr>
+ </table>
+ </dd>
++ <dt><code>pvspinlock</code></dt>
++ <dd>Notify the guest that the host supports paravirtual spinlocks
++ for example by exposing the pvticketlocks mechanism. This feature
++ can be explicitly disabled by using <code>state='off'</code>
++ attribute.
++ </dd>
++
+ </dl>
+
+ <h3><a name="elementsTime">Time keeping</a></h3>
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 9563893..4e61d7c 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -3510,7 +3510,7 @@
+ </define>
+ <!--
+ A set of optional features: PAE, APIC, ACPI,
+- HyperV Enlightenment and HAP support
++ HyperV Enlightenment, paravirtual spinlocks and HAP support
+ -->
+ <define name="features">
+ <optional>
+@@ -3556,6 +3556,14 @@
+ <empty/>
+ </element>
+ </optional>
++ <optional>
++ <element name="pvspinlock">
++ <optional>
++ <ref name="featurestate"/>
++ </optional>
++ <empty/>
++ </element>
++ </optional>
+ </interleave>
+ </element>
+ </optional>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 6664c2a..57a82b6 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -142,7 +142,8 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
+ "hap",
+ "viridian",
+ "privnet",
+- "hyperv")
++ "hyperv",
++ "pvspinlock")
+
+ VIR_ENUM_IMPL(virDomainFeatureState, VIR_DOMAIN_FEATURE_STATE_LAST,
+ "default",
+@@ -11343,6 +11344,22 @@ virDomainDefParseXML(xmlDocPtr xml,
+ def->features[val] = VIR_DOMAIN_FEATURE_STATE_ON;
+ break;
+
++ case VIR_DOMAIN_FEATURE_PVSPINLOCK:
++ node = ctxt->node;
++ ctxt->node = nodes[i];
++ if ((tmp = virXPathString("string(./@state)", ctxt))) {
++ if ((def->features[val] = virDomainFeatureStateTypeFromString(tmp)) == -1) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++ _("unknown state atribute '%s' of feature '%s'"),
++ tmp, virDomainFeatureTypeToString(val));
++ goto error;
++ }
++ } else {
++ def->features[val] = VIR_DOMAIN_FEATURE_STATE_ON;
++ }
++ ctxt->node = node;
++ break;
++
+ case VIR_DOMAIN_FEATURE_LAST:
+ break;
+ }
+@@ -16706,6 +16723,23 @@ virDomainDefFormatInternal(virDomainDefPtr def,
+
+ break;
+
++ case VIR_DOMAIN_FEATURE_PVSPINLOCK:
++ switch ((enum virDomainFeatureState) def->features[i]) {
++ case VIR_DOMAIN_FEATURE_STATE_LAST:
++ case VIR_DOMAIN_FEATURE_STATE_DEFAULT:
++ break;
++
++ case VIR_DOMAIN_FEATURE_STATE_ON:
++ virBufferAsprintf(buf, " <%s state='on'/>\n", name);
++ break;
++
++ case VIR_DOMAIN_FEATURE_STATE_OFF:
++ virBufferAsprintf(buf, " <%s state='off'/>\n", name);
++ break;
++ }
++
++ break;
++
+ case VIR_DOMAIN_FEATURE_APIC:
+ if (def->features[i] == VIR_DOMAIN_FEATURE_STATE_ON) {
+ virBufferAddLit(buf, " <apic");
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 3d2b3a4..1d27ccd 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -1603,6 +1603,7 @@ enum virDomainFeature {
+ VIR_DOMAIN_FEATURE_VIRIDIAN,
+ VIR_DOMAIN_FEATURE_PRIVNET,
+ VIR_DOMAIN_FEATURE_HYPERV,
++ VIR_DOMAIN_FEATURE_PVSPINLOCK,
+
+ VIR_DOMAIN_FEATURE_LAST
+ };
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index f14b0f2..0d08852 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -6574,6 +6574,19 @@ qemuBuildCpuArgStr(const virQEMUDriverPtr driver,
+ have_cpu = true;
+ }
+
++ if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
++ char sign;
++ if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_DOMAIN_FEATURE_STATE_ON)
++ sign = '+';
++ else
++ sign = '-';
++
++ virBufferAsprintf(&buf, "%s,%ckvm_pv_unhalt",
++ have_cpu ? "" : default_model,
++ sign);
++ have_cpu = true;
++ }
++
+ if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_FEATURE_STATE_ON) {
+ if (!have_cpu) {
+ virBufferAdd(&buf, default_model, -1);
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
+new file mode 100644
+index 0000000..65c66ec
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
+@@ -0,0 +1,5 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
++/usr/bin/qemu -S -M pc \
++-cpu qemu32,-kvm_pv_unhalt -m 214 -smp 6 -nographic -monitor \
++unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial \
++none -parallel none
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
+new file mode 100644
+index 0000000..4820476
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
+@@ -0,0 +1,26 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static'>6</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='network'/>
++ </os>
++ <features>
++ <acpi/>
++ <pae/>
++ <pvspinlock state='off'/>
++ </features>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <controller type='usb' index='0'/>
++ <controller type='pci' index='0' model='pci-root'/>
++ <memballoon model='virtio'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
+new file mode 100644
+index 0000000..dc4cbe1
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
+@@ -0,0 +1,5 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
++/usr/bin/qemu -S -M pc \
++-cpu qemu32,+kvm_pv_unhalt -m 214 -smp 6 -nographic -monitor \
++unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial \
++none -parallel none
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
+new file mode 100644
+index 0000000..ac8781b
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
+@@ -0,0 +1,26 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static'>6</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='network'/>
++ </os>
++ <features>
++ <acpi/>
++ <pae/>
++ <pvspinlock state='on'/>
++ </features>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <controller type='usb' index='0'/>
++ <controller type='pci' index='0' model='pci-root'/>
++ <memballoon model='virtio'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 1d964ce..2f05727 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -446,6 +446,8 @@ mymain(void)
+ QEMU_CAPS_CHARDEV_SPICEVMC, QEMU_CAPS_SPICE, QEMU_CAPS_HDA_DUPLEX);
+ DO_TEST("eoi-disabled", NONE);
+ DO_TEST("eoi-enabled", NONE);
++ DO_TEST("pv-spinlock-disabled", NONE);
++ DO_TEST("pv-spinlock-enabled", NONE);
+ DO_TEST("kvmclock+eoi-disabled", QEMU_CAPS_ENABLE_KVM);
+
+ DO_TEST("hyperv", NONE);
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index 6eebc68..5a47ef8 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -156,6 +156,8 @@ mymain(void)
+ DO_TEST("cpu-eoi-enabled");
+ DO_TEST("eoi-disabled");
+ DO_TEST("eoi-enabled");
++ DO_TEST("pv-spinlock-disabled");
++ DO_TEST("pv-spinlock-enabled");
+
+ DO_TEST("hyperv");
+ DO_TEST("hyperv-off");
+--
+1.8.4.2
+
--- /dev/null
+From ac2a6bb565013f8fce9f36d3eac1ffa7d9523e9a Mon Sep 17 00:00:00 2001
+Message-Id: <ac2a6bb565013f8fce9f36d3eac1ffa7d9523e9a.1382534061.git.jdenemar@redhat.com>
+From: Wang Yufei <james.wangyufei@huawei.com>
+Date: Tue, 22 Oct 2013 16:24:46 +0100
+Subject: [PATCH] qemu: Avoid assigning unavailable migration ports
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1019237
+
+When we migrate vms concurrently, there's a chance that libvirtd on
+destination assigns the same port for different migrations, which will
+lead to migration failure during prepare phase on destination. So we use
+virPortAllocator here to solve the problem.
+
+Signed-off-by: Wang Yufei <james.wangyufei@huawei.com>
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 0196845d3abd0d914cf11f7ad6c19df8b47c32ed)
+---
+ src/qemu/qemu_command.h | 3 +++
+ src/qemu/qemu_conf.h | 6 +++---
+ src/qemu/qemu_domain.h | 1 +
+ src/qemu/qemu_driver.c | 6 ++++++
+ src/qemu/qemu_migration.c | 53 +++++++++++++++++++++++++++++++++--------------
+ 5 files changed, 50 insertions(+), 19 deletions(-)
+
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index 47022e6..decc940 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -51,6 +51,9 @@
+ # define QEMU_WEBSOCKET_PORT_MIN 5700
+ # define QEMU_WEBSOCKET_PORT_MAX 65535
+
++# define QEMU_MIGRATION_PORT_MIN 49152
++# define QEMU_MIGRATION_PORT_MAX 49215
++
+ typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
+ typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
+ struct _qemuBuildCommandLineCallbacks {
+diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
+index 356e501..4acc67b 100644
+--- a/src/qemu/qemu_conf.h
++++ b/src/qemu/qemu_conf.h
+@@ -224,6 +224,9 @@ struct _virQEMUDriver {
+ /* Immutable pointer, self-locking APIs */
+ virPortAllocatorPtr webSocketPorts;
+
++ /* Immutable pointer, self-locking APIs */
++ virPortAllocatorPtr migrationPorts;
++
+ /* Immutable pointer, lockless APIs*/
+ virSysinfoDefPtr hostsysinfo;
+
+@@ -245,9 +248,6 @@ struct _qemuDomainCmdlineDef {
+ char **env_value;
+ };
+
+-/* Port numbers used for KVM migration. */
+-# define QEMUD_MIGRATION_FIRST_PORT 49152
+-# define QEMUD_MIGRATION_NUM_PORTS 64
+
+
+ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged);
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index 21f116c..04f08a3 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate {
+ unsigned long migMaxBandwidth;
+ char *origname;
+ int nbdPort; /* Port used for migration with NBD */
++ unsigned short migrationPort;
+
+ virChrdevsPtr devs;
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index c2445d9..4a4880c 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged,
+ cfg->webSocketPortMax)) == NULL)
+ goto error;
+
++ if ((qemu_driver->migrationPorts =
++ virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
++ QEMU_MIGRATION_PORT_MAX)) == NULL)
++ goto error;
++
+ if (qemuSecurityInit(qemu_driver) < 0)
+ goto error;
+
+@@ -993,6 +998,7 @@ qemuStateCleanup(void) {
+ virObjectUnref(qemu_driver->domains);
+ virObjectUnref(qemu_driver->remotePorts);
+ virObjectUnref(qemu_driver->webSocketPorts);
++ virObjectUnref(qemu_driver->migrationPorts);
+
+ virObjectUnref(qemu_driver->xmlopt);
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 047fad9..4222a10 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -2145,6 +2145,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
+ qemuDomainJobTypeToString(priv->job.active),
+ qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+
++ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
++ priv->migrationPort = 0;
++
+ if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
+ return;
+ qemuDomainObjDiscardAsyncJob(driver, vm);
+@@ -2160,7 +2163,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ virDomainDefPtr *def,
+ const char *origname,
+ virStreamPtr st,
+- unsigned int port,
++ unsigned short port,
++ bool autoPort,
+ const char *listenAddress,
+ unsigned long flags)
+ {
+@@ -2440,6 +2444,8 @@ done:
+ goto cleanup;
+ }
+
++ if (autoPort)
++ priv->migrationPort = port;
+ ret = 0;
+
+ cleanup:
+@@ -2507,7 +2513,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+ cookieout, cookieoutlen, def, origname,
+- st, 0, NULL, flags);
++ st, 0, false, NULL, flags);
+ return ret;
+ }
+
+@@ -2526,8 +2532,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ const char *listenAddress,
+ unsigned long flags)
+ {
+- static int port = 0;
+- int this_port;
++ unsigned short port = 0;
++ bool autoPort = true;
+ char *hostname = NULL;
+ const char *p;
+ char *uri_str = NULL;
+@@ -2554,10 +2560,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ * to be a correct hostname which refers to the target machine).
+ */
+ if (uri_in == NULL) {
+- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
+- if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
++ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
++ goto cleanup;
++ } else if (!port) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("No migration port available within the "
++ "configured range"));
++ goto cleanup;
++ }
+
+- /* Get hostname */
+ if ((hostname = virGetHostname()) == NULL)
+ goto cleanup;
+
+@@ -2574,7 +2585,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ * new targets accept both syntaxes though.
+ */
+ /* Caller frees */
+- if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0)
++ if (virAsprintf(uri_out, "tcp:%s:%d", hostname, port) < 0)
+ goto cleanup;
+ } else {
+ /* Check the URI starts with "tcp:". We will escape the
+@@ -2610,17 +2621,22 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ }
+
+ if (uri->port == 0) {
+- /* Generate a port */
+- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
+- if (port == QEMUD_MIGRATION_NUM_PORTS)
+- port = 0;
++ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
++ goto cleanup;
++ } else if (!port) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("No migration port available within the "
++ "configured range"));
++ goto cleanup;
++ }
+
+ /* Caller frees */
+- if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0)
++ if (virAsprintf(uri_out, "%s:%d", uri_in, port) < 0)
+ goto cleanup;
+
+ } else {
+- this_port = uri->port;
++ port = uri->port;
++ autoPort = false;
+ }
+ }
+
+@@ -2629,12 +2645,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+ cookieout, cookieoutlen, def, origname,
+- NULL, this_port, listenAddress, flags);
++ NULL, port, autoPort, listenAddress, flags);
+ cleanup:
+ virURIFree(uri);
+ VIR_FREE(hostname);
+- if (ret != 0)
++ if (ret != 0) {
+ VIR_FREE(*uri_out);
++ if (autoPort)
++ virPortAllocatorRelease(driver->migrationPorts, port);
++ }
+ return ret;
+ }
+
+@@ -4414,6 +4433,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
+ }
+
+ qemuMigrationStopNBDServer(driver, vm, mig);
++ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
++ priv->migrationPort = 0;
+
+ if (flags & VIR_MIGRATE_PERSIST_DEST) {
+ virDomainDefPtr vmdef;
+--
+1.8.4
+
--- /dev/null
+From 68d2b7bb402e826812745b67df96f4715746d1bc Mon Sep 17 00:00:00 2001
+Message-Id: <68d2b7bb402e826812745b67df96f4715746d1bc.1379597660.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 18 Sep 2013 10:37:48 +0200
+Subject: [PATCH] qemu: Avoid dangling job in qemuDomainSetBlockIoTune
+
+https://bugzilla.redhat.com/show_bug.cgi?id=700443
+
+virDomainSetBlockIoTuneEnsureACL was incorrectly called after we already
+started a job. As a result of this, the job was not cleaned up when an
+access driver had forbidden the action.
+
+(cherry picked from commit 13e9bad55ad3d4705585bd483765805973d9f2f1)
+---
+ src/qemu/qemu_driver.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 53cb1ec..eb1a2ce 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -14945,15 +14945,15 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ return -1;
+
++ if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0)
++ goto cleanup;
++
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ priv = vm->privateData;
+ cfg = virQEMUDriverGetConfig(driver);
+
+- if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0)
+- goto cleanup;
+-
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+ goto endjob;
+
+--
+1.8.3.2
+
--- /dev/null
+From 5f78e7c3588d19b63acd717a53a62fca1971fc9a Mon Sep 17 00:00:00 2001
+Message-Id: <5f78e7c3588d19b63acd717a53a62fca1971fc9a.1383922565.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 8 Nov 2013 08:01:41 +0100
+Subject: [PATCH] qemu: Avoid double free of VM
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1018267
+
+One of my previous patches (c7ac2519b7f) did try to fix the issue when
+domain dies too soon during migration. However, this clumsy approach was
+missing removal of qemuProcessHandleMonitorDestroy resulting in double
+unrefing of mon->vm and hence producing the daemon crash:
+
+==11843== Invalid read of size 4
+==11843== at 0x50C28C5: virObjectUnref (virobject.c:255)
+==11843== by 0x1148F7DB: qemuMonitorDispose (qemu_monitor.c:258)
+==11843== by 0x50C2991: virObjectUnref (virobject.c:262)
+==11843== by 0x50C2D13: virObjectFreeCallback (virobject.c:388)
+==11843== by 0x509C37B: virEventPollCleanupHandles (vireventpoll.c:583)
+==11843== by 0x509C711: virEventPollRunOnce (vireventpoll.c:652)
+==11843== by 0x509A620: virEventRunDefaultImpl (virevent.c:274)
+==11843== by 0x520D21C: virNetServerRun (virnetserver.c:1112)
+==11843== by 0x11F368: main (libvirtd.c:1513)
+==11843== Address 0x13b88864 is 4 bytes inside a block of size 136 free'd
+==11843== at 0x4A07F5C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==11843== by 0x5079A2F: virFree (viralloc.c:580)
+==11843== by 0x50C29E3: virObjectUnref (virobject.c:270)
+==11843== by 0x114770E4: qemuProcessHandleMonitorDestroy (qemu_process.c:1103)
+==11843== by 0x1148F7CB: qemuMonitorDispose (qemu_monitor.c:257)
+==11843== by 0x50C2991: virObjectUnref (virobject.c:262)
+==11843== by 0x50C2D13: virObjectFreeCallback (virobject.c:388)
+==11843== by 0x509C37B: virEventPollCleanupHandles (vireventpoll.c:583)
+==11843== by 0x509C711: virEventPollRunOnce (vireventpoll.c:652)
+==11843== by 0x509A620: virEventRunDefaultImpl (virevent.c:274)
+==11843== by 0x520D21C: virNetServerRun (virnetserver.c:1112)
+==11843== by 0x11F368: main (libvirtd.c:1513)
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 5a4c2374a2ca5d9d5c5d495f507abcef0f5aabe7)
+
+Conflicts:
+ src/qemu/qemu_process.c: Context, as 809ee6bad is not backported yet.
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index b9f291d..e0097df 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -1082,13 +1082,6 @@ error:
+ return -1;
+ }
+
+-
+-static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+- virDomainObjPtr vm)
+-{
+- virObjectUnref(vm);
+-}
+-
+ static int
+ qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+@@ -1345,7 +1338,6 @@ cleanup:
+
+
+ static qemuMonitorCallbacks monitorCallbacks = {
+- .destroy = qemuProcessHandleMonitorDestroy,
+ .eofNotify = qemuProcessHandleMonitorEOF,
+ .errorNotify = qemuProcessHandleMonitorError,
+ .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
+@@ -1382,7 +1374,7 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int logfd)
+ }
+
+ /* Hold an extra reference because we can't allow 'vm' to be
+- * deleted while the monitor is active */
++ * deleted unitl the monitor gets its own reference. */
+ virObjectRef(vm);
+
+ ignore_value(virTimeMillisNow(&priv->monStart));
+@@ -1397,11 +1389,10 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int logfd)
+ ignore_value(qemuMonitorSetDomainLog(mon, logfd));
+
+ virObjectLock(vm);
++ virObjectUnref(vm);
+ priv->monStart = 0;
+
+- if (mon == NULL) {
+- virObjectUnref(vm);
+- } else if (!virDomainObjIsActive(vm)) {
++ if (!virDomainObjIsActive(vm)) {
+ qemuMonitorClose(mon);
+ mon = NULL;
+ }
+--
+1.8.4.2
+
--- /dev/null
+From f937ef18118e499e5049bca012bed51ccc5d2b3e Mon Sep 17 00:00:00 2001
+Message-Id: <f937ef18118e499e5049bca012bed51ccc5d2b3e.1380703761.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 27 Sep 2013 16:02:39 +0200
+Subject: [PATCH] qemu: Don't leak reference to virQEMUDriverConfigPtr
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1011330 (case D)
+
+qemuProcessStart created two references to virQEMUDriverConfigPtr before
+calling fork():
+
+ cfg = virQEMUDriverGetConfig(driver);
+ ...
+ hookData.cfg = virObjectRef(cfg);
+
+However, the child only unreferenced hookData.cfg and the parent only
+removed the cfg reference. That said, we don't need to increment the
+reference counter when assigning cfg to hookData. Both the child and the
+parent will correctly remove the reference on cfg (the child will do
+that through hookData).
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 833cdab6d2ad7521c954948adf3c7d3c3b42ae9f)
+---
+ src/qemu/qemu_process.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 843ff76..1bd0d04 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3475,7 +3475,8 @@ int qemuProcessStart(virConnectPtr conn,
+ hookData.conn = conn;
+ hookData.vm = vm;
+ hookData.driver = driver;
+- hookData.cfg = virObjectRef(cfg);
++ /* We don't increase cfg's reference counter here. */
++ hookData.cfg = cfg;
+
+ VIR_DEBUG("Beginning VM startup process");
+
+--
+1.8.3.2
+
--- /dev/null
+From ecb424b6ca400a126e5677a1f573e3688490d9e6 Mon Sep 17 00:00:00 2001
+Message-Id: <ecb424b6ca400a126e5677a1f573e3688490d9e6.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:45 +0200
+Subject: [PATCH] qemu: Drop qemuDomainMemoryLimit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+This function is to guess the correct limit for maximal memory
+usage by qemu for given domain. This can never be guessed
+correctly, not to mention all the pains and sleepless nights this
+code has caused. Once somebody discovers algorithm to solve the
+Halting Problem, we can compute the limit algorithmically. But
+till then, this code should never see the light of the release
+again.
+(cherry picked from commit 16bcb3b61675a88bff00317336b9610080c31000)
+---
+ src/qemu/qemu_cgroup.c | 3 +--
+ src/qemu/qemu_command.c | 2 +-
+ src/qemu/qemu_domain.c | 49 -------------------------------------------------
+ src/qemu/qemu_domain.h | 2 --
+ src/qemu/qemu_hotplug.c | 2 +-
+ 5 files changed, 3 insertions(+), 55 deletions(-)
+
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index 787ddeb..f07c450 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -428,8 +428,7 @@ qemuSetupMemoryCgroup(virDomainObjPtr vm)
+ }
+ }
+
+- if (virCgroupSetMemoryHardLimit(priv->cgroup,
+- qemuDomainMemoryLimit(vm->def)) < 0)
++ if (virCgroupSetMemoryHardLimit(priv->cgroup, vm->def->mem.hard_limit) < 0)
+ return -1;
+
+ if (vm->def->mem.soft_limit != 0 &&
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index af8a5b4..7bbfd03 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -9240,7 +9240,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ }
+
+ if (mlock)
+- virCommandSetMaxMemLock(cmd, qemuDomainMemoryLimit(def) * 1024);
++ virCommandSetMaxMemLock(cmd, def->mem.hard_limit * 1024);
+
+ virObjectUnref(cfg);
+ return cmd;
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 393af6b..7f4d17d 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -2306,55 +2306,6 @@ cleanup:
+ return ret;
+ }
+
+-
+-unsigned long long
+-qemuDomainMemoryLimit(virDomainDefPtr def)
+-{
+- unsigned long long mem;
+- size_t i;
+-
+- if (def->mem.hard_limit) {
+- mem = def->mem.hard_limit;
+- } else {
+- /* If there is no hard_limit set, compute a reasonable one to avoid
+- * system thrashing caused by exploited qemu. A 'reasonable
+- * limit' has been chosen:
+- * (1 + k) * (domain memory + total video memory) + (32MB for
+- * cache per each disk) + F
+- * where k = 0.5 and F = 400MB. The cache for disks is important as
+- * kernel cache on the host side counts into the RSS limit.
+- * Moreover, VFIO requires some amount for IO space. Alex Williamson
+- * suggested adding 1GiB for IO space just to be safe (some finer
+- * tuning might be nice, though).
+- *
+- * Technically, the disk cache does not have to be included in
+- * RLIMIT_MEMLOCK but it doesn't hurt as it's just an upper limit and
+- * it makes this function and its usage simpler.
+- */
+- mem = def->mem.max_balloon;
+- for (i = 0; i < def->nvideos; i++)
+- mem += def->videos[i]->vram;
+- mem *= 1.5;
+- mem += def->ndisks * 32768;
+- mem += 409600;
+-
+- for (i = 0; i < def->nhostdevs; i++) {
+- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+- if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+- hostdev->source.subsys.type ==
+- VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+- hostdev->source.subsys.u.pci.backend ==
+- VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+- mem += 1024 * 1024;
+- break;
+- }
+- }
+- }
+-
+- return mem;
+-}
+-
+-
+ int
+ qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
+ virDomainObjPtr vm)
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index 0a4a51e..21f116c 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -365,8 +365,6 @@ extern virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks;
+ extern virDomainXMLNamespace virQEMUDriverDomainXMLNamespace;
+ extern virDomainDefParserConfig virQEMUDriverDomainDefParserConfig;
+
+-unsigned long long qemuDomainMemoryLimit(virDomainDefPtr def);
+-
+ int qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
+ virDomainObjPtr vm);
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index b1f4586..89df4ad 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1035,7 +1035,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ */
+ vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+ virProcessSetMaxMemLock(vm->pid,
+- qemuDomainMemoryLimit(vm->def) * 1024);
++ vm->def->mem.hard_limit * 1024);
+ vm->def->hostdevs[vm->def->nhostdevs--] = NULL;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From f1241c136e006b81b4f041be94bd226e4742c252 Mon Sep 17 00:00:00 2001
+Message-Id: <f1241c136e006b81b4f041be94bd226e4742c252.1382534062.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 22 Oct 2013 16:26:26 +0100
+Subject: [PATCH] qemu: Fix augeas support for migration ports
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1019237
+
+Commit e3ef20d7 allows user to configure migration ports range via
+qemu.conf. However, it forgot to update augeas definition file and
+even the test data was malicious.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit d9be5a7157515eeae99379e9544c34b34c5e5198)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/libvirtd_qemu.aug | 2 ++
+ src/qemu/test_libvirtd_qemu.aug.in | 4 ++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
+index 8ce6885..3a73820 100644
+--- a/src/qemu/libvirtd_qemu.aug
++++ b/src/qemu/libvirtd_qemu.aug
+@@ -78,6 +78,8 @@ module Libvirtd_qemu =
+ | int_entry "keepalive_count"
+
+ let network_entry = str_entry "migration_address"
++ | int_entry "migration_port_min"
++ | int_entry "migration_port_max"
+
+ (* Each entry in the config is one of the following ... *)
+ let entry = vnc_entry
+diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
+index d6d55b8..2683b9b 100644
+--- a/src/qemu/test_libvirtd_qemu.aug.in
++++ b/src/qemu/test_libvirtd_qemu.aug.in
+@@ -67,5 +67,5 @@ module Test_libvirtd_qemu =
+ { "keepalive_count" = "5" }
+ { "seccomp_sandbox" = "1" }
+ { "migration_address" = "127.0.0.1" }
+-{ "migration_port_min" = "1234" }
+-{ "migration_port_max" = "12345" }
++{ "migration_port_min" = "49152" }
++{ "migration_port_max" = "49215" }
+--
+1.8.4
+
--- /dev/null
+From bfaf4b3a5bb4bc74d089d5230cdd1e83622f9239 Mon Sep 17 00:00:00 2001
+Message-Id: <bfaf4b3a5bb4bc74d089d5230cdd1e83622f9239.1379597659.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 17 Sep 2013 10:19:32 +0200
+Subject: [PATCH] qemu: Fix checking of ABI stability when restoring external
+ checkpoints
+
+External checkpoints have a bug in the implementation where they use the
+normal definition instead of the "migratable" one. This causes errors
+when the snapshot is being reverted using the workaround method via
+qemuDomainRestoreFlags() with a custom XML. This issue was introduced
+when commit 07966f6a8b5ccb5bb4c716b25deb8ba2e572cc67 changed the code to
+compare "migratable" XMLs from the user as we should have used
+migratable in the image too.
+
+This patch adds a compatibility layer, so that fixing the snapshot code
+won't make existing snapshots fail to load.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1008340
+(cherry picked from commit 59898a88ce8431bd3ea249b8789edc2ef9985827)
+---
+ src/qemu/qemu_driver.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 86a1d6d..9b9732d 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -5312,14 +5312,31 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
+ goto error;
+
+ newdef = qemuDomainDefCopy(driver, def2, VIR_DOMAIN_XML_MIGRATABLE);
+- virDomainDefFree(def2);
+- if (!newdef)
++ if (!newdef) {
++ virDomainDefFree(def2);
+ goto error;
++ }
+
+ if (!virDomainDefCheckABIStability(def, newdef)) {
+ virDomainDefFree(newdef);
+- goto error;
++ virResetLastError();
++
++ /* Due to a bug in older version of external snapshot creation
++ * code, the XML saved in the save image was not a migratable
++ * XML. To ensure backwards compatibility with the change of the
++ * saved XML type, we need to check the ABI compatibility against
++ * the user provided XML if the check against the migratable XML
++ * fails. Snapshots created prior to v1.1.3 have this issue. */
++ if (!virDomainDefCheckABIStability(def, def2)) {
++ virDomainDefFree(def2);
++ goto error;
++ }
++
++ /* use the user provided XML */
++ newdef = def2;
++ def2 = NULL;
+ }
++
+ virDomainDefFree(def);
+ def = newdef;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From d82d81f40afed3eb75a7e0b6ebf1e35186f5cf50 Mon Sep 17 00:00:00 2001
+Message-Id: <d82d81f40afed3eb75a7e0b6ebf1e35186f5cf50.1379193141.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 12 Sep 2013 16:16:31 +0200
+Subject: [PATCH] qemu: Fix checking of guest ABI compatibility when reverting
+ snapshots
+
+When reverting a live internal snapshot with a live guest the ABI
+compatiblity check was comparing a "migratable" definition with a normal
+one. This resulted in the check failing with:
+
+revert requires force: Target device address type none does not match source pci
+
+This patch generates a "migratable" definition from the actual one to
+check against the definition from the snapshot to avoid this problem.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1006886
+(cherry picked from commit 53c39f5837a6eed543465a7a55690786d0655ad0)
+---
+ src/qemu/qemu_driver.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 995fe76..86a1d6d 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -13266,6 +13266,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+ qemuDomainObjPrivatePtr priv;
+ int rc;
+ virDomainDefPtr config = NULL;
++ virDomainDefPtr migratableDef = NULL;
+ virQEMUDriverConfigPtr cfg = NULL;
+ virCapsPtr caps = NULL;
+
+@@ -13380,8 +13381,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+ * to have finer control. */
+ if (virDomainObjIsActive(vm)) {
+ /* Transitions 5, 6, 8, 9 */
+- /* Check for ABI compatibility. */
+- if (config && !virDomainDefCheckABIStability(vm->def, config)) {
++ /* Check for ABI compatibility. We need to do this check against
++ * the migratable XML or it will always fail otherwise */
++ if (!(migratableDef = qemuDomainDefCopy(driver, vm->def,
++ VIR_DOMAIN_XML_MIGRATABLE)))
++ goto cleanup;
++
++ if (config && !virDomainDefCheckABIStability(migratableDef, config)) {
+ virErrorPtr err = virGetLastError();
+
+ if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
+@@ -13586,6 +13592,7 @@ cleanup:
+ }
+ if (vm)
+ virObjectUnlock(vm);
++ virDomainDefFree(migratableDef);
+ virObjectUnref(caps);
+ virObjectUnref(cfg);
+
+--
+1.8.3.2
+
--- /dev/null
+From 739e3d6333e8e02a9403be18502af9a8866b0c73 Mon Sep 17 00:00:00 2001
+Message-Id: <739e3d6333e8e02a9403be18502af9a8866b0c73.1379597660.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Wed, 18 Sep 2013 09:28:12 +0200
+Subject: [PATCH] qemu: Fix memleak after commit
+ 59898a88ce8431bd3ea249b8789edc2ef9985827
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008340
+
+If the ABI compatibility check with the "migratable" user XML is
+successful, we would leak the originally parsed XML from the user that
+would not be used in this case.
+
+Reported by Ján Tomko.
+
+(cherry picked from commit 044e3e75248f0346f9dfd181a90f7d16d69ed482)
+---
+ src/qemu/qemu_driver.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 71d773c..53cb1ec 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -5335,6 +5335,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
+ /* use the user provided XML */
+ newdef = def2;
+ def2 = NULL;
++ } else {
++ virDomainDefFree(def2);
+ }
+
+ virDomainDefFree(def);
+--
+1.8.3.2
+
--- /dev/null
+From a529b0f55b74654c07f9d0398e8fa179be76c3db Mon Sep 17 00:00:00 2001
+Message-Id: <a529b0f55b74654c07f9d0398e8fa179be76c3db.1380112456.git.jdenemar@redhat.com>
+From: Martin Kletzander <mkletzan@redhat.com>
+Date: Mon, 23 Sep 2013 10:40:21 +0200
+Subject: [PATCH] qemu: Fix seamless SPICE migration
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1010861
+
+Since the wait is done during migration (still inside
+QEMU_ASYNC_JOB_MIGRATION_OUT), the code should enter the monitor as such
+in order to prohibit all other jobs from interfering in the meantime.
+This patch fixes bug #1009886 in which qemuDomainGetBlockInfo was
+waiting on the monitor condition and after GetSpiceMigrationStatus
+mangled its internal data, the daemon crashed.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1009886
+(cherry picked from commit 484cc3217b73b865f00bf42a9c12187b37200699)
+Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_migration.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 5fd52c1..4f53576 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -1598,7 +1598,10 @@ qemuMigrationWaitForSpice(virQEMUDriverPtr driver,
+ /* Poll every 50ms for progress & to allow cancellation */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
+
+- qemuDomainObjEnterMonitor(driver, vm);
++ if (qemuDomainObjEnterMonitorAsync(driver, vm,
++ QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
++ return -1;
++
+ if (qemuMonitorGetSpiceMigrationStatus(priv->mon,
+ &spice_migrated) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+--
+1.8.3.2
+
--- /dev/null
+From 0ab9ef832c9e5531c1428e0274d46a29b0be4637 Mon Sep 17 00:00:00 2001
+Message-Id: <0ab9ef832c9e5531c1428e0274d46a29b0be4637.1380703761.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 27 Sep 2013 16:02:38 +0200
+Subject: [PATCH] qemu: Free all driver data in qemuStateCleanup
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1011330 (case A)
+
+While activeScsiHostdevs and webSocketPorts were allocated in
+qemuStateInitialize, they were not freed in qemuStateCleanup.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 9e03f313b80d6b7daef90235b607e7ed80dd7235)
+---
+ src/qemu/qemu_driver.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 693dd85..fd548b2 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -986,12 +986,14 @@ qemuStateCleanup(void) {
+ virObjectUnref(qemu_driver->activePciHostdevs);
+ virObjectUnref(qemu_driver->inactivePciHostdevs);
+ virObjectUnref(qemu_driver->activeUsbHostdevs);
++ virObjectUnref(qemu_driver->activeScsiHostdevs);
+ virHashFree(qemu_driver->sharedDevices);
+ virObjectUnref(qemu_driver->caps);
+ virQEMUCapsCacheFree(qemu_driver->qemuCapsCache);
+
+ virObjectUnref(qemu_driver->domains);
+ virObjectUnref(qemu_driver->remotePorts);
++ virObjectUnref(qemu_driver->webSocketPorts);
+
+ virObjectUnref(qemu_driver->xmlopt);
+
+--
+1.8.3.2
+
--- /dev/null
+From 78e74acdcac9ada430b822afa6b5e1dadae575e8 Mon Sep 17 00:00:00 2001
+Message-Id: <78e74acdcac9ada430b822afa6b5e1dadae575e8.1378475168.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 3 Sep 2013 15:18:46 +0200
+Subject: [PATCH] qemu: Handle huge number of queues correctly
+
+https://bugzilla.redhat.com/show_bug.cgi?id=651941
+
+Currently, kernel supports up to 8 queues for a multiqueue tap device.
+However, if user tries to enter a huge number (e.g. one million) the tap
+allocation fails, as expected. But what is not expected is the log full
+of warnings:
+
+ warning : virFileClose:83 : Tried to close invalid fd 0
+
+The problem is, upon error we iterate over an array of FDs (handlers to
+queues) and VIR_FORCE_CLOSE() over each item. However, the array is
+pre-filled with zeros. Hence, we repeatedly close stdin. Ouch.
+But there's more. The queues allocation is done in virNetDevTapCreate()
+which cleans up the FDs in case of error. Then, its caller, the
+virNetDevTapCreateInBridgePort() iterates over the FD array and tries to
+close them too. And so does qemuNetworkIfaceConnect() and
+qemuBuildInterfaceCommandLine().
+(cherry picked from commit 1dc5dea7d605d3b02c64940fc3566a7765dce3c3)
+---
+ src/qemu/qemu_command.c | 10 +++++++---
+ src/util/virnetdevtap.c | 5 +++--
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 6dfd141..6e9657f 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -405,7 +405,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
+ cleanup:
+ if (ret < 0) {
+ size_t i;
+- for (i = 0; i < *tapfdSize; i++)
++ for (i = 0; i < *tapfdSize && tapfd[i] >= 0; i++)
+ VIR_FORCE_CLOSE(tapfd[i]);
+ if (template_ifname)
+ VIR_FREE(net->ifname);
+@@ -7215,6 +7215,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
+ VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
+ goto cleanup;
+
++ memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
++
+ if (qemuNetworkIfaceConnect(def, conn, driver, net,
+ qemuCaps, tapfd, &tapfdSize) < 0)
+ goto cleanup;
+@@ -7242,6 +7244,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
+ VIR_ALLOC_N(vhostfdName, vhostfdSize))
+ goto cleanup;
+
++ memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));
++
+ if (qemuOpenVhostNet(def, net, qemuCaps, vhostfd, &vhostfdSize) < 0)
+ goto cleanup;
+ }
+@@ -7303,13 +7307,13 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
+ cleanup:
+ if (ret < 0)
+ virDomainConfNWFilterTeardown(net);
+- for (i = 0; tapfd && i < tapfdSize; i++) {
++ for (i = 0; tapfd && i < tapfdSize && tapfd[i] >= 0; i++) {
+ if (ret < 0)
+ VIR_FORCE_CLOSE(tapfd[i]);
+ if (tapfdName)
+ VIR_FREE(tapfdName[i]);
+ }
+- for (i = 0; vhostfd && i < vhostfdSize; i++) {
++ for (i = 0; vhostfd && i < vhostfdSize && vhostfd[i] >= 0; i++) {
+ if (ret < 0)
+ VIR_FORCE_CLOSE(vhostfd[i]);
+ if (vhostfdName)
+diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
+index 42e8dfe..fb173e3 100644
+--- a/src/util/virnetdevtap.c
++++ b/src/util/virnetdevtap.c
+@@ -445,6 +445,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
+ {
+ virMacAddr tapmac;
+ char macaddrstr[VIR_MAC_STRING_BUFLEN];
++ size_t i;
+
+ if (virNetDevTapCreate(ifname, tapfd, tapfdSize, flags) < 0)
+ return -1;
+@@ -498,8 +499,8 @@ int virNetDevTapCreateInBridgePort(const char *brname,
+ return 0;
+
+ error:
+- while (tapfdSize)
+- VIR_FORCE_CLOSE(tapfd[--tapfdSize]);
++ for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
++ VIR_FORCE_CLOSE(tapfd[i]);
+
+ return -1;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From ecbf7a620fb79456724d37e86069e5a006e45270 Mon Sep 17 00:00:00 2001
+Message-Id: <ecbf7a620fb79456724d37e86069e5a006e45270.1382534061.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 11:24:35 +0200
+Subject: [PATCH] qemu: Implement support for VIR_MIGRATE_PARAM_LISTEN_ADDRESS
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015215
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit c4ac7ef6638081c79ee7e9209bc49a81560a9f25)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_driver.c | 26 +++++++----
+ src/qemu/qemu_migration.c | 112 +++++++++++++++++++++++++++++++---------------
+ src/qemu/qemu_migration.h | 13 +++---
+ 3 files changed, 102 insertions(+), 49 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 3d0b56e..91549fb 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -10330,7 +10330,7 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
+ ret = qemuMigrationPrepareDirect(driver, dconn,
+ NULL, 0, NULL, NULL, /* No cookies */
+ uri_in, uri_out,
+- &def, origname, flags);
++ &def, origname, NULL, flags);
+
+ cleanup:
+ VIR_FREE(origname);
+@@ -10381,7 +10381,8 @@ qemuDomainMigratePerform(virDomainPtr dom,
+ * Consume any cookie we were able to decode though
+ */
+ ret = qemuMigrationPerform(driver, dom->conn, vm,
+- NULL, dconnuri, uri, NULL, cookie, cookielen,
++ NULL, dconnuri, uri, NULL, NULL,
++ cookie, cookielen,
+ NULL, NULL, /* No output cookies in v2 */
+ flags, dname, resource, false);
+
+@@ -10535,7 +10536,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ uri_in, uri_out,
+- &def, origname, flags);
++ &def, origname, NULL, flags);
+
+ cleanup:
+ VIR_FREE(origname);
+@@ -10559,6 +10560,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
+ const char *uri_in = NULL;
++ const char *listenAddress = NULL;
+ char *origname = NULL;
+ int ret = -1;
+
+@@ -10574,7 +10576,10 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ &dname) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_URI,
+- &uri_in) < 0)
++ &uri_in) < 0 ||
++ virTypedParamsGetString(params, nparams,
++ VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
++ &listenAddress) < 0)
+ return -1;
+
+ if (flags & VIR_MIGRATE_TUNNELLED) {
+@@ -10597,7 +10602,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ uri_in, uri_out,
+- &def, origname, flags);
++ &def, origname, listenAddress, flags);
+
+ cleanup:
+ VIR_FREE(origname);
+@@ -10729,7 +10734,8 @@ qemuDomainMigratePerform3(virDomainPtr dom,
+ }
+
+ return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
+- dconnuri, uri, NULL, cookiein, cookieinlen,
++ dconnuri, uri, NULL, NULL,
++ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource, true);
+ }
+@@ -10751,6 +10757,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
+ const char *dname = NULL;
+ const char *uri = NULL;
+ const char *graphicsuri = NULL;
++ const char *listenAddress = NULL;
+ unsigned long long bandwidth = 0;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10771,7 +10778,10 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
+ &bandwidth) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_GRAPHICS_URI,
+- &graphicsuri) < 0)
++ &graphicsuri) < 0 ||
++ virTypedParamsGetString(params, nparams,
++ VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
++ &listenAddress) < 0)
+ return -1;
+
+ if (!(vm = qemuDomObjFromDomain(dom)))
+@@ -10783,7 +10793,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom,
+ }
+
+ return qemuMigrationPerform(driver, dom->conn, vm, dom_xml,
+- dconnuri, uri, graphicsuri,
++ dconnuri, uri, graphicsuri, listenAddress,
+ cookiein, cookieinlen, cookieout, cookieoutlen,
+ flags, dname, bandwidth, true);
+ }
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 4f53576..3f07b86 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -1100,12 +1100,6 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
+ unsigned short port = 0;
+ char *diskAlias = NULL;
+ size_t i;
+- const char *host;
+-
+- if (STREQ(listenAddr, "[::]"))
+- host = "::";
+- else
+- host = listenAddr;
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+@@ -1125,7 +1119,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
+
+ if (!port &&
+ ((virPortAllocatorAcquire(driver->remotePorts, &port) < 0) ||
+- (qemuMonitorNBDServerStart(priv->mon, host, port) < 0))) {
++ (qemuMonitorNBDServerStart(priv->mon, listenAddr, port) < 0))) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+@@ -2167,6 +2161,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ const char *origname,
+ virStreamPtr st,
+ unsigned int port,
++ const char *listenAddress,
+ unsigned long flags)
+ {
+ virDomainObjPtr vm = NULL;
+@@ -2180,7 +2175,6 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ char *xmlout = NULL;
+ unsigned int cookieFlags;
+ virCapsPtr caps = NULL;
+- const char *listenAddr = NULL;
+ char *migrateFrom = NULL;
+ bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
+
+@@ -2264,31 +2258,65 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ if (VIR_STRDUP(migrateFrom, "stdio") < 0)
+ goto cleanup;
+ } else {
++ virSocketAddr listenAddressSocket;
++ bool encloseAddress = false;
++ bool hostIPv6Capable = false;
++ bool qemuIPv6Capable = false;
+ virQEMUCapsPtr qemuCaps = NULL;
+ struct addrinfo *info = NULL;
+ struct addrinfo hints = { .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM };
+
++ if (getaddrinfo("::", NULL, &hints, &info) == 0) {
++ freeaddrinfo(info);
++ hostIPv6Capable = true;
++ }
+ if (!(qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
+ (*def)->emulator)))
+ goto cleanup;
+
+- /* Listen on :: instead of 0.0.0.0 if QEMU understands it
+- * and there is at least one IPv6 address configured
+- */
+- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION) &&
+- getaddrinfo("::", NULL, &hints, &info) == 0) {
+- freeaddrinfo(info);
+- listenAddr = "[::]";
++ qemuIPv6Capable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION);
++ virObjectUnref(qemuCaps);
++
++ if (listenAddress) {
++ if (virSocketAddrIsNumeric(listenAddress)) {
++ /* listenAddress is numeric IPv4 or IPv6 */
++ if (virSocketAddrParse(&listenAddressSocket, listenAddress, AF_UNSPEC) < 0)
++ goto cleanup;
++
++ /* address parsed successfully */
++ if (VIR_SOCKET_ADDR_IS_FAMILY(&listenAddressSocket, AF_INET6)) {
++ if (!qemuIPv6Capable) {
++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
++ _("qemu isn't capable of IPv6"));
++ goto cleanup;
++ }
++ if (!hostIPv6Capable) {
++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
++ _("host isn't capable of IPv6"));
++ goto cleanup;
++ }
++ /* IPv6 address must be escaped in brackets on the cmd line */
++ encloseAddress = true;
++ }
++ } else {
++ /* listenAddress is a hostname */
++ }
+ } else {
+- listenAddr = "0.0.0.0";
++ /* Listen on :: instead of 0.0.0.0 if QEMU understands it
++ * and there is at least one IPv6 address configured
++ */
++ listenAddress = qemuIPv6Capable && hostIPv6Capable ?
++ encloseAddress = true, "::" : "0.0.0.0";
+ }
+- virObjectUnref(qemuCaps);
+
+- /* QEMU will be started with -incoming [::]:port
+- * or -incoming 0.0.0.0:port
++ /* QEMU will be started with -incoming [<IPv6 addr>]:port,
++ * -incoming <IPv4 addr>:port or -incoming <hostname>:port
+ */
+- if (virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddr, port) < 0)
++ if ((encloseAddress &&
++ virAsprintf(&migrateFrom, "tcp:[%s]:%d", listenAddress, port) < 0) ||
++ (!encloseAddress &&
++ virAsprintf(&migrateFrom, "tcp:%s:%d", listenAddress, port) < 0))
+ goto cleanup;
+ }
+
+@@ -2375,7 +2403,7 @@ done:
+ if (mig->nbd &&
+ flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
+- if (qemuMigrationStartNBDServer(driver, vm, listenAddr) < 0) {
++ if (qemuMigrationStartNBDServer(driver, vm, listenAddress) < 0) {
+ /* error already reported */
+ goto endjob;
+ }
+@@ -2479,7 +2507,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+ cookieout, cookieoutlen, def, origname,
+- st, 0, flags);
++ st, 0, NULL, flags);
+ return ret;
+ }
+
+@@ -2495,6 +2523,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ char **uri_out,
+ virDomainDefPtr *def,
+ const char *origname,
++ const char *listenAddress,
+ unsigned long flags)
+ {
+ static int port = 0;
+@@ -2600,7 +2629,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+ cookieout, cookieoutlen, def, origname,
+- NULL, this_port, flags);
++ NULL, this_port, listenAddress, flags);
+ cleanup:
+ virURIFree(uri);
+ VIR_FREE(hostname);
+@@ -3604,6 +3633,7 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
+ const char *dname,
+ const char *uri,
+ const char *graphicsuri,
++ const char *listenAddress,
+ unsigned long long bandwidth,
+ bool useParams,
+ unsigned long flags)
+@@ -3625,11 +3655,11 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
+ int maxparams = 0;
+
+ VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, dconnuri=%s, vm=%p, xmlin=%s, "
+- "dname=%s, uri=%s, graphicsuri=%s, bandwidth=%llu, "
+- "useParams=%d, flags=%lx",
++ "dname=%s, uri=%s, graphicsuri=%s, listenAddress=%s, "
++ "bandwidth=%llu, useParams=%d, flags=%lx",
+ driver, sconn, dconn, NULLSTR(dconnuri), vm, NULLSTR(xmlin),
+- NULLSTR(dname), NULLSTR(uri), NULLSTR(graphicsuri), bandwidth,
+- useParams, flags);
++ NULLSTR(dname), NULLSTR(uri), NULLSTR(graphicsuri),
++ NULLSTR(listenAddress), bandwidth, useParams, flags);
+
+ /* Unlike the virDomainMigrateVersion3 counterpart, we don't need
+ * to worry about auto-setting the VIR_MIGRATE_CHANGE_PROTECTION
+@@ -3667,6 +3697,11 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver,
+ VIR_MIGRATE_PARAM_GRAPHICS_URI,
+ graphicsuri) < 0)
+ goto cleanup;
++ if (listenAddress &&
++ virTypedParamsAddString(¶ms, &nparams, &maxparams,
++ VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
++ listenAddress) < 0)
++ goto cleanup;
+ }
+
+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
+@@ -3871,6 +3906,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
+ const char *dconnuri,
+ const char *uri,
+ const char *graphicsuri,
++ const char *listenAddress,
+ unsigned long flags,
+ const char *dname,
+ unsigned long resource,
+@@ -3885,10 +3921,11 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
+ bool useParams;
+
+ VIR_DEBUG("driver=%p, sconn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
+- "uri=%s, graphicsuri=%s, flags=%lx, dname=%s, resource=%lu",
++ "uri=%s, graphicsuri=%s, listenAddress=%s, flags=%lx, "
++ "dname=%s, resource=%lu",
+ driver, sconn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
+- NULLSTR(uri), NULLSTR(graphicsuri), flags, NULLSTR(dname),
+- resource);
++ NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
++ flags, NULLSTR(dname), resource);
+
+ /* the order of operations is important here; we make sure the
+ * destination side is completely setup before we touch the source
+@@ -3963,8 +4000,8 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver,
+
+ if (*v3proto) {
+ ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
+- dname, uri, graphicsuri, resource,
+- useParams, flags);
++ dname, uri, graphicsuri, listenAddress,
++ resource, useParams, flags);
+ } else {
+ ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
+ dconnuri, flags, dname, resource);
+@@ -3998,6 +4035,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
+ const char *uri,
+ const char *graphicsuri,
+ const char *cookiein,
++ const char *listenAddress,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
+@@ -4032,8 +4070,8 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
+
+ if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
+ ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
+- dconnuri, uri, graphicsuri, flags, dname,
+- resource, &v3proto);
++ dconnuri, uri, graphicsuri, listenAddress,
++ flags, dname, resource, &v3proto);
+ } else {
+ qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
+ ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
+@@ -4198,6 +4236,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
+ const char *dconnuri,
+ const char *uri,
+ const char *graphicsuri,
++ const char *listenAddress,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+@@ -4224,7 +4263,8 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
+ }
+
+ return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
+- graphicsuri, cookiein, cookieinlen,
++ graphicsuri, listenAddress,
++ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource, v3proto);
+ } else {
+@@ -4242,7 +4282,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
+ flags, resource);
+ } else {
+ return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri,
+- uri, graphicsuri,
++ uri, graphicsuri, listenAddress,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen, flags,
+ dname, resource, v3proto);
+diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
+index 4af5aed..cafa2a2 100644
+--- a/src/qemu/qemu_migration.h
++++ b/src/qemu/qemu_migration.h
+@@ -43,11 +43,12 @@
+
+ /* All supported migration parameters and their types. */
+ # define QEMU_MIGRATION_PARAMETERS \
+- VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
+- VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
+- VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
+- VIR_MIGRATE_PARAM_BANDWIDTH, VIR_TYPED_PARAM_ULLONG, \
+- VIR_MIGRATE_PARAM_GRAPHICS_URI, VIR_TYPED_PARAM_STRING, \
++ VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
++ VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
++ VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
++ VIR_MIGRATE_PARAM_BANDWIDTH, VIR_TYPED_PARAM_ULLONG, \
++ VIR_MIGRATE_PARAM_GRAPHICS_URI, VIR_TYPED_PARAM_STRING, \
++ VIR_MIGRATE_PARAM_LISTEN_ADDRESS, VIR_TYPED_PARAM_STRING, \
+ NULL
+
+
+@@ -124,6 +125,7 @@ int qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ char **uri_out,
+ virDomainDefPtr *def,
+ const char *origname,
++ const char *listenAddress,
+ unsigned long flags);
+
+ int qemuMigrationPerform(virQEMUDriverPtr driver,
+@@ -133,6 +135,7 @@ int qemuMigrationPerform(virQEMUDriverPtr driver,
+ const char *dconnuri,
+ const char *uri,
+ const char *graphicsuri,
++ const char *listenAddress,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+--
+1.8.4
+
--- /dev/null
+From 0256413de0e54abee13663e37e57e3537c8e74d5 Mon Sep 17 00:00:00 2001
+Message-Id: <0256413de0e54abee13663e37e57e3537c8e74d5.1382534061.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 15:30:53 +0200
+Subject: [PATCH] qemu: Include listenAddress in debug prints
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015215
+
+After my patches, some functions gained one more argument
+(@listenAddress) which wasn't included in debug printing of
+arguments they were called with. Functions in question are:
+qemuMigrationPrepareDirect and qemuMigrationPerform.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit be651860444cab8d4961ea63ac570846f63e2d89)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_migration.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 3f07b86..047fad9 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -2536,10 +2536,10 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+
+ VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
+ "cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, "
+- "def=%p, origname=%s, flags=%lx",
++ "def=%p, origname=%s, listenAddress=%s, flags=%lx",
+ driver, dconn, NULLSTR(cookiein), cookieinlen,
+ cookieout, cookieoutlen, NULLSTR(uri_in), uri_out,
+- *def, origname, flags);
++ *def, origname, NULLSTR(listenAddress), flags);
+
+ *uri_out = NULL;
+
+@@ -4247,11 +4247,11 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
+ bool v3proto)
+ {
+ VIR_DEBUG("driver=%p, conn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
+- "uri=%s, graphicsuri=%s, "
++ "uri=%s, graphicsuri=%s, listenAddress=%s"
+ "cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, "
+ "flags=%lx, dname=%s, resource=%lu, v3proto=%d",
+ driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
+- NULLSTR(uri), NULLSTR(graphicsuri),
++ NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
+ NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen,
+ flags, NULLSTR(dname), resource, v3proto);
+
+--
+1.8.4
+
--- /dev/null
+From 4a1972082b79836027e50fcfa90d6e24d784d897 Mon Sep 17 00:00:00 2001
+Message-Id: <4a1972082b79836027e50fcfa90d6e24d784d897.1382534060.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:38 +0200
+Subject: [PATCH] qemu: Init @pcidevs in qemuPrepareHostdevPCIDevices
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+At the beginning of the function qemuPrepareHostdevPCICheckSupport() is
+called. After that @pcidevs is initialized. However, if the very first
+command fails, we go to 'cleanup' label where virObjectUnref(pcidevs) is
+called. Obviously, it is called before @pcidevs was able to get
+initialized. Compiler warns about it:
+
+ CC qemu/libvirt_driver_qemu_impl_la-qemu_hostdev.lo
+qemu/qemu_hostdev.c: In function 'qemuPrepareHostdevPCIDevices':
+qemu/qemu_hostdev.c:824:19: error: 'pcidevs' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+ virObjectUnref(pcidevs);
+ ^
+cc1: all warnings being treated as errors
+
+(cherry picked from commit 9c228e08175bdd76372c236298ce129d9a64e0d8)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hostdev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
+index 81e0e88..43c03cc 100644
+--- a/src/qemu/qemu_hostdev.c
++++ b/src/qemu/qemu_hostdev.c
+@@ -633,7 +633,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ int nhostdevs,
+ virQEMUCapsPtr qemuCaps)
+ {
+- virPCIDeviceListPtr pcidevs;
++ virPCIDeviceListPtr pcidevs = NULL;
+ int last_processed_hostdev_vf = -1;
+ size_t i;
+ int ret = -1;
+--
+1.8.4
+
--- /dev/null
+From 830af6845e0c1dd0ebe6f3de37c27ec3cd6f5e74 Mon Sep 17 00:00:00 2001
+Message-Id: <830af6845e0c1dd0ebe6f3de37c27ec3cd6f5e74.1378475168.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 4 Sep 2013 09:47:02 +0200
+Subject: [PATCH] qemu: Make domain renaming work during migration
+
+https://bugzilla.redhat.com/show_bug.cgi?id=999352
+
+Since commit v1.0.5-56-g449e6b1 (Pull parsing of migration xml up into
+QEMU driver APIs) any attempt to rename a domain during migration fails
+with the following error message:
+
+ internal error Incoming cookie data had unexpected name DOM vs DOM2
+
+This is because migration cookies always use the original domain name
+and the mentioned commit failed to propagate the name back to
+qemuMigrationPrepareAny.
+
+(cherry picked from commit 8d67c550e931f1dbc163e7e20784218edc1165df)
+---
+ src/qemu/qemu_driver.c | 36 ++++++++++++++++++++++++------------
+ src/qemu/qemu_migration.c | 31 +++++++++++++++++++------------
+ src/qemu/qemu_migration.h | 5 ++++-
+ 3 files changed, 47 insertions(+), 25 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 99cce90..995fe76 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -10202,6 +10202,7 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
+ {
+ virQEMUDriverPtr driver = dconn->privateData;
+ virDomainDefPtr def = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10219,7 +10220,7 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0)
+@@ -10227,9 +10228,10 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
+
+ ret = qemuMigrationPrepareTunnel(driver, dconn,
+ NULL, 0, NULL, NULL, /* No cookies in v2 */
+- st, &def, flags);
++ st, &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+@@ -10251,6 +10253,7 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
+ {
+ virQEMUDriverPtr driver = dconn->privateData;
+ virDomainDefPtr def = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10272,7 +10275,7 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0)
+@@ -10285,9 +10288,10 @@ qemuDomainMigratePrepare2(virConnectPtr dconn,
+ ret = qemuMigrationPrepareDirect(driver, dconn,
+ NULL, 0, NULL, NULL, /* No cookies */
+ uri_in, uri_out,
+- &def, flags);
++ &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+@@ -10464,6 +10468,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
+ {
+ virQEMUDriverPtr driver = dconn->privateData;
+ virDomainDefPtr def = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10478,7 +10483,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0)
+@@ -10488,9 +10493,10 @@ qemuDomainMigratePrepare3(virConnectPtr dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ uri_in, uri_out,
+- &def, flags);
++ &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+@@ -10511,6 +10517,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
+ const char *uri_in = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10538,7 +10545,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
+@@ -10548,9 +10555,10 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ uri_in, uri_out,
+- &def, flags);
++ &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+@@ -10570,6 +10578,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
+ {
+ virQEMUDriverPtr driver = dconn->privateData;
+ virDomainDefPtr def = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10580,7 +10589,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0)
+@@ -10589,9 +10598,10 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
+ ret = qemuMigrationPrepareTunnel(driver, dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+- st, &def, flags);
++ st, &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+@@ -10611,6 +10621,7 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+ virDomainDefPtr def = NULL;
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
++ char *origname = NULL;
+ int ret = -1;
+
+ virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
+@@ -10631,7 +10642,7 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+ goto cleanup;
+ }
+
+- if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname)))
++ if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
+ goto cleanup;
+
+ if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
+@@ -10640,9 +10651,10 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
+ ret = qemuMigrationPrepareTunnel(driver, dconn,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+- st, &def, flags);
++ st, &def, origname, flags);
+
+ cleanup:
++ VIR_FREE(origname);
+ virDomainDefFree(def);
+ return ret;
+ }
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 3dedfe8..5fd52c1 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -2161,6 +2161,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ char **cookieout,
+ int *cookieoutlen,
+ virDomainDefPtr *def,
++ const char *origname,
+ virStreamPtr st,
+ unsigned int port,
+ unsigned long flags)
+@@ -2173,7 +2174,6 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+ unsigned long long now;
+ qemuMigrationCookiePtr mig = NULL;
+ bool tunnel = !!st;
+- char *origname = NULL;
+ char *xmlout = NULL;
+ unsigned int cookieFlags;
+ virCapsPtr caps = NULL;
+@@ -2298,8 +2298,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
+
+ *def = NULL;
+ priv = vm->privateData;
+- priv->origname = origname;
+- origname = NULL;
++ if (VIR_STRDUP(priv->origname, origname) < 0)
++ goto cleanup;
+
+ if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
+ QEMU_MIGRATION_COOKIE_LOCKSTATE |
+@@ -2413,7 +2413,6 @@ done:
+
+ cleanup:
+ VIR_FREE(migrateFrom);
+- VIR_FREE(origname);
+ VIR_FREE(xmlout);
+ VIR_FORCE_CLOSE(dataFD[0]);
+ VIR_FORCE_CLOSE(dataFD[1]);
+@@ -2458,15 +2457,16 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+ int *cookieoutlen,
+ virStreamPtr st,
+ virDomainDefPtr *def,
++ const char *origname,
+ unsigned long flags)
+ {
+ int ret;
+
+ VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
+ "cookieout=%p, cookieoutlen=%p, st=%p, def=%p, "
+- "flags=%lx",
++ "origname=%s, flags=%lx",
+ driver, dconn, NULLSTR(cookiein), cookieinlen,
+- cookieout, cookieoutlen, st, *def, flags);
++ cookieout, cookieoutlen, st, *def, origname, flags);
+
+ if (st == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+@@ -2475,7 +2475,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+ }
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+- cookieout, cookieoutlen, def,
++ cookieout, cookieoutlen, def, origname,
+ st, 0, flags);
+ return ret;
+ }
+@@ -2491,6 +2491,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ const char *uri_in,
+ char **uri_out,
+ virDomainDefPtr *def,
++ const char *origname,
+ unsigned long flags)
+ {
+ static int port = 0;
+@@ -2503,10 +2504,10 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+
+ VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
+ "cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, "
+- "def=%p, flags=%lx",
++ "def=%p, origname=%s, flags=%lx",
+ driver, dconn, NULLSTR(cookiein), cookieinlen,
+ cookieout, cookieoutlen, NULLSTR(uri_in), uri_out,
+- *def, flags);
++ *def, origname, flags);
+
+ *uri_out = NULL;
+
+@@ -2595,7 +2596,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ VIR_DEBUG("Generated uri_out=%s", *uri_out);
+
+ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
+- cookieout, cookieoutlen, def,
++ cookieout, cookieoutlen, def, origname,
+ NULL, this_port, flags);
+ cleanup:
+ virURIFree(uri);
+@@ -2609,10 +2610,12 @@ cleanup:
+ virDomainDefPtr
+ qemuMigrationPrepareDef(virQEMUDriverPtr driver,
+ const char *dom_xml,
+- const char *dname)
++ const char *dname,
++ char **origname)
+ {
+ virCapsPtr caps = NULL;
+ virDomainDefPtr def;
++ char *name = NULL;
+
+ if (!dom_xml) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+@@ -2629,7 +2632,7 @@ qemuMigrationPrepareDef(virQEMUDriverPtr driver,
+ goto cleanup;
+
+ if (dname) {
+- VIR_FREE(def->name);
++ name = def->name;
+ if (VIR_STRDUP(def->name, dname) < 0) {
+ virDomainDefFree(def);
+ def = NULL;
+@@ -2638,6 +2641,10 @@ qemuMigrationPrepareDef(virQEMUDriverPtr driver,
+
+ cleanup:
+ virObjectUnref(caps);
++ if (def && origname)
++ *origname = name;
++ else
++ VIR_FREE(name);
+ return def;
+ }
+
+diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
+index 0f6c5f7..4af5aed 100644
+--- a/src/qemu/qemu_migration.h
++++ b/src/qemu/qemu_migration.h
+@@ -100,7 +100,8 @@ char *qemuMigrationBegin(virConnectPtr conn,
+
+ virDomainDefPtr qemuMigrationPrepareDef(virQEMUDriverPtr driver,
+ const char *dom_xml,
+- const char *dname);
++ const char *dname,
++ char **origname);
+
+ int qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+ virConnectPtr dconn,
+@@ -110,6 +111,7 @@ int qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
+ int *cookieoutlen,
+ virStreamPtr st,
+ virDomainDefPtr *def,
++ const char *origname,
+ unsigned long flags);
+
+ int qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+@@ -121,6 +123,7 @@ int qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
+ const char *uri_in,
+ char **uri_out,
+ virDomainDefPtr *def,
++ const char *origname,
+ unsigned long flags);
+
+ int qemuMigrationPerform(virQEMUDriverPtr driver,
+--
+1.8.3.2
+
--- /dev/null
+From 3b3b9b240e186546abf11b2683bf917be5fc854f Mon Sep 17 00:00:00 2001
+Message-Id: <3b3b9b240e186546abf11b2683bf917be5fc854f.1382534061.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Tue, 22 Oct 2013 16:24:47 +0100
+Subject: [PATCH] qemu: Make migration port range configurable
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1019237
+
+(cherry picked from commit e3ef20d7f7fee595ac4fc6094e04b7d65ee0583a)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu.conf | 11 +++++++++++
+ src/qemu/qemu_conf.c | 21 +++++++++++++++++++++
+ src/qemu/qemu_conf.h | 2 ++
+ src/qemu/qemu_driver.c | 4 ++--
+ src/qemu/test_libvirtd_qemu.aug.in | 2 ++
+ 5 files changed, 38 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
+index 541db64..4b59320 100644
+--- a/src/qemu/qemu.conf
++++ b/src/qemu/qemu.conf
+@@ -427,3 +427,14 @@
+ # Override the listen address for all incoming migrations. Defaults to
+ # 0.0.0.0 or :: in case if both host and qemu are capable of IPv6.
+ #migration_address = "127.0.0.1"
++
++
++# Override the port range used for incoming migrations.
++#
++# Minimum must be greater than 0, however when QEMU is not running as root,
++# setting the minimum to be lower than 1024 will not work.
++#
++# Maximum must not be greater than 65535.
++#
++#migration_port_min = 49152
++#migration_port_max = 49215
+diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
+index cea139d..e45180a 100644
+--- a/src/qemu/qemu_conf.c
++++ b/src/qemu/qemu_conf.c
+@@ -207,6 +207,9 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
+ cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
+ cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;
+
++ cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN;
++ cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX;
++
+ #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+ /* For privileged driver, try and find hugepage mount automatically.
+ * Non-privileged driver requires admin to create a dir for the
+@@ -440,6 +443,24 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
+ goto cleanup;
+ }
+
++ GET_VALUE_LONG("migration_port_min", cfg->migrationPortMin);
++ if (cfg->migrationPortMin <= 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("%s: migration_port_min: port must be greater than 0"),
++ filename);
++ goto cleanup;
++ }
++
++ GET_VALUE_LONG("migration_port_max", cfg->migrationPortMax);
++ if (cfg->migrationPortMax > 65535 ||
++ cfg->migrationPortMax < cfg->migrationPortMin) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("%s: migration_port_max: port must be between "
++ "the minimal port %d and 65535"),
++ filename, cfg->migrationPortMin);
++ goto cleanup;
++ }
++
+ p = virConfGetValue(conf, "user");
+ CHECK_TYPE("user", VIR_CONF_STRING);
+ if (p && p->str &&
+diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
+index 4acc67b..576a2e2 100644
+--- a/src/qemu/qemu_conf.h
++++ b/src/qemu/qemu_conf.h
+@@ -158,6 +158,8 @@ struct _virQEMUDriverConfig {
+
+ /* The default for -incoming */
+ char *migrationAddress;
++ int migrationPortMin;
++ int migrationPortMax;
+ };
+
+ /* Main driver state */
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 4a4880c..226e32d 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -688,8 +688,8 @@ qemuStateInitialize(bool privileged,
+ goto error;
+
+ if ((qemu_driver->migrationPorts =
+- virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
+- QEMU_MIGRATION_PORT_MAX)) == NULL)
++ virPortAllocatorNew(cfg->migrationPortMin,
++ cfg->migrationPortMax)) == NULL)
+ goto error;
+
+ if (qemuSecurityInit(qemu_driver) < 0)
+diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
+index be4518c..d6d55b8 100644
+--- a/src/qemu/test_libvirtd_qemu.aug.in
++++ b/src/qemu/test_libvirtd_qemu.aug.in
+@@ -67,3 +67,5 @@ module Test_libvirtd_qemu =
+ { "keepalive_count" = "5" }
+ { "seccomp_sandbox" = "1" }
+ { "migration_address" = "127.0.0.1" }
++{ "migration_port_min" = "1234" }
++{ "migration_port_max" = "12345" }
+--
+1.8.4
+
--- /dev/null
+From be42017f858b8227a7a2569eb80adbcb79342145 Mon Sep 17 00:00:00 2001
+Message-Id: <be42017f858b8227a7a2569eb80adbcb79342145.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:37 +0200
+Subject: [PATCH] qemu: Prefer VFIO for PCI device passthrough
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+Prefer using VFIO (if available) to the legacy KVM device passthrough.
+
+With this patch a PCI passthrough device without the driver configured
+will be started with VFIO if it's available on the host. If not legacy
+KVM passthrough is checked and error is reported if it's not available.
+
+(cherry picked from commit f094aaac48a6bbeef87a4df0345dfe2964297298)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/formatdomain.html.in | 9 ++++-----
+ src/conf/domain_conf.h | 2 +-
+ src/libvirt_private.syms | 1 +
+ src/qemu/qemu_command.c | 12 +++++++-----
+ src/qemu/qemu_hostdev.c | 30 +++++++++++++++++++++++++-----
+ src/qemu/qemu_hostdev.h | 4 +++-
+ src/qemu/qemu_hotplug.c | 2 +-
+ src/qemu/qemu_process.c | 15 ++++++++-------
+ tests/qemuxml2argvtest.c | 11 +++++++++++
+ 9 files changed, 61 insertions(+), 25 deletions(-)
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 4fecdee..512e0df 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -2704,11 +2704,10 @@
+ backend, which is compatible with UEFI SecureBoot) or "kvm"
+ (for the legacy device assignment handled directly by the KVM
+ kernel module)<span class="since">Since 1.0.5 (QEMU and KVM
+- only, requires kernel 3.6 or newer)</span>. Currently, "kvm"
+- is the default used by libvirt when not explicitly provided,
+- but since the two are functionally equivalent, this default
+- could be changed in the future with no impact to domains that
+- don't specify anything.
++ only, requires kernel 3.6 or newer)</span>. The default, when
++ the driver name is not explicitly specified, is to check wether
++ VFIO is available and use it if it's the case. If VFIO is not
++ available, the legacy "kvm" assignment is attempted.
+ </dd>
+ <dt><code>readonly</code></dt>
+ <dd>Indicates that the device is readonly, only supported by SCSI host
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 5a21576..5ad0318 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -398,7 +398,7 @@ enum virDomainHostdevSubsysType {
+
+ /* the backend driver used for PCI hostdev devices */
+ typedef enum {
+- VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* currently kvm, could change */
++ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* detect automaticaly, prefer VFIO */
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, /* force legacy kvm style */
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO, /* force vfio */
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 5e4de67..9a00dfe 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -261,6 +261,7 @@ virDomainHostdevFind;
+ virDomainHostdevInsert;
+ virDomainHostdevModeTypeToString;
+ virDomainHostdevRemove;
++virDomainHostdevSubsysPciBackendTypeToString;
+ virDomainHostdevSubsysTypeToString;
+ virDomainHubTypeFromString;
+ virDomainHubTypeToString;
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 9c9b956..78f07c8 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -5347,10 +5347,10 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
++ int backend = dev->source.subsys.u.pci.backend;
+
+- switch ((virDomainHostdevSubsysPciBackendType)
+- dev->source.subsys.u.pci.backend) {
+- case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
++ /* caller has to assign proper passthrough backend type */
++ switch ((virDomainHostdevSubsysPciBackendType) backend) {
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
+ virBufferAddLit(&buf, "pci-assign");
+ if (configfd && *configfd)
+@@ -5361,9 +5361,11 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
+ virBufferAddLit(&buf, "vfio-pci");
+ break;
+
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
+- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+- _("PCI passhthrough type needs to be specified"));
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("invalid PCI passthrough type '%s'"),
++ virDomainHostdevSubsysPciBackendTypeToString(backend));
+ break;
+ }
+
+diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
+index 7f3170d..81e0e88 100644
+--- a/src/qemu/qemu_hostdev.c
++++ b/src/qemu/qemu_hostdev.c
+@@ -564,7 +564,8 @@ qemuHostdevHostSupportsPassthroughLegacy(void)
+
+ static bool
+ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
+- size_t nhostdevs)
++ size_t nhostdevs,
++ virQEMUCapsPtr qemuCaps)
+ {
+ bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy();
+ bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
+@@ -581,6 +582,23 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
+ continue;
+
+ switch ((virDomainHostdevSubsysPciBackendType) *backend) {
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
++ if (supportsPassthroughVFIO &&
++ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
++ *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
++ } else if (supportsPassthroughKVM &&
++ (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIDEVICE) ||
++ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) {
++ *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
++ } else {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("host doesn't support passthrough of "
++ "host PCI devices"));
++ return false;
++ }
++
++ break;
++
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
+ if (!supportsPassthroughVFIO) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+@@ -589,7 +607,6 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
+ }
+ break;
+
+- case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
+ if (!supportsPassthroughKVM) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+@@ -613,7 +630,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ const char *name,
+ const unsigned char *uuid,
+ virDomainHostdevDefPtr *hostdevs,
+- int nhostdevs)
++ int nhostdevs,
++ virQEMUCapsPtr qemuCaps)
+ {
+ virPCIDeviceListPtr pcidevs;
+ int last_processed_hostdev_vf = -1;
+@@ -621,7 +639,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ int ret = -1;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
+- if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs))
++ if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps))
+ goto cleanup;
+
+ virObjectLock(driver->activePciHostdevs);
+@@ -1142,13 +1160,15 @@ cleanup:
+ int
+ qemuPrepareHostDevices(virQEMUDriverPtr driver,
+ virDomainDefPtr def,
++ virQEMUCapsPtr qemuCaps,
+ bool coldBoot)
+ {
+ if (!def->nhostdevs)
+ return 0;
+
+ if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid,
+- def->hostdevs, def->nhostdevs) < 0)
++ def->hostdevs, def->nhostdevs,
++ qemuCaps) < 0)
+ return -1;
+
+ if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0)
+diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
+index 327d4d5..272086e 100644
+--- a/src/qemu/qemu_hostdev.h
++++ b/src/qemu/qemu_hostdev.h
+@@ -37,7 +37,8 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ const char *name,
+ const unsigned char *uuid,
+ virDomainHostdevDefPtr *hostdevs,
+- int nhostdevs);
++ int nhostdevs,
++ virQEMUCapsPtr qemuCaps);
+ int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
+ bool mandatory,
+ virUSBDevicePtr *usb);
+@@ -50,6 +51,7 @@ int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver,
+ int nhostdevs);
+ int qemuPrepareHostDevices(virQEMUDriverPtr driver,
+ virDomainDefPtr def,
++ virQEMUCapsPtr qemuCaps,
+ bool coldBoot);
+ void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver,
+ const char *name,
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 0c42b0a..cdbafa7 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1018,7 +1018,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ return -1;
+
+ if (qemuPrepareHostdevPCIDevices(driver, vm->def->name, vm->def->uuid,
+- &hostdev, 1) < 0)
++ &hostdev, 1, priv->qemuCaps) < 0)
+ return -1;
+
+ switch ((virDomainHostdevSubsysPciBackendType) backend) {
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index f979877..b9f291d 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3540,6 +3540,12 @@ int qemuProcessStart(virConnectPtr conn,
+ goto cleanup;
+ }
+
++ VIR_DEBUG("Determining emulator version");
++ virObjectUnref(priv->qemuCaps);
++ if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
++ vm->def->emulator)))
++ goto cleanup;
++
+ /* network devices must be "prepared" before hostdevs, because
+ * setting up a network device might create a new hostdev that
+ * will need to be setup.
+@@ -3550,7 +3556,8 @@ int qemuProcessStart(virConnectPtr conn,
+
+ /* Must be run before security labelling */
+ VIR_DEBUG("Preparing host devices");
+- if (qemuPrepareHostDevices(driver, vm->def, !migrateFrom) < 0)
++ if (qemuPrepareHostDevices(driver, vm->def, priv->qemuCaps,
++ !migrateFrom) < 0)
+ goto cleanup;
+
+ VIR_DEBUG("Preparing chr devices");
+@@ -3632,12 +3639,6 @@ int qemuProcessStart(virConnectPtr conn,
+ }
+ }
+
+- VIR_DEBUG("Determining emulator version");
+- virObjectUnref(priv->qemuCaps);
+- if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
+- vm->def->emulator)))
+- goto cleanup;
+-
+ if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
+ goto cleanup;
+
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 23ea2ee..1d964ce 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -98,6 +98,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
+ virConnectPtr conn;
+ char *log = NULL;
+ virCommandPtr cmd = NULL;
++ size_t i;
+
+ if (!(conn = virGetConnect()))
+ goto out;
+@@ -154,6 +155,16 @@ static int testCompareXMLToArgvFiles(const char *xml,
+ if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0)
+ goto out;
+
++ for (i = 0; i < vmdef->nhostdevs; i++) {
++ virDomainHostdevDefPtr hostdev = vmdef->hostdevs[i];
++
++ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
++ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
++ hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
++ hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
++ }
++ }
++
+ if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr,
+ (flags & FLAG_JSON), extraFlags,
+ migrateFrom, migrateFd, NULL,
+--
+1.8.4
+
--- /dev/null
+From 0309361905e9b9ee674b740610f49ae273862939 Mon Sep 17 00:00:00 2001
+Message-Id: <0309361905e9b9ee674b740610f49ae273862939.1377873641.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 29 Aug 2013 19:21:11 +0200
+Subject: [PATCH] qemu: Remove hostdev entry when freeing the depending network
+ entry
+
+When using a <interface type="network"> that points to a network with
+hostdev forwarding mode a hostdev alias is created for the network. This
+allias is inserted into the hostdev list, but is backed with a part of
+the network object that it is connected to.
+
+When a VM is being stopped qemuProcessStop() calls
+networkReleaseActualDevice() which eventually frees the memory for the
+hostdev object. Afterwards when the domain definition is being freed by
+virDomainDefFree() an invalid pointer is accessed by
+virDomainHostdevDefFree() and may cause a crash of the daemon.
+
+This patch removes the entry in the hostdev list before freeing the
+depending memory to avoid this issue.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1002669 [7.0]
+ https://bugzilla.redhat.com/show_bug.cgi?id=1000973 [6.5]
+(cherry picked from commit 50348e6edfa10ddb61929bf95a1c4820a9614e19)
+---
+ src/conf/domain_conf.c | 26 ++++++++++++++++++--------
+ src/conf/domain_conf.h | 1 +
+ src/libvirt_private.syms | 1 +
+ src/qemu/qemu_hotplug.c | 5 +++++
+ src/qemu/qemu_process.c | 2 ++
+ 5 files changed, 27 insertions(+), 8 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 01f9bd0..1a20232 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -9936,26 +9936,36 @@ virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net)
+ return matchidx;
+ }
+
+-virDomainNetDefPtr
+-virDomainNetRemove(virDomainDefPtr def, size_t i)
+-{
+- virDomainNetDefPtr net = def->nets[i];
+
++void
++virDomainNetRemoveHostdev(virDomainDefPtr def,
++ virDomainNetDefPtr net)
++{
+ if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ /* hostdev net devices are normally also be in the hostdevs
+ * array, but might have already been removed by the time we
+ * get here.
+ */
+ virDomainHostdevDefPtr hostdev = &net->data.hostdev.def;
+- size_t h;
++ size_t i;
+
+- for (h = 0; h < def->nhostdevs; h++) {
+- if (def->hostdevs[h] == hostdev) {
+- virDomainHostdevRemove(def, h);
++ for (i = 0; i < def->nhostdevs; i++) {
++ if (def->hostdevs[i] == hostdev) {
++ virDomainHostdevRemove(def, i);
+ break;
+ }
+ }
+ }
++}
++
++
++virDomainNetDefPtr
++virDomainNetRemove(virDomainDefPtr def, size_t i)
++{
++ virDomainNetDefPtr net = def->nets[i];
++
++ virDomainNetRemoveHostdev(def, net);
++
+ if (def->nnets > 1) {
+ memmove(def->nets + i,
+ def->nets + i + 1,
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 536fc96..29ef0f8 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -2360,6 +2360,7 @@ int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net);
+ virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
+ int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
+ virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i);
++void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net);
+
+ int virDomainHostdevInsert(virDomainDefPtr def, virDomainHostdevDefPtr hostdev);
+ virDomainHostdevDefPtr
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index faa67ad..e6c23e4 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -302,6 +302,7 @@ virDomainNetGetActualVirtPortProfile;
+ virDomainNetGetActualVlan;
+ virDomainNetInsert;
+ virDomainNetRemove;
++virDomainNetRemoveHostdev;
+ virDomainNetTypeToString;
+ virDomainNostateReasonTypeFromString;
+ virDomainNostateReasonTypeToString;
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 7a6946e..cbe7072 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -940,6 +940,8 @@ cleanup:
+ virDomainNetGetActualBridgeName(net), net->ifname));
+ }
+
++ virDomainNetRemoveHostdev(vm->def, net);
++
+ networkReleaseActualDevice(net);
+ }
+
+@@ -1978,6 +1980,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
+ /* the changes above warrant replacing olddev with newdev in
+ * the domain's nets list.
+ */
++
++ /* this function doesn't work with HOSTDEV networks yet, thus
++ * no need to change the pointer in the hostdev structure */
+ networkReleaseActualDevice(olddev);
+ virDomainNetDefFree(olddev);
+ /* move newdev into the nets list, and NULL it out from the
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 0dccac3..6a28356 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -4234,6 +4234,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
+ virDomainNetGetActualBridgeName(net),
+ net->ifname));
+
++ /* kick the device out of the hostdev list too */
++ virDomainNetRemoveHostdev(def, net);
+ networkReleaseActualDevice(net);
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 9787da1f764c3a2fcccaf5f4dd5227dab5abb82d Mon Sep 17 00:00:00 2001
+Message-Id: <9787da1f764c3a2fcccaf5f4dd5227dab5abb82d.1379597660.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 17 Sep 2013 10:19:33 +0200
+Subject: [PATCH] qemu: Use "migratable" XML definition when doing external
+ checkpoints
+
+In the original implementation of external checkpoints I've mistakenly
+used the live definition to be stored in the save image. The normal
+approach is to use the "migratable" definition. This was discovered when
+commit 07966f6a8b5ccb5bb4c716b25deb8ba2e572cc67 changed the behavior to
+use a converted XML from the user to do the compatibility check to fix
+problem when using the regular machine saving.
+
+As the previous patch added a compatibility layer, we can now change the
+type of the XML in the image.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1008340
+(cherry picked from commit 1b7bfa65e36996fc3a204452d2a844ab9f4b52b3)
+---
+ src/qemu/qemu_driver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 9b9732d..71d773c 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -12427,7 +12427,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
+ JOB_MASK(QEMU_JOB_SUSPEND) |
+ JOB_MASK(QEMU_JOB_MIGRATION_OP));
+
+- if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, false)))
++ if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)))
+ goto endjob;
+
+ if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file,
+--
+1.8.3.2
+
--- /dev/null
+From 4ac6f237fe6ec1c681aab55b4745a14da51e1fd3 Mon Sep 17 00:00:00 2001
+Message-Id: <4ac6f237fe6ec1c681aab55b4745a14da51e1fd3.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:32 +0200
+Subject: [PATCH] qemu: Wire up better early error reporting
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+The previous patches added infrastructure to report better errors from
+monitor in some cases. This patch finalizes this "feature" by enabling
+this enhanced error reporting on early phases of VM startup. In these
+phases the possibility of qemu producing a useful error message is
+really high compared to running it during the whole life cycle. After
+the start up is complete, the feature is disabled to provide the usual
+error messages so that users are not confused by possibly irrelevant
+messages that may be in the domain log.
+
+The original motivation to do this enhancement is to capture errors when
+using VFIO device passthrough, where qemu reports errors after the
+monitor is initialized and the existing error catching code couldn't
+catch this producing a unhelpful message:
+
+ # virsh start test
+ error: Failed to start domain test
+ error: Unable to read from monitor: Connection reset by peer
+
+With this change, the message is changed to:
+
+ # virsh start test
+ error: Failed to start domain test
+ error: internal error: early end of file from monitor: possible problem:
+ qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: vfio: error, group 8 is not viable, please ensure all devices within the iommu_group are bound to their vfio bus driver.
+ qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: vfio: failed to get group 8
+ qemu-system-x86_64: -device vfio-pci,host=00:1a.0,id=hostdev0,bus=pci.0,addr=0x5: Device 'vfio-pci' could not be initialized
+
+(cherry picked from commit ef29de14c37d14abc546e90555a0093797facfdd)
+
+Conflicts:
+ src/qemu/qemu_process.c
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 29 +++++++++++++++++++----------
+ 1 file changed, 19 insertions(+), 10 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 063cd78..c991d04 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -1368,7 +1368,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
+ };
+
+ static int
+-qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm)
++qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int logfd)
+ {
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+@@ -1393,6 +1393,9 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm)
+ priv->monJSON,
+ &monitorCallbacks);
+
++ if (mon)
++ ignore_value(qemuMonitorSetDomainLog(mon, logfd));
++
+ virObjectLock(vm);
+ priv->monStart = 0;
+
+@@ -1767,10 +1770,11 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
+ virHashTablePtr paths = NULL;
+ qemuDomainObjPrivatePtr priv;
+
+- if (!virQEMUCapsUsedQMP(qemuCaps) && pos != -1) {
+- if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
+- return -1;
++ if (pos != -1 &&
++ (logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
++ return -1;
+
++ if (logfd != -1 && !virQEMUCapsUsedQMP(qemuCaps)) {
+ if (VIR_ALLOC_N(buf, buf_size) < 0)
+ goto closelog;
+
+@@ -1781,9 +1785,8 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
+ }
+
+ VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
+- if (qemuConnectMonitor(driver, vm) < 0) {
++ if (qemuConnectMonitor(driver, vm, logfd) < 0)
+ goto cleanup;
+- }
+
+ /* Try to get the pty path mappings again via the monitor. This is much more
+ * reliable if it's available.
+@@ -1810,14 +1813,15 @@ cleanup:
+ /* VM is dead, any other error raised in the interim is probably
+ * not as important as the qemu cmdline output */
+ if (virQEMUCapsUsedQMP(qemuCaps)) {
+- if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
+- return -1;
+-
+ if (VIR_ALLOC_N(buf, buf_size) < 0)
+ goto closelog;
+ }
+
+ len = strlen(buf);
++ /* best effor seek - we need to reset to the original position, so that
++ * a possible read of the fd in the monitor code doesn't influence this
++ * error delivery option */
++ lseek(logfd, pos, SEEK_SET);
+ qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("process exited while connecting to monitor: %s"),
+@@ -3052,7 +3056,7 @@ qemuProcessReconnect(void *opaque)
+ virObjectRef(obj);
+
+ /* XXX check PID liveliness & EXE path */
+- if (qemuConnectMonitor(driver, obj) < 0)
++ if (qemuConnectMonitor(driver, obj, -1) < 0)
+ goto error;
+
+ /* Failure to connect to agent shouldn't be fatal */
+@@ -4020,6 +4024,9 @@ int qemuProcessStart(virConnectPtr conn,
+ goto cleanup;
+ }
+
++ /* unset reporting errors from qemu log */
++ qemuMonitorSetDomainLog(priv->mon, -1);
++
+ virCommandFree(cmd);
+ VIR_FORCE_CLOSE(logfile);
+ virObjectUnref(cfg);
+@@ -4035,6 +4042,8 @@ cleanup:
+ virBitmapFree(nodemask);
+ virCommandFree(cmd);
+ VIR_FORCE_CLOSE(logfile);
++ if (priv->mon)
++ qemuMonitorSetDomainLog(priv->mon, -1);
+ qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stop_flags);
+ virObjectUnref(cfg);
+ virObjectUnref(caps);
+--
+1.8.4
+
--- /dev/null
+From d026ab3f17ab1d8b2b0e41c543dc09a3204319b3 Mon Sep 17 00:00:00 2001
+Message-Id: <d026ab3f17ab1d8b2b0e41c543dc09a3204319b3.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:23 -0600
+Subject: [PATCH] qemu: add dmi-to-pci-bridge controller
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+This PCI controller, named "dmi-to-pci-bridge" in the libvirt config,
+and implemented with qemu's "i82801b11-bridge" device, connects to a
+PCI Express slot (e.g. one of the slots provided by the pcie-root
+controller, aka "pcie.0" on the qemu commandline), and provides 31
+*non-hot-pluggable* PCI (*not* PCIe) slots, numbered 1-31.
+
+Any time a machine is defined which has a pcie-root controller
+(i.e. any q35-based machinetype), libvirt will automatically add a
+dmi-to-pci-bridge controller if one doesn't exist, and also add a
+pci-bridge controller. The reasoning here is that any useful domain
+will have either an immediate (startup time) or eventual (subsequent
+hot-plug) need for a standard PCI slot; since the pcie-root controller
+only provides PCIe slots, we need to connect a dmi-to-pci-bridge
+controller to it in order to get a non-hot-plug PCI slot that we can
+then use to connect a pci-bridge - the slots provided by the
+pci-bridge will be both standard PCI and hot-pluggable.
+
+Since pci-bridge devices themselves can not be hot-plugged into a
+running system (although you can hot-plug other devices into a
+pci-bridge's slots), any new pci-bridge controller that is added can
+(and will) be plugged into the dmi-to-pci-bridge as long as it has
+empty slots available.
+
+This patch is also changing the qemuxml2xml-pcie test from a "DO_TEST"
+to a "DO_DIFFERENT_TEST". This is so that the "before" xml can omit
+the automatically added dmi-to-pci-bridge and pci-bridge devices, and
+the "after" xml can include it - this way we are testing if libvirt is
+properly adding these devices.
+(cherry picked from commit 62ac6b43541e46605d62a569d6480c3de9805b98)
+---
+ docs/formatdomain.html.in | 26 +++++++++++++++--
+ docs/schemas/domaincommon.rng | 1 +
+ src/conf/domain_conf.c | 3 +-
+ src/conf/domain_conf.h | 1 +
+ src/qemu/qemu_capabilities.c | 2 ++
+ src/qemu/qemu_capabilities.h | 1 +
+ src/qemu/qemu_command.c | 33 ++++++++++++++++++++++
+ src/qemu/qemu_domain.c | 21 ++++++++++----
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 3 +-
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 7 +++++
+ tests/qemuxml2argvdata/qemuxml2argv-q35.xml | 25 ++++++++++++++++
+ tests/qemuxml2argvtest.c | 8 +++++-
+ .../qemuxml2xmlout-pcie-root.xml | 23 +++++++++++++++
+ tests/qemuxml2xmltest.c | 3 +-
+ 14 files changed, 145 insertions(+), 12 deletions(-)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35.xml
+ create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 55a6e71..562d991 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -2338,11 +2338,14 @@
+
+ <p>
+ PCI controllers have an optional <code>model</code> attribute with
+- possible values <code>pci-root</code>, <code>pcie-root</code>
+- or <code>pci-bridge</code>.
++ possible values <code>pci-root</code>, <code>pcie-root</code>,
++ <code>pci-bridge</code>, or <code>dmi-to-pci-bridge</code>.
+ For machine types which provide an implicit PCI bus, the pci-root
+ controller with index=0 is auto-added and required to use PCI devices.
+ pci-root has no address.
++ PCI bridges are auto-added if there are too many devices to fit on
++ the one bus provided by pci-root, or a PCI bus number greater than zero
++ was specified.
+ PCI bridges can also be specified manually, but their addresses should
+ only refer to PCI buses provided by already specified PCI controllers.
+ Leaving gaps in the PCI controller indexes might lead to an invalid
+@@ -2365,12 +2368,29 @@
+ the pcie-root controller with index=0 is auto-added to the
+ domain's configuration. pcie-root has also no address, provides
+ 31 slots (numbered 1-31) and can only be used to attach PCIe
+- devices. (<span class="since">since 1.1.2</span>).
++ devices. In order to connect standard PCI devices on a system
++ which has a pcie-root controller, a pci controller
++ with <code>model='dmi-to-pci-bridge'</code> is automatically
++ added. A dmi-to-pci-bridge controller plugs into a PCIe slot (as
++ provided by pcie-root), and itself provides 31 standard PCI
++ slots (which are not hot-pluggable). In order to have
++ hot-pluggable PCI slots in the guest system, a pci-bridge
++ controller will also be automatically created and connected to
++ one of the slots of the auto-created dmi-to-pci-bridge
++ controller; all guest devices with PCI addresses that are
++ auto-determined by libvirt will be placed on this pci-bridge
++ device. (<span class="since">since 1.1.2</span>).
+ </p>
+ <pre>
+ ...
+ <devices>
+ <controller type='pci' index='0' model='pcie-root'/>
++ <controller type='pci' index='1' model='dmi-to-pci-bridge'>
++ <address type='pci' domain='0' bus='0' slot='0xe' function='0'/>
++ </controller>
++ <controller type='pci' index='2' model='pci-bridge'>
++ <address type='pci' domain='0' bus='1' slot='1' function='0'/>
++ </controller>
+ </devices>
+ ...</pre>
+
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index e04be12..173359c 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -1540,6 +1540,7 @@
+ <value>pci-root</value>
+ <value>pcie-root</value>
+ <value>pci-bridge</value>
++ <value>dmi-to-pci-bridge</value>
+ </choice>
+ </attribute>
+ </group>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 02f1cf6..f46b17e 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -311,7 +311,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
+ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
+ "pci-root",
+ "pcie-root",
+- "pci-bridge")
++ "pci-bridge",
++ "dmi-to-pci-bridge")
+
+ VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
+ "auto",
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 68f36fd..536fc96 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -770,6 +770,7 @@ typedef enum {
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE,
++ VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE,
+
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
+ } virDomainControllerModelPCI;
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 08406b8..47cc07a 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -234,6 +234,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+
+ "vnc-share-policy", /* 150 */
+ "device-del-event",
++ "dmi-to-pci-bridge",
+ );
+
+ struct _virQEMUCaps {
+@@ -1381,6 +1382,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
+ { "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE },
+ { "vfio-pci", QEMU_CAPS_DEVICE_VFIO_PCI },
+ { "scsi-generic", QEMU_CAPS_DEVICE_SCSI_GENERIC },
++ { "i82801b11-bridge", QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE },
+ };
+
+ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index f5f685d..074e55d 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -190,6 +190,7 @@ enum virQEMUCapsFlags {
+ QEMU_CAPS_MLOCK = 149, /* -realtime mlock=on|off */
+ QEMU_CAPS_VNC_SHARE_POLICY = 150, /* set display sharing policy */
+ QEMU_CAPS_DEVICE_DEL_EVENT = 151, /* DEVICE_DELETED event */
++ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE = 152, /* -device i82801b11-bridge */
+
+ QEMU_CAPS_LAST, /* this must always be the last item */
+ };
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 8ac39ff..50f37ae 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1561,6 +1561,13 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus,
+ bus->minSlot = 1;
+ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
+ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
++ /* slots 1 - 31, standard PCI slots,
++ * but *not* hot-pluggable */
++ bus->flags = QEMU_PCI_CONNECT_TYPE_PCI;
++ bus->minSlot = 1;
++ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
++ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid PCI controller model %d"), model);
+@@ -1669,6 +1676,12 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ */
+ flags = QEMU_PCI_CONNECT_TYPE_PCI;
+ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
++ /* pci-bridge needs a PCIe slot, but it isn't
++ * hot-pluggable, so it doesn't need a hot-pluggable slot.
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
+ default:
+ break;
+ }
+@@ -2372,6 +2385,12 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ */
+ flags = QEMU_PCI_CONNECT_TYPE_PCI;
+ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
++ /* dmi-to-pci-bridge requires a non-hotplug PCIe
++ * slot
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
+ default:
+ flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
+ break;
+@@ -4351,6 +4370,20 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ virBufferAsprintf(&buf, "pci-bridge,chassis_nr=%d,id=pci.%d",
+ def->idx, def->idx);
+ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE)) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("The dmi-to-pci-bridge (i82801b11-bridge) "
++ "controller is not supported in this QEMU binary"));
++ goto error;
++ }
++ if (def->idx == 0) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("dmi-to-pci-bridge index should be > 0"));
++ goto error;
++ }
++ virBufferAsprintf(&buf, "i82801b11-bridge,id=pci.%d", def->idx);
++ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 40b813c..bdbe5a9 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -760,12 +760,23 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
+ return -1;
+
+- if (addPCIeRoot &&
+- virDomainDefMaybeAddController(
+- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+- VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0)
++ /* When a machine has a pcie-root, make sure that there is always
++ * a dmi-to-pci-bridge controller added as bus 1, and a pci-bridge
++ * as bus 2, so that standard PCI devices can be connected
++ */
++ if (addPCIeRoot) {
++ if (virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
++ VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0 ||
++ virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
++ VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) < 0 ||
++ virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 2,
++ VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) < 0) {
+ return -1;
+-
++ }
++ }
+ return 0;
+ }
+
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+index e937189..23db85c 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+@@ -1,4 +1,5 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
+ -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.1,addr=0x1 -usb
++-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
++-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 -usb
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+new file mode 100644
+index 0000000..ddff6f0
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -0,0 +1,7 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
++/usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
++-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
++-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
++-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
++-usb \
++-vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
+new file mode 100644
+index 0000000..3541b14
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
+@@ -0,0 +1,25 @@
++<domain type='qemu'>
++ <name>q35-test</name>
++ <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
++ <memory unit='KiB'>2097152</memory>
++ <currentMemory unit='KiB'>2097152</currentMemory>
++ <vcpu placement='static' cpuset='0-1'>2</vcpu>
++ <os>
++ <type arch='x86_64' machine='q35'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <controller type='pci' index='0' model='pcie-root'/>
++ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
++ <controller type='pci' index='2' model='pci-bridge'/>
++ <video>
++ <model type='qxl' ram='65536' vram='18432' heads='1'/>
++ </video>
++ <memballoon model='none'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 57c6989..aba0f88 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -995,7 +995,13 @@ mymain(void)
+ DO_TEST("pci-bridge-many-disks",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+ DO_TEST("pcie-root",
+- QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
++ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
++ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE);
++ DO_TEST("q35",
++ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
++ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
++ QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
++ QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL);
+
+ DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
+new file mode 100644
+index 0000000..25c77f1
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
+@@ -0,0 +1,23 @@
++<domain type='qemu'>
++ <name>q35-test</name>
++ <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
++ <memory unit='KiB'>2097152</memory>
++ <currentMemory unit='KiB'>2097152</currentMemory>
++ <vcpu placement='static' cpuset='0-1'>2</vcpu>
++ <os>
++ <type arch='x86_64' machine='q35'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <controller type='pci' index='0' model='pcie-root'/>
++ <controller type='usb' index='0'/>
++ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
++ <controller type='pci' index='2' model='pci-bridge'/>
++ <memballoon model='none'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index ea511b8..8b4590a 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -294,7 +294,8 @@ mymain(void)
+ DO_TEST_DIFFERENT("pci-bridge-many-disks");
+ DO_TEST_DIFFERENT("pci-autoadd-addr");
+ DO_TEST_DIFFERENT("pci-autoadd-idx");
+- DO_TEST("pcie-root");
++ DO_TEST_DIFFERENT("pcie-root");
++ DO_TEST("q35");
+
+ DO_TEST("hostdev-scsi-lsi");
+ DO_TEST("hostdev-scsi-virtio-scsi");
+--
+1.8.3.2
+
--- /dev/null
+From 29271efbf03fa88b54090dca46c42304a28c2fc3 Mon Sep 17 00:00:00 2001
+Message-Id: <29271efbf03fa88b54090dca46c42304a28c2fc3.1377873637.git.jdenemar@redhat.com>
+From: Guannan Ren <gren@redhat.com>
+Date: Thu, 8 Aug 2013 16:07:27 +0800
+Subject: [PATCH] qemu: add helper functions for diskchain checking
+
+Resovles: https://bugzilla.redhat.com/show_bug.cgi?id=910171
+(cherry picked from commit d7b7aa2c206951bef3b1bfece656394d1775cb7d)
+
+*src/util/virstoragefile.c: Add a helper function to get
+the first name of missing backing files, if the name is NULL,
+it means the diskchain is not broken.
+*src/qemu/qemu_domain.c: qemuDiskChainCheckBroken(disk) to
+check if its chain is broken
+---
+ src/libvirt_private.syms | 1 +
+ src/qemu/qemu_domain.c | 22 ++++++++++++++++++++++
+ src/qemu/qemu_domain.h | 3 +++
+ src/util/virstoragefile.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ src/util/virstoragefile.h | 2 ++
+ 5 files changed, 74 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 0247a46..9cfb84c 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1882,6 +1882,7 @@ virSocketAddrSetPort;
+
+
+ # util/virstoragefile.h
++virStorageFileChainGetBroken;
+ virStorageFileChainLookup;
+ virStorageFileFeatureTypeFromString;
+ virStorageFileFeatureTypeToString;
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 13303da..fd62deb 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -2228,6 +2228,28 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver,
+ }
+
+ int
++qemuDiskChainCheckBroken(virDomainDiskDefPtr disk)
++{
++ char *brokenFile = NULL;
++
++ if (!disk->src || !disk->backingChain)
++ return 0;
++
++ if (virStorageFileChainGetBroken(disk->backingChain, &brokenFile) < 0)
++ return -1;
++
++ if (brokenFile) {
++ virReportError(VIR_ERR_INVALID_ARG,
++ _("Backing file '%s' of image '%s' is missing."),
++ brokenFile, disk->src);
++ VIR_FREE(brokenFile);
++ return -1;
++ }
++
++ return 0;
++}
++
++int
+ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
+ virDomainDiskDefPtr disk,
+ bool force)
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index 9a959d6..0a4a51e 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -347,6 +347,9 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
+ int qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ bool start_with_state);
++
++int qemuDiskChainCheckBroken(virDomainDiskDefPtr disk);
++
+ int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
+ virDomainDiskDefPtr disk,
+ bool force);
+diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
+index cb6df91..0b9cec3 100644
+--- a/src/util/virstoragefile.c
++++ b/src/util/virstoragefile.c
+@@ -572,6 +572,13 @@ virFindBackingFile(const char *start, bool start_is_dir, const char *path,
+ goto cleanup;
+ }
+
++ if (virFileAccessibleAs(combined, F_OK, getuid(), getgid()) < 0) {
++ virReportSystemError(errno,
++ _("Cannot access backing file '%s'"),
++ combined);
++ goto cleanup;
++ }
++
+ if (!(*canonical = canonicalize_file_name(combined))) {
+ virReportSystemError(errno,
+ _("Can't canonicalize path '%s'"), path);
+@@ -1097,6 +1104,45 @@ virStorageFileGetMetadata(const char *path, int format,
+ }
+
+ /**
++ * virStorageFileChainCheckBroken
++ *
++ * If CHAIN is broken, set *brokenFile to the broken file name,
++ * otherwise set it to NULL. Caller MUST free *brokenFile after use.
++ * Return 0 on success, negative on error.
++ */
++int
++virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
++ char **brokenFile)
++{
++ virStorageFileMetadataPtr tmp;
++ int ret = -1;
++
++ if (!chain)
++ return 0;
++
++ *brokenFile = NULL;
++
++ tmp = chain;
++ while (tmp) {
++ /* Break if no backing store or backing store is not file */
++ if (!tmp->backingStoreRaw)
++ break;
++ if (!tmp->backingStore) {
++ if (VIR_STRDUP(*brokenFile, tmp->backingStoreRaw) < 0)
++ goto error;
++ break;
++ }
++ tmp = tmp->backingMeta;
++ }
++
++ ret = 0;
++
++error:
++ return ret;
++}
++
++
++/**
+ * virStorageFileFreeMetadata:
+ *
+ * Free pointers in passed structure and structure itself.
+diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
+index 4cb47e6..1f89839 100644
+--- a/src/util/virstoragefile.h
++++ b/src/util/virstoragefile.h
+@@ -90,6 +90,8 @@ virStorageFileMetadataPtr virStorageFileGetMetadata(const char *path,
+ virStorageFileMetadataPtr virStorageFileGetMetadataFromFD(const char *path,
+ int fd,
+ int format);
++int virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
++ char **broken_file);
+
+ const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain,
+ const char *start,
+--
+1.8.3.2
+
--- /dev/null
+From 484b6b06d7b1229836c6402591a7c047d62c95fd Mon Sep 17 00:00:00 2001
+Message-Id: <484b6b06d7b1229836c6402591a7c047d62c95fd.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:22 -0600
+Subject: [PATCH] qemu: add pcie-root controller
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+This controller is implicit on q35 machinetypes. It provides 31 PCIe
+(*not* PCI) slots as controller 0.
+
+Currently there are no devices that can connect to pcie-root, and no
+implicit pci controller on a q35 machine, so q35 is still
+unusable. For a usable q35 system, we need to add a
+"dmi-to-pci-bridge" pci controller, which can connect to pcie-root,
+and provides standard pci slots that can be used to connect other
+devices.
+(cherry picked from commit 48a3f48ac59a335b95b445e69f7e47f3e10d930e)
+---
+ docs/formatdomain.html.in | 29 ++++++++++++++++------
+ docs/schemas/domaincommon.rng | 1 +
+ src/conf/domain_conf.c | 8 +++---
+ src/conf/domain_conf.h | 1 +
+ src/qemu/qemu_command.c | 23 ++++++++++++++---
+ src/qemu/qemu_command.h | 4 ++-
+ src/qemu/qemu_domain.c | 19 +++++++++++---
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 4 +++
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml | 21 ++++++++++++++++
+ tests/qemuxml2argvtest.c | 2 ++
+ tests/qemuxml2xmltest.c | 1 +
+ 11 files changed, 93 insertions(+), 20 deletions(-)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 78e132e..55a6e71 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -2338,29 +2338,42 @@
+
+ <p>
+ PCI controllers have an optional <code>model</code> attribute with
+- possible values <code>pci-root</code> or <code>pci-bridge</code>.
+- For machine types which provide an implicit pci bus, the pci-root
++ possible values <code>pci-root</code>, <code>pcie-root</code>
++ or <code>pci-bridge</code>.
++ For machine types which provide an implicit PCI bus, the pci-root
+ controller with index=0 is auto-added and required to use PCI devices.
+- PCI root has no address.
+- PCI bridges are auto-added if there are too many devices to fit on
+- the one bus provided by pci-root, or a PCI bus number greater than zero
+- was specified.
++ pci-root has no address.
+ PCI bridges can also be specified manually, but their addresses should
+ only refer to PCI buses provided by already specified PCI controllers.
+ Leaving gaps in the PCI controller indexes might lead to an invalid
+ configuration.
+- (<span class="since">since 1.0.5</span>)
++ (pci-root and pci-bridge <span class="since">since 1.0.5</span>)
+ </p>
+ <pre>
+ ...
+ <devices>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='1' model='pci-bridge'>
+- <address type='pci' domain='0' bus='0' slot='5' function='0' multifunction=off'/>
++ <address type='pci' domain='0' bus='0' slot='5' function='0' multifunction='off'/>
+ </controller>
+ </devices>
+ ...</pre>
+
++ <p>
++ For machine types which provide an implicit PCI Express (PCIe)
++ bus (for example, the machine types based on the Q35 chipset),
++ the pcie-root controller with index=0 is auto-added to the
++ domain's configuration. pcie-root has also no address, provides
++ 31 slots (numbered 1-31) and can only be used to attach PCIe
++ devices. (<span class="since">since 1.1.2</span>).
++ </p>
++<pre>
++ ...
++ <devices>
++ <controller type='pci' index='0' model='pcie-root'/>
++ </devices>
++ ...</pre>
++
+ <h4><a name="elementsLease">Device leases</a></h4>
+
+ <p>
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 745b959..e04be12 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -1538,6 +1538,7 @@
+ <attribute name="model">
+ <choice>
+ <value>pci-root</value>
++ <value>pcie-root</value>
+ <value>pci-bridge</value>
+ </choice>
+ </attribute>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 18c6acf..02f1cf6 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -310,6 +310,7 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
+
+ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
+ "pci-root",
++ "pcie-root",
+ "pci-bridge")
+
+ VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
+@@ -5714,16 +5715,17 @@ virDomainControllerDefParseXML(xmlNodePtr node,
+ case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
+ switch (def->model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+- _("pci-root controller should not "
++ _("pci-root and pcie-root controllers should not "
+ "have an address"));
+ goto error;
+ }
+ if (def->idx != 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+- _("pci-root controller should have "
+- "index 0"));
++ _("pci-root and pcie-root controllers "
++ "should have index 0"));
+ goto error;
+ }
+
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index abf024c..68f36fd 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -768,6 +768,7 @@ enum virDomainControllerType {
+
+ typedef enum {
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT,
++ VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE,
+
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 2886e01..8ac39ff 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1453,6 +1453,12 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ "device. Device requires a standard PCI slot, "
+ "which is not provided by this bus"),
+ addr->domain, addr->bus);
++ } else if (devFlags & QEMU_PCI_CONNECT_TYPE_PCIE) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("PCI bus %.4x:%.2x is not compatible with the "
++ "device. Device requires a PCI Express slot, "
++ "which is not provided by this bus"),
++ addr->domain, addr->bus);
+ } else {
+ /* this should never happen. If it does, there is a
+ * bug in the code that sets the flag bits for devices.
+@@ -1549,6 +1555,12 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus,
+ bus->minSlot = 1;
+ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
+ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
++ /* slots 1 - 31, PCIe devices only, no hotplug */
++ bus->flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++ bus->minSlot = 1;
++ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
++ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid PCI controller model %d"), model);
+@@ -2350,7 +2362,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ continue;
+ switch (def->controllers[i]->model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+- /* pci-root is implicit in the machine,
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
++ /* pci-root and pcie-root are implicit in the machine,
+ * and needs no address */
+ continue;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+@@ -4339,8 +4352,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ def->idx, def->idx);
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+- _("wrong function called for pci-root"));
++ _("wrong function called for pci-root/pcie-root"));
+ return NULL;
+ }
+ break;
+@@ -7618,9 +7632,10 @@ qemuBuildCommandLine(virConnectPtr conn,
+ continue;
+ }
+
+- /* Skip pci-root */
++ /* Skip pci-root/pcie-root */
+ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
+- cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
++ (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT ||
++ cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) {
+ continue;
+ }
+
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index bf4953a..e5111d2 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -233,13 +233,15 @@ typedef enum {
+
+ QEMU_PCI_CONNECT_TYPE_PCI = 1 << 2,
+ /* PCI devices can connect to this bus */
++ QEMU_PCI_CONNECT_TYPE_PCIE = 1 << 3,
++ /* PCI Express devices can connect to this bus */
+ } qemuDomainPCIConnectFlags;
+
+ /* a combination of all bit that describe the type of connections
+ * allowed, e.g. PCI, PCIe, switch
+ */
+ # define QEMU_PCI_CONNECT_TYPES_MASK \
+- QEMU_PCI_CONNECT_TYPE_PCI
++ (QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE)
+
+
+ int qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 648121a..40b813c 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -701,6 +701,7 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ {
+ bool addDefaultUSB = true;
+ bool addPCIRoot = false;
++ bool addPCIeRoot = false;
+
+ /* check for emulator and create a default one if needed */
+ if (!def->emulator &&
+@@ -713,12 +714,16 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ case VIR_ARCH_X86_64:
+ if (!def->os.machine)
+ break;
+- if (STRPREFIX(def->os.machine, "pc-q35") ||
+- STREQ(def->os.machine, "q35") ||
+- STREQ(def->os.machine, "isapc")) {
++ if (STREQ(def->os.machine, "isapc")) {
+ addDefaultUSB = false;
+ break;
+ }
++ if (STRPREFIX(def->os.machine, "pc-q35") ||
++ STREQ(def->os.machine, "q35")) {
++ addPCIeRoot = true;
++ addDefaultUSB = false;
++ break;
++ }
+ if (!STRPREFIX(def->os.machine, "pc-0.") &&
+ !STRPREFIX(def->os.machine, "pc-1.") &&
+ !STRPREFIX(def->os.machine, "pc-i440") &&
+@@ -755,6 +760,12 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
+ return -1;
+
++ if (addPCIeRoot &&
++ virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
++ VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0)
++ return -1;
++
+ return 0;
+ }
+
+@@ -1421,7 +1432,7 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver,
+
+ if (pci && pci->idx == 0 &&
+ pci->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
+- VIR_DEBUG("Removing default 'pci-root' from domain '%s'"
++ VIR_DEBUG("Removing default pci-root from domain '%s'"
+ " for migration compatibility", def->name);
+ toremove++;
+ } else {
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+new file mode 100644
+index 0000000..e937189
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+@@ -0,0 +1,4 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
++-S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
++-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
++-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.1,addr=0x1 -usb
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
+new file mode 100644
+index 0000000..1aa5455
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
+@@ -0,0 +1,21 @@
++<domain type='qemu'>
++ <name>q35-test</name>
++ <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
++ <memory unit='KiB'>2097152</memory>
++ <currentMemory unit='KiB'>2097152</currentMemory>
++ <vcpu placement='static' cpuset='0-1'>2</vcpu>
++ <os>
++ <type arch='x86_64' machine='q35'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <controller type='pci' index='0' model='pcie-root'/>
++ <controller type='usb' index='0'/>
++ <memballoon model='none'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index b7485fc..57c6989 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -994,6 +994,8 @@ mymain(void)
+ DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+ DO_TEST("pci-bridge-many-disks",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
++ DO_TEST("pcie-root",
++ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+
+ DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index 66be40e..ea511b8 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -294,6 +294,7 @@ mymain(void)
+ DO_TEST_DIFFERENT("pci-bridge-many-disks");
+ DO_TEST_DIFFERENT("pci-autoadd-addr");
+ DO_TEST_DIFFERENT("pci-autoadd-idx");
++ DO_TEST("pcie-root");
+
+ DO_TEST("hostdev-scsi-lsi");
+ DO_TEST("hostdev-scsi-virtio-scsi");
+--
+1.8.3.2
+
--- /dev/null
+From 725fe06bebb3f2be2ff685064eccab320ff8aa4c Mon Sep 17 00:00:00 2001
+Message-Id: <725fe06bebb3f2be2ff685064eccab320ff8aa4c.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:41 -0600
+Subject: [PATCH] qemu: allow some PCI devices to be attached to PCIe slots
+
+Part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+Although most devices available in qemu area defined as PCI devices,
+and strictly speaking should only be attached via a PCI slot, in
+practice qemu allows them to be attached to a PCIe slot and sometimes
+this makes sense.
+
+For example, The UHCI and EHCI USB controllers are usually attached
+directly to the PCIe "root complex" (i.e. PCIe slots) on real
+hardware, so that should be possible for a Q35-based qemu virtual
+machine as well.
+
+We still want to prefer a standard PCI slot when auto-assigning
+addresses, though, and in general to disallow attaching PCI devices
+via PCIe slots.
+
+This patch makes that possible by adding a new
+QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG flag. Three things are done
+with this flag:
+
+1) It is set for the "pcie-root" controller
+
+2) qemuCollectPCIAddress() now has a set of nested switches that set
+this "EITHER" flag for devices that we want to allow connecting to
+pcie-root when specifically requested in the config.
+
+3) qemuDomainPCIAddressFlagsCompatible() adds this new flag to the
+"flagsMatchMask" if the address being checked came from config rather
+than being newly auto-allocated by libvirt (this knowledge is
+conveniently already available in the "fromConfig" arg).
+
+Now any device having the EITHER flag set can be connected to
+pcie-root if explicitly requested, but auto-allocated addresses for
+those devices will still be standard PCI slots instead.
+
+This patch only loosens the restrictions on devices that have been
+specifically requested, but the setup is such that it should be fairly
+easy to add new devices.
+
+(cherry picked from commit 07af519298996f4341f62542c31c1c01969eeceb)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---
+ src/qemu/qemu_command.h | 4 ++++
+ 2 files changed, 51 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 85eedd5..f025e8c 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1454,12 +1454,16 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ {
+ virErrorNumber errType = (fromConfig
+ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
++ qemuDomainPCIConnectFlags flagsMatchMask = QEMU_PCI_CONNECT_TYPES_MASK;
++
++ if (fromConfig)
++ flagsMatchMask |= QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG;
+
+ /* If this bus doesn't allow the type of connection (PCI
+ * vs. PCIe) required by the device, or if the device requires
+ * hot-plug and this bus doesn't have it, return false.
+ */
+- if (!(devFlags & busFlags & QEMU_PCI_CONNECT_TYPES_MASK)) {
++ if (!(devFlags & busFlags & flagsMatchMask)) {
+ if (reportError) {
+ if (devFlags & QEMU_PCI_CONNECT_TYPE_PCI) {
+ virReportError(errType,
+@@ -1578,8 +1582,12 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus,
+ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+- /* slots 1 - 31, PCIe devices only, no hotplug */
+- bus->flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++ /* slots 1 - 31, no hotplug, PCIe only unless the address was
++ * specified in user config *and* the particular device being
++ * attached also allows it
++ */
++ bus->flags = (QEMU_PCI_CONNECT_TYPE_PCIE |
++ QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
+ bus->minSlot = 1;
+ bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
+ break;
+@@ -1717,6 +1725,42 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ */
+ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
+ break;
++
++ case VIR_DOMAIN_CONTROLLER_TYPE_USB:
++ /* allow UHCI and EHCI controllers to be manually placed on
++ * the PCIe bus (but don't put them there automatically)
++ */
++ switch (device->data.controller->model) {
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
++ flags = (QEMU_PCI_CONNECT_TYPE_PCI |
++ QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
++ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
++ /* should this be PCIE-only? Or do we need to allow PCI
++ * for backward compatibility?
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
++ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
++ /* Allow these for PCI only */
++ break;
++ }
++ }
++ break;
++
++ case VIR_DOMAIN_DEVICE_SOUND:
++ switch (device->data.sound->model) {
++ case VIR_DOMAIN_SOUND_MODEL_ICH6:
++ flags = (QEMU_PCI_CONNECT_TYPE_PCI |
++ QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
++ break;
+ }
+ break;
+
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index a9854a3..47022e6 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -246,6 +246,10 @@ typedef enum {
+ /* PCI devices can connect to this bus */
+ QEMU_PCI_CONNECT_TYPE_PCIE = 1 << 3,
+ /* PCI Express devices can connect to this bus */
++ QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG = 1 << 4,
++ /* PCI *and* PCIe devices allowed, if the address
++ * was specified in the config by the user
++ */
+ } qemuDomainPCIConnectFlags;
+
+ /* a combination of all bit that describe the type of connections
+--
+1.8.3.2
+
--- /dev/null
+From 2e3465d664c764032bd133c545905639f459efbc Mon Sep 17 00:00:00 2001
+Message-Id: <2e3465d664c764032bd133c545905639f459efbc.1381871411.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 4 Oct 2013 01:53:09 -0600
+Subject: [PATCH] qemu: check actual netdev type rather than config netdev type
+ during init
+
+This resolves:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1012824 (RHEL7)
+ https://bugzilla.redhat.com/show_bug.cgi?id=1012834 (RHEL6)
+
+Note that a similar problem was reported in:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=827519
+
+but the fix only worked for <interface type='hostdev'>, *not* for
+<interface type='network'> where the network itself was a pool of
+hostdevs.
+
+The symptom in both cases was this error message:
+
+ internal error: Unable to determine device index for network device
+
+In both cases the cause was lack of proper handling for netdevs
+(<interface>) of type='hostdev' when scanning the netdev list looking
+for alias names in qemuAssignDeviceNetAlias() - those that aren't
+type='hostdev' have an alias of the form "net%d", while those that are
+hostdev use "hostdev%d". This special handling was completely lacking
+prior to the fix for Bug 827519 which was:
+
+When searching for the highest alias index, libvirt looks at the alias
+for each netdev and if it is type='hostdev' it ignores the entry. If
+the type is not hostdev, then it expects the "net%d" form; if it
+doesn't find that, it fails and logs the above error message.
+
+That fix works except in the case of <interface type='network'> where
+the network uses hostdev (i.e. the network is a pool of VFs to be
+assigned to the guests via PCI passthrough). In this case, the check
+for type='hostdev' would fail because it was done as:
+
+ def->net[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV
+
+(which compares what was written in the config) when it actually
+should have been:
+
+ virDomainNetGetActualType(def->net[i]) == VIR_DOMAIN_NET_TYPE_HOSTDEV
+
+(which compares the type of netdev that was actually allocated from
+the network at runtime).
+
+Of course the latter wouldn't be of any use if the netdevs of
+type='network' hadn't already acquired their actual network connection
+yet, but manual examination of the code showed that this is never the
+case.
+
+While looking through qemu_command.c, two other places were found to
+directly compare the net[i]->type field rather than getting actualType:
+
+* qemuAssignDeviceAliases() - in this case, the incorrect comparison
+ would cause us to create a "net%d" alias for a netdev with
+ type='network' but actualType='hostdev'. This alias would be
+ subsequently overwritten by the proper "hostdev%d" form, so
+ everything would operate properly, but a string would be
+ leaked. This patch also fixes this problem.
+
+* qemuAssignDevicePCISlots() - would defer assigning a PCI address to
+ a netdev if it was type='hostdev', but not for type='network +
+ actualType='hostdev'. In this case, the actual device usually hasn't
+ been acquired yet anyway, and even in the case that it has, there is
+ no practical difference between assigning a PCI address while
+ traversing the netdev list or while traversing the hostdev
+ list. Because changing it would be an effective NOP (but potentially
+ cause some unexpected regression), this usage was left unchanged.
+
+(cherry picked from commit 9881bfed2541faa428372b4513518b4b9ae1ab15)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 47b488a..dcce432 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -787,7 +787,8 @@ qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx)
+ for (i = 0; i < def->nnets; i++) {
+ int thisidx;
+
+- if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
++ if (virDomainNetGetActualType(def->nets[i])
++ == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ /* type='hostdev' interfaces have a hostdev%d alias */
+ continue;
+ }
+@@ -957,8 +958,9 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
+ /* type='hostdev' interfaces are also on the hostdevs list,
+ * and will have their alias assigned with other hostdevs.
+ */
+- if ((def->nets[i]->type != VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+- (qemuAssignDeviceNetAlias(def, def->nets[i], i) < 0)) {
++ if (virDomainNetGetActualType(def->nets[i])
++ != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
++ qemuAssignDeviceNetAlias(def, def->nets[i], i) < 0) {
+ return -1;
+ }
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 0ebc2077b69700849c366dd644911f47503bfbaa Mon Sep 17 00:00:00 2001
+Message-Id: <0ebc2077b69700849c366dd644911f47503bfbaa.1377873637.git.jdenemar@redhat.com>
+From: Guannan Ren <gren@redhat.com>
+Date: Thu, 8 Aug 2013 16:07:28 +0800
+Subject: [PATCH] qemu: check presence of each disk and its backing file as
+ well
+
+Resovles: https://bugzilla.redhat.com/show_bug.cgi?id=910171
+(cherry picked from commit dbca8414577a0d76a5bad9eb5919130db7bc451f)
+
+For disk with startupPolicy support, such as cdrom and floppy
+when its chain is broken, the startup policy will apply,
+otherwise, report an error.
+---
+ src/qemu/qemu_domain.c | 33 +++++++++++++--------------------
+ src/qemu/qemu_process.c | 6 ------
+ 2 files changed, 13 insertions(+), 26 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index fd62deb..d0f09ae 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -2084,19 +2084,11 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
+ break;
+
+ case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
+- virReportSystemError(errno,
+- _("cannot access file '%s'"),
+- disk->src);
+ goto error;
+- break;
+
+ case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
+- if (cold_boot) {
+- virReportSystemError(errno,
+- _("cannot access file '%s'"),
+- disk->src);
++ if (cold_boot)
+ goto error;
+- }
+ break;
+
+ case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
+@@ -2105,6 +2097,7 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
+ break;
+ }
+
++ virResetLastError();
+ VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
+ "due to inaccessible source '%s'",
+ disk->dst, vm->def->name, uuid, disk->src);
+@@ -2130,30 +2123,30 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ int ret = -1;
+ size_t i;
+ virDomainDiskDefPtr disk;
+- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
++ VIR_DEBUG("Checking for disk presence");
+ for (i = 0; i < vm->def->ndisks; i++) {
+ disk = vm->def->disks[i];
+
+- if (!disk->startupPolicy || !disk->src)
++ if (!disk->src)
+ continue;
+
+- if (virFileAccessibleAs(disk->src, F_OK,
+- cfg->user,
+- cfg->group) >= 0) {
+- /* disk accessible */
++ if (qemuDomainDetermineDiskChain(driver, disk, false) >= 0 &&
++ qemuDiskChainCheckBroken(disk) >= 0)
+ continue;
++
++ if (disk->startupPolicy) {
++ if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
++ cold_boot) >= 0)
++ continue;
+ }
+
+- if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
+- cold_boot) < 0)
+- goto cleanup;
++ goto error;
+ }
+
+ ret = 0;
+
+-cleanup:
+- virObjectUnref(cfg);
++error:
+ return ret;
+ }
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index d631a6f..0dccac3 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3621,16 +3621,10 @@ int qemuProcessStart(virConnectPtr conn,
+ if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
+ goto cleanup;
+
+- VIR_DEBUG("Checking for CDROM and floppy presence");
+ if (qemuDomainCheckDiskPresence(driver, vm,
+ flags & VIR_QEMU_PROCESS_START_COLD) < 0)
+ goto cleanup;
+
+- for (i = 0; i < vm->def->ndisks; i++) {
+- if (qemuDomainDetermineDiskChain(driver, vm->def->disks[i],
+- false) < 0)
+- goto cleanup;
+- }
+
+ /* Get the advisory nodeset from numad if 'placement' of
+ * either <vcpu> or <numatune> is 'auto'.
+--
+1.8.3.2
+
--- /dev/null
+From 83fad420027989538efa19d7009a65feb6524c28 Mon Sep 17 00:00:00 2001
+Message-Id: <83fad420027989538efa19d7009a65feb6524c28.1383922565.git.jdenemar@redhat.com>
+From: Zeng Junliang <zengjunliang@huawei.com>
+Date: Wed, 6 Nov 2013 15:22:26 +0100
+Subject: [PATCH] qemu: clean up migration ports when migration cancelled
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1019237
+
+If there's a migration cancelled, the bitmap of migration port should be
+cleaned up too.
+
+Signed-off-by: Zeng Junliang <zengjunliang@huawei.com>
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit c92ca769af2bacefdd451802d7eb1adac5e6597c)
+---
+ src/qemu/qemu_migration.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 4222a10..379e381 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -4381,12 +4381,16 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virCapsPtr caps = NULL;
++ unsigned short port;
+
+ VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
+ "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
+ driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
+ cookieout, cookieoutlen, flags, retcode);
+
++ port = priv->migrationPort;
++ priv->migrationPort = 0;
++
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+ goto cleanup;
+
+@@ -4433,8 +4437,6 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
+ }
+
+ qemuMigrationStopNBDServer(driver, vm, mig);
+- virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+- priv->migrationPort = 0;
+
+ if (flags & VIR_MIGRATE_PERSIST_DEST) {
+ virDomainDefPtr vmdef;
+@@ -4567,6 +4569,7 @@ endjob:
+ }
+
+ cleanup:
++ virPortAllocatorRelease(driver->migrationPorts, port);
+ if (vm) {
+ VIR_FREE(priv->origname);
+ virObjectUnlock(vm);
+--
+1.8.4.2
+
--- /dev/null
+From ecc34514032017857dcf514d8b7a83973f084e41 Mon Sep 17 00:00:00 2001
+Message-Id: <ecc34514032017857dcf514d8b7a83973f084e41.1380112457.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 23 Sep 2013 11:10:06 -0600
+Subject: [PATCH] qemu: don't leak vm on failure
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1010617
+
+Failure to attach to a domain during 'virsh qemu-attach' left
+the list of domains in an odd state:
+
+$ virsh qemu-attach 4176
+error: An error occurred, but the cause is unknown
+
+$ virsh list --all
+ Id Name State
+----------------------------------------------------
+ 2 foo shut off
+
+$ virsh qemu-attach 4176
+error: Requested operation is not valid: domain is already active as 'foo'
+
+$ virsh undefine foo
+error: Failed to undefine domain foo
+error: Requested operation is not valid: cannot undefine transient domain
+
+$ virsh shutdown foo
+error: Failed to shutdown domain foo
+error: invalid argument: monitor must not be NULL
+
+It all stems from leaving the list of domains unmodified on
+the initial failure; we should follow the lead of createXML
+which removes vm on failure (the actual initial failure still
+needs to be fixed in a later patch, but at least this patch
+gets us to the point where we aren't getting stuck with an
+unremovable "shut off" transient domain).
+
+While investigating, I also found a leak in qemuDomainCreateXML;
+the two functions should behave similarly. Note that there are
+still two unusual paths: if dom is not allocated, the user will
+see an OOM error even though the vm remains registered (but oom
+errors already indicate tricky cleanup); and if the vm starts
+and then quits again all before the job ends, it is possible
+to return a non-NULL dom even though the dom will no longer be
+useful for anything (but this at least lets the user know their
+short-lived vm ran).
+
+* src/qemu/qemu_driver.c (qemuDomainCreateXML): Don't leak vm on
+failure to obtain job.
+(qemuDomainQemuAttach): Match cleanup of qemuDomainCreateXML.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit d047b2d9835cbe5090e9eedb11ab69e7e4522f76)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_driver.c | 33 ++++++++++++++++++++-------------
+ 1 file changed, 20 insertions(+), 13 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index eb1a2ce..693dd85 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -1602,8 +1602,11 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
+
+ def = NULL;
+
+- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+- goto cleanup; /* XXXX free the 'vm' we created ? */
++ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
++ qemuDomainRemoveInactive(driver, vm);
++ vm = NULL;
++ goto cleanup;
++ }
+
+ if (qemuProcessStart(conn, driver, vm, NULL, -1, NULL, NULL,
+ VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
+@@ -1631,10 +1634,10 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
+ virDomainAuditStart(vm, "booted", true);
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+- if (dom) dom->id = vm->def->id;
++ if (dom)
++ dom->id = vm->def->id;
+
+- if (vm &&
+- qemuDomainObjEndJob(driver, vm) == 0)
++ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+
+ cleanup:
+@@ -13885,34 +13888,38 @@ static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn,
+
+ def = NULL;
+
+- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
++ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
++ qemuDomainRemoveInactive(driver, vm);
++ vm = NULL;
+ goto cleanup;
++ }
+
+ if (qemuProcessAttach(conn, driver, vm, pid,
+ pidfile, monConfig, monJSON) < 0) {
++ if (qemuDomainObjEndJob(driver, vm) > 0)
++ qemuDomainRemoveInactive(driver, vm);
++ vm = NULL;
+ monConfig = NULL;
+- goto endjob;
++ goto cleanup;
+ }
+
+ monConfig = NULL;
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+- if (dom) dom->id = vm->def->id;
++ if (dom)
++ dom->id = vm->def->id;
+
+-endjob:
+- if (qemuDomainObjEndJob(driver, vm) == 0) {
++ if (qemuDomainObjEndJob(driver, vm) == 0)
+ vm = NULL;
+- goto cleanup;
+- }
+
+ cleanup:
+ virDomainDefFree(def);
+- virObjectUnref(qemuCaps);
+ virDomainChrSourceDefFree(monConfig);
+ if (vm)
+ virObjectUnlock(vm);
+ VIR_FREE(pidfile);
+ virObjectUnref(caps);
++ virObjectUnref(qemuCaps);
+ return dom;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From c4255703d236874c2cb0f7f5a636315310b440ca Mon Sep 17 00:00:00 2001
+Message-Id: <c4255703d236874c2cb0f7f5a636315310b440ca.1380112457.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 23 Sep 2013 11:10:05 -0600
+Subject: [PATCH] qemu: don't leave shutdown inhibited on attach failure
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1010617
+
+While debugging a failure of 'virsh qemu-attach', I noticed that
+we were leaking the count of active domains on failure. This
+means that a libvirtd session that is supposed to quit after
+active domains disappear will hang around forever.
+
+* src/qemu/qemu_process.c (qemuProcessAttach): Undo count of
+active domains on failure.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 93e599750e5d5fff49c41a7f91570498a4b6de71)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 65 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 34 insertions(+), 31 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 1d8df58..843ff76 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -4334,6 +4334,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+ const char *model;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virCapsPtr caps = NULL;
++ bool active = false;
+
+ VIR_DEBUG("Beginning VM attach process");
+
+@@ -4345,7 +4346,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+ }
+
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+- goto cleanup;
++ goto error;
+
+ /* 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
+@@ -4353,60 +4354,59 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+ */
+ VIR_DEBUG("Setting current domain def as transient");
+ if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
+- goto cleanup;
++ goto error;
+
+ vm->def->id = qemuDriverAllocateID(driver);
+
+ if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
++ active = true;
+
+ if (virFileMakePath(cfg->logDir) < 0) {
+ virReportSystemError(errno,
+ _("cannot create log directory %s"),
+ cfg->logDir);
+- goto cleanup;
++ goto error;
+ }
+
+ VIR_FREE(priv->pidfile);
+ if (VIR_STRDUP(priv->pidfile, pidfile) < 0)
+- goto cleanup;
++ goto error;
+
+ VIR_DEBUG("Detect security driver config");
+ sec_managers = virSecurityManagerGetNested(driver->securityManager);
+- if (sec_managers == NULL) {
+- goto cleanup;
+- }
++ if (sec_managers == NULL)
++ goto error;
+
+ for (i = 0; sec_managers[i]; i++) {
+ model = virSecurityManagerGetModel(sec_managers[i]);
+ seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
+- if (seclabeldef == NULL) {
+- goto cleanup;
+- }
++ if (seclabeldef == NULL)
++ goto error;
+ seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
+ if (VIR_ALLOC(seclabel) < 0)
+- goto cleanup;
++ goto error;
+ if (virSecurityManagerGetProcessLabel(driver->securityManager,
+ vm->def, vm->pid, seclabel) < 0)
+- goto cleanup;
++ goto error;
+
+ if (VIR_STRDUP(seclabeldef->model, model) < 0)
+- goto cleanup;
++ goto error;
+
+ if (VIR_STRDUP(seclabeldef->label, seclabel->label) < 0)
+- goto cleanup;
++ goto error;
+ VIR_FREE(seclabel);
+ }
+
+ VIR_DEBUG("Creating domain log file");
+ if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
+- goto cleanup;
++ goto error;
+
+ VIR_DEBUG("Determining emulator version");
+ virObjectUnref(priv->qemuCaps);
+ if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
+ vm->def->emulator)))
+- goto cleanup;
++ goto error;
+
+ VIR_DEBUG("Preparing monitor state");
+ priv->monConfig = monConfig;
+@@ -4425,11 +4425,11 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+ VIR_DEBUG("Assigning domain PCI addresses");
+ if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
+- goto cleanup;
++ goto error;
+ }
+
+ if ((timestamp = virTimeStringNow()) == NULL) {
+- goto cleanup;
++ goto error;
+ } else {
+ if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
+ safewrite(logfile, ATTACH_POSTFIX, strlen(ATTACH_POSTFIX)) < 0) {
+@@ -4446,7 +4446,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+ VIR_DEBUG("Waiting for monitor to show up");
+ if (qemuProcessWaitForMonitor(driver, vm, priv->qemuCaps, -1) < 0)
+- goto cleanup;
++ goto error;
+
+ /* Failure to connect to agent shouldn't be fatal */
+ if (qemuConnectAgent(driver, vm) < 0) {
+@@ -4458,34 +4458,34 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+ VIR_DEBUG("Detecting VCPU PIDs");
+ if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
+- goto cleanup;
++ goto error;
+
+ /* If we have -device, then addresses are assigned explicitly.
+ * If not, then we have to detect dynamic ones here */
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+ VIR_DEBUG("Determining domain device PCI addresses");
+ if (qemuProcessInitPCIAddresses(driver, vm) < 0)
+- goto cleanup;
++ goto error;
+ }
+
+ VIR_DEBUG("Getting initial memory amount");
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+- goto cleanup;
++ goto error;
+ }
+ if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+- goto cleanup;
++ goto error;
+ }
+ if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+- goto cleanup;
++ goto error;
+ }
+ qemuDomainObjExitMonitor(driver, vm);
+
+ if (!virDomainObjIsActive(vm))
+- goto cleanup;
++ goto error;
+
+ if (running) {
+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+@@ -4502,7 +4502,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+ VIR_DEBUG("Writing domain status to disk");
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+- goto cleanup;
++ goto error;
+
+ /* Run an hook to allow admins to do some magic */
+ if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
+@@ -4518,7 +4518,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+ * If the script raised an error abort the launch
+ */
+ if (hookret < 0)
+- goto cleanup;
++ goto error;
+ }
+
+ VIR_FORCE_CLOSE(logfile);
+@@ -4529,10 +4529,13 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
+
+ return 0;
+
+-cleanup:
+- /* We jump here if we failed to start the VM for any reason, or
+- * if we failed to initialize the now running VM. kill it off and
+- * pretend we never started it */
++error:
++ /* We jump here if we failed to attach to the VM for any reason.
++ * Leave the domain running, but pretend we never attempted to
++ * attach to it. */
++ if (active && virAtomicIntDecAndTest(&driver->nactive) &&
++ driver->inhibitCallback)
++ driver->inhibitCallback(false, driver->inhibitOpaque);
+ VIR_FORCE_CLOSE(logfile);
+ VIR_FREE(seclabel);
+ VIR_FREE(sec_managers);
+--
+1.8.3.2
+
--- /dev/null
+From 3155b1327ffc178fea9ef96987dfbeb296862d58 Mon Sep 17 00:00:00 2001
+Message-Id: <3155b1327ffc178fea9ef96987dfbeb296862d58.1377873636.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:20 -0600
+Subject: [PATCH] qemu: eliminate almost-duplicate code in qemu_command.c
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+* The functions qemuDomainPCIAddressReserveAddr and
+qemuDomainPCIAddressReserveSlot were very similar (and should have
+been more similar) and were about to get more code added to them which
+would create even more duplicated code, so this patch gives
+qemuDomainPCIAddressReserveAddr a "reserveEntireSlot" arg, then
+replaces the body of qemuDomainPCIAddressReserveSlot with a call to
+qemuDomainPCIAddressReserveAddr.
+
+You will notice that addrs->lastaddr was previously set in
+qemuDomainPCIAddressReserveAddr (but *not* set in
+qemuDomainPCIAddressReserveSlot). For consistency and cleanliness of
+code, that bit was removed and put into the one caller of
+qemuDomainPCIAddressReserveAddr (there is a similar place where the
+caller of qemuDomainPCIAddressReserveSlot sets lastaddr). This does
+guarantee identical functionality to pre-patch code, but in practice
+isn't really critical, because lastaddr is just keeping track of where
+to start when looking for a free slot - if it isn't updated, we will
+just start looking on a slot that's already occupied, then skip up to
+one that isn't.
+
+* qemuCollectPCIAddress was essentially doing the same thing as
+qemuDomainPCIAddressReserveAddr, but with some extra special case
+checking at the beginning. The duplicate code has been replaced with
+a call to qemuDomainPCIAddressReserveAddr. This required adding a
+"fromConfig" boolean, which is only used to change the log error
+code from VIR_ERR_INTERNAL_ERROR (when the address was
+auto-generated by libvirt) to VIR_ERR_XML_ERROR (when the address is
+coming from the config); without this differentiation, it would be
+difficult to tell if an error was caused by something wrong in
+libvirt's auto-allocate code or just bad config.
+
+* the bit of code in qemuDomainPCIAddressValidate that checks the
+connect type flags is going to be used in a couple more places where
+we don't need to also check the slot limits (because we're generating
+the slot number ourselves), so that has been pulled out into a
+separate qemuDomainPCIAddressFlagsCompatible function.
+(cherry picked from commit 3bb0125766a301a9d99884e7cdb002ba5fa5df01)
+---
+ src/qemu/qemu_command.c | 232 ++++++++++++++++++++++++------------------------
+ src/qemu/qemu_command.h | 4 +-
+ 2 files changed, 119 insertions(+), 117 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 4345456..abc973a 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1434,9 +1434,53 @@ struct _qemuDomainPCIAddressSet {
+ };
+
+
+-/*
+- * Check that the PCI address is valid for use
+- * with the specified PCI address set.
++static bool
++qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
++ qemuDomainPCIConnectFlags busFlags,
++ qemuDomainPCIConnectFlags devFlags,
++ bool reportError)
++{
++ /* If this bus doesn't allow the type of connection (PCI
++ * vs. PCIe) required by the device, or if the device requires
++ * hot-plug and this bus doesn't have it, return false.
++ */
++ if (!(devFlags & busFlags & QEMU_PCI_CONNECT_TYPES_MASK)) {
++ if (reportError) {
++ if (devFlags & QEMU_PCI_CONNECT_TYPE_PCI) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("PCI bus %.4x:%.2x is not compatible with the "
++ "device. Device requires a standard PCI slot, "
++ "which is not provided by this bus"),
++ addr->domain, addr->bus);
++ } else {
++ /* this should never happen. If it does, there is a
++ * bug in the code that sets the flag bits for devices.
++ */
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("The device information has no PCI "
++ "connection types listed"));
++ }
++ }
++ return false;
++ }
++ if ((devFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE) &&
++ !(busFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE)) {
++ if (reportError) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("PCI bus %.4x:%.2x is not compatible with the "
++ "device. Device requires hot-plug capability, "
++ "which is not provided by the bus"),
++ addr->domain, addr->bus);
++ }
++ return false;
++ }
++ return true;
++}
++
++
++/* Verify that the address is in bounds for the chosen bus, and
++ * that the bus is of the correct type for the device (via
++ * comparing the flags).
+ */
+ static bool
+ qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
+@@ -1466,24 +1510,9 @@ qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
+ /* assure that at least one of the requested connection types is
+ * provided by this bus
+ */
+- if (!(flags & bus->flags & QEMU_PCI_CONNECT_TYPES_MASK)) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Invalid PCI address: The PCI controller "
+- "providing bus %04x doesn't support "
+- "connections appropriate for the device "
+- "(%x required vs. %x provided by bus)"),
+- addr->bus, flags & QEMU_PCI_CONNECT_TYPES_MASK,
+- bus->flags & QEMU_PCI_CONNECT_TYPES_MASK);
+- return false;
+- }
+- /* make sure this bus allows hot-plug if the caller demands it */
+- if ((flags & QEMU_PCI_CONNECT_HOTPLUGGABLE) &&
+- !(bus->flags & QEMU_PCI_CONNECT_HOTPLUGGABLE)) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Invalid PCI address: hot-pluggable slot requested, "
+- "but bus %04x doesn't support hot-plug"), addr->bus);
++ if (!qemuDomainPCIAddressFlagsCompatible(addr, bus->flags, flags, true))
+ return false;
+- }
++
+ /* some "buses" are really just a single port */
+ if (bus->minSlot && addr->slot < bus->minSlot) {
+ virReportError(VIR_ERR_XML_ERROR,
+@@ -1597,10 +1626,10 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr info,
+ void *opaque)
+ {
++ qemuDomainPCIAddressSetPtr addrs = opaque;
+ int ret = -1;
+- char *str = NULL;
+ virDevicePCIAddressPtr addr = &info->addr.pci;
+- qemuDomainPCIAddressSetPtr addrs = opaque;
++ bool entireSlot;
+ /* FIXME: flags should be set according to the requirements of @device */
+ qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
+ QEMU_PCI_CONNECT_TYPE_PCI);
+@@ -1639,56 +1668,15 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ return 0;
+ }
+
+- /* add an additional bus of the correct type if needed */
+- if (addrs->dryRun &&
+- qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
+- return -1;
+-
+- /* verify that the address is in bounds for the chosen bus, and
+- * that the bus is of the correct type for the device (via
+- * comparing the flags).
+- */
+- if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
+- return -1;
+-
+- if (!(str = qemuDomainPCIAddressAsString(addr)))
+- goto cleanup;
++ entireSlot = (addr->function == 0 &&
++ addr->multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON);
+
+- /* check if already in use */
+- if (addrs->buses[addr->bus].slots[addr->slot] & (1 << addr->function)) {
+- if (info->addr.pci.function != 0) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Attempted double use of PCI Address '%s' "
+- "(may need \"multifunction='on'\" for device on function 0)"),
+- str);
+- } else {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Attempted double use of PCI Address '%s'"), str);
+- }
++ if (qemuDomainPCIAddressReserveAddr(addrs, addr, flags,
++ entireSlot, true) < 0)
+ goto cleanup;
+- }
+
+- /* mark as in use */
+- if ((info->addr.pci.function == 0) &&
+- (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) {
+- /* a function 0 w/o multifunction=on must reserve the entire slot */
+- if (addrs->buses[addr->bus].slots[addr->slot]) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Attempted double use of PCI Address on slot '%s' "
+- "(need \"multifunction='off'\" for device "
+- "on function 0)"),
+- str);
+- goto cleanup;
+- }
+- addrs->buses[addr->bus].slots[addr->slot] = 0xFF;
+- VIR_DEBUG("Remembering PCI slot: %s (multifunction=off)", str);
+- } else {
+- VIR_DEBUG("Remembering PCI addr: %s", str);
+- addrs->buses[addr->bus].slots[addr->slot] |= 1 << addr->function;
+- }
+ ret = 0;
+ cleanup:
+- VIR_FREE(str);
+ return ret;
+ }
+
+@@ -1871,46 +1859,73 @@ static bool qemuDomainPCIAddressSlotInUse(qemuDomainPCIAddressSetPtr addrs,
+ }
+
+
++/*
++ * Reserve a slot (or just one function) for a device. If
++ * reserveEntireSlot is true, all functions for the slot are reserved,
++ * otherwise only one. If fromConfig is true, the address being
++ * requested came directly from the config and errors should be worded
++ * appropriately. If fromConfig is false, the address was
++ * automatically created by libvirt, so it is an internal error (not
++ * XML).
++ */
+ int
+ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+- qemuDomainPCIConnectFlags flags)
++ qemuDomainPCIConnectFlags flags,
++ bool reserveEntireSlot,
++ bool fromConfig)
+ {
+- char *str;
++ int ret = -1;
++ char *str = NULL;
+ qemuDomainPCIAddressBusPtr bus;
+-
+- if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
+- return -1;
++ virErrorNumber errType = (fromConfig
++ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+
+ if (!(str = qemuDomainPCIAddressAsString(addr)))
+- return -1;
++ goto cleanup;
+
+- VIR_DEBUG("Reserving PCI addr %s", str);
++ /* Add an extra bus if necessary */
++ if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
++ goto cleanup;
++ /* Check that the requested bus exists, is the correct type, and we
++ * are asking for a valid slot
++ */
++ if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
++ goto cleanup;
+
+ bus = &addrs->buses[addr->bus];
+- if ((bus->minSlot && addr->slot < bus->minSlot) ||
+- addr->slot > bus->maxSlot) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("Unable to reserve PCI address %s. "
+- "Slot %02x can't be used on bus %04x, "
+- "only slots %02zx - %02zx are permitted on this bus."),
+- str, addr->slot, addr->bus, bus->minSlot, bus->maxSlot);
+- }
+
+- if (bus->slots[addr->slot] & (1 << addr->function)) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("unable to reserve PCI address %s already in use"), str);
+- VIR_FREE(str);
+- return -1;
++ if (reserveEntireSlot) {
++ if (bus->slots[addr->slot]) {
++ virReportError(errType,
++ _("Attempted double use of PCI slot %s "
++ "(may need \"multifunction='on'\" for "
++ "device on function 0)"), str);
++ goto cleanup;
++ }
++ bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
++ VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", str);
++ } else {
++ if (bus->slots[addr->slot] & (1 << addr->function)) {
++ if (addr->function == 0) {
++ virReportError(errType,
++ _("Attempted double use of PCI Address %s"), str);
++ } else {
++ virReportError(errType,
++ _("Attempted double use of PCI Address %s "
++ "(may need \"multifunction='on'\" "
++ "for device on function 0)"), str);
++ }
++ goto cleanup;
++ }
++ bus->slots[addr->slot] |= (1 << addr->function);
++ VIR_DEBUG("Reserving PCI address %s", str);
+ }
+
++ ret = 0;
++cleanup:
+ VIR_FREE(str);
+-
+- addrs->lastaddr = *addr;
+- addrs->lastaddr.function = 0;
+- addrs->lastaddr.multi = 0;
+- bus->slots[addr->slot] |= 1 << addr->function;
+- return 0;
++ return ret;
+ }
+
+
+@@ -1919,26 +1934,7 @@ qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ qemuDomainPCIConnectFlags flags)
+ {
+- char *str;
+-
+- if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
+- return -1;
+-
+- if (!(str = qemuDomainPCIAddressAsString(addr)))
+- return -1;
+-
+- VIR_DEBUG("Reserving PCI slot %s", str);
+-
+- if (addrs->buses[addr->bus].slots[addr->slot]) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("unable to reserve PCI slot %s"), str);
+- VIR_FREE(str);
+- return -1;
+- }
+-
+- VIR_FREE(str);
+- addrs->buses[addr->bus].slots[addr->slot] = 0xFF;
+- return 0;
++ return qemuDomainPCIAddressReserveAddr(addrs, addr, flags, true, false);
+ }
+
+ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+@@ -2044,12 +2040,11 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
+ a.domain, a.bus, a.slot);
+ }
+-
+ }
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+- "%s", _("No more available PCI addresses"));
++ "%s", _("No more available PCI slots"));
+ return -1;
+
+ success:
+@@ -2409,9 +2404,14 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+
+ addr.bus = tmp_addr.bus;
+ addr.slot = tmp_addr.slot;
++
++ addrs->lastaddr = addr;
++ addrs->lastaddr.function = 0;
++ addrs->lastaddr.multi = 0;
+ }
+ /* Finally we can reserve the slot+function */
+- if (qemuDomainPCIAddressReserveAddr(addrs, &addr, flags) < 0)
++ if (qemuDomainPCIAddressReserveAddr(addrs, &addr, flags,
++ false, false) < 0)
+ goto error;
+
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index c9f1600..bf4953a 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -253,7 +253,9 @@ int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ qemuDomainPCIConnectFlags flags);
+ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+- qemuDomainPCIConnectFlags flags);
++ qemuDomainPCIConnectFlags flags,
++ bool reserveEntireSlot,
++ bool fromConfig);
+ int qemuDomainPCIAddressReserveNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev,
+ qemuDomainPCIConnectFlags flags);
+--
+1.8.3.2
+
--- /dev/null
+From 7d759a3c11fad02795b6ef9cdc091356353d8492 Mon Sep 17 00:00:00 2001
+Message-Id: <7d759a3c11fad02795b6ef9cdc091356353d8492.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:40 -0600
+Subject: [PATCH] qemu: eliminate redundant if clauses in qemuCollectPCIAddress
+
+Replace them with switch cases. This will make it more efficient when
+we add exceptions for more controller types, and other device types.
+
+This is a prerequisite for patches to resolve:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+(cherry picked from commit fbd9be484c3b1891412e9409d0133a07bbc3fc2b)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 57 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 32 insertions(+), 25 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index d596f09..85eedd5 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1689,37 +1689,44 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ /* Change flags according to differing requirements of different
+ * devices.
+ */
+- if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
+- device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+- switch (device->data.controller->model) {
+- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+- /* pci-bridge needs a PCI slot, but it isn't
+- * hot-pluggable, so it doesn't need a hot-pluggable slot.
+- */
+- flags = QEMU_PCI_CONNECT_TYPE_PCI;
++ switch (device->type) {
++ case VIR_DOMAIN_DEVICE_CONTROLLER:
++ switch (device->data.controller->type) {
++ case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
++ switch (device->data.controller->model) {
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
++ /* pci-bridge needs a PCI slot, but it isn't
++ * hot-pluggable, so it doesn't need a hot-pluggable slot.
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCI;
++ break;
++ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
++ /* pci-bridge needs a PCIe slot, but it isn't
++ * hot-pluggable, so it doesn't need a hot-pluggable slot.
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
++ default:
++ break;
++ }
+ break;
+- case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+- /* pci-bridge needs a PCIe slot, but it isn't
+- * hot-pluggable, so it doesn't need a hot-pluggable slot.
++
++ case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
++ /* SATA controllers aren't hot-plugged, and can be put in
++ * either a PCI or PCIe slot
+ */
+- flags = QEMU_PCI_CONNECT_TYPE_PCIE;
+- break;
+- default:
++ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
+ break;
+ }
+- }
+- /* SATA controllers aren't hot-plugged, and can be put in either a
+- * PCI or PCIe slot
+- */
+- if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
+- device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA)
+- flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
+
+- /* video cards aren't hot-plugged, and can be put in either a PCI
+- * or PCIe slot
+- */
+- if (device->type == VIR_DOMAIN_DEVICE_VIDEO)
++ case VIR_DOMAIN_DEVICE_VIDEO:
++ /* video cards aren't hot-plugged, and can be put in either a
++ * PCI or PCIe slot
++ */
+ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
++ break;
++ }
+
+ /* Ignore implicit controllers on slot 0:0:1.0:
+ * implicit IDE controller on 0:0:1.1 (no qemu command line)
+--
+1.8.3.2
+
--- /dev/null
+From efc2b6dc182a0d5a36b3791114f844bcc29e5e45 Mon Sep 17 00:00:00 2001
+Message-Id: <efc2b6dc182a0d5a36b3791114f844bcc29e5e45.1377873636.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:21 -0600
+Subject: [PATCH] qemu: enable auto-allocate of all PCI addresses
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+Previous refactoring of the guest PCI address reservation/allocation
+code allowed for slot types other than basic PCI (e.g. PCI express,
+non-hotpluggable slots, etc) but would not auto-allocate a slot for a
+device that required any type other than a basic hot-pluggable
+PCI slot.
+
+This patch refactors the code to be aware of different slot types
+during auto-allocation of addresses as well - as long as there is an
+empty slot of the required type, it will be found and used.
+
+The piece that *wasn't* added is that we don't auto-create a new PCI
+bus when needed for anything except basic PCI devices. This is because
+there are multiple different types of controllers that can provide,
+for example, a PCI express slot (in addition to the pcie-root
+controller, these can also be found on a "root-port" or on a
+"downstream-switch-port"). Since we currently don't support any PCIe
+devices (except pending support for dmi-to-pci-bridge), we can defer
+any decision on what to do about this.
+(cherry picked from commit c305783c65f2b552a08fc0e03e1d9b98157d91ca)
+---
+ src/qemu/qemu_command.c | 115 +++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 93 insertions(+), 22 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index abc973a..2886e01 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1429,6 +1429,7 @@ struct _qemuDomainPCIAddressSet {
+ qemuDomainPCIAddressBus *buses;
+ size_t nbuses;
+ virDevicePCIAddress lastaddr;
++ qemuDomainPCIConnectFlags lastFlags;
+ bool dryRun; /* on a dry run, new buses are auto-added
+ and addresses aren't saved in device infos */
+ };
+@@ -1630,7 +1631,7 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ int ret = -1;
+ virDevicePCIAddressPtr addr = &info->addr.pci;
+ bool entireSlot;
+- /* FIXME: flags should be set according to the requirements of @device */
++ /* flags may be changed from default below */
+ qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
+ QEMU_PCI_CONNECT_TYPE_PCI);
+
+@@ -1644,28 +1645,60 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ return 0;
+ }
+
++ /* Change flags according to differing requirements of different
++ * devices.
++ */
++ if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
++ device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
++ switch (device->data.controller->model) {
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
++ /* pci-bridge needs a PCI slot, but it isn't
++ * hot-pluggable, so it doesn't need a hot-pluggable slot.
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCI;
++ break;
++ default:
++ break;
++ }
++ }
++
+ /* Ignore implicit controllers on slot 0:0:1.0:
+ * implicit IDE controller on 0:0:1.1 (no qemu command line)
+ * implicit USB controller on 0:0:1.2 (-usb)
+ *
+ * If the machine does have a PCI bus, they will get reserved
+ * in qemuAssignDevicePCISlots().
+- *
+- * FIXME: When we have support for a pcie-root controller at bus
+- * 0, we will no longer be able to skip checking of these devices,
+- * as they are PCI, and thus can't be connected to bus 0 if it is
+- * PCIe rather than PCI.
++ */
++
++ /* These are the IDE and USB controllers in the PIIX3, hardcoded
++ * to bus 0 slot 1. They cannot be attached to a PCIe slot, only
++ * PCI.
+ */
+ if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 &&
+ addr->bus == 0 && addr->slot == 1) {
+ virDomainControllerDefPtr cont = device->data.controller;
+- if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
+- addr->function == 1)
+- return 0;
+- if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
+- (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
+- cont->model == -1) && addr->function == 2)
+- return 0;
++
++ if ((cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
++ addr->function == 1) ||
++ (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
++ (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
++ cont->model == -1) && addr->function == 2)) {
++ /* Note the check for nbuses > 0 - if there are no PCI
++ * buses, we skip this check. This is a quirk required for
++ * some machinetypes such as s390, which pretend to have a
++ * PCI bus for long enough to generate the "-usb" on the
++ * commandline, but that don't really care if a PCI bus
++ * actually exists. */
++ if (addrs->nbuses > 0 &&
++ !(addrs->buses[0].flags & QEMU_PCI_CONNECT_TYPE_PCI)) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Bus 0 must be PCI for integrated PIIX3 "
++ "USB or IDE controllers"));
++ return -1;
++ } else {
++ return 0;
++ }
++ }
+ }
+
+ entireSlot = (addr->function == 0 &&
+@@ -1695,8 +1728,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+ int nbuses = 0;
+ size_t i;
+ int rv;
+- qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
+- QEMU_PCI_CONNECT_TYPE_PCI);
++ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCI;
+
+ for (i = 0; i < def->ncontrollers; i++) {
+ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+@@ -1941,7 +1973,11 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+ {
+ int ret = 0;
+- /* FIXME: flags should be set according to the particular device */
++ /* Flags should be set according to the particular device,
++ * but only the caller knows the type of device. Currently this
++ * function is only used for hot-plug, though, and hot-plug is
++ * only supported for standard PCI devices, so we can safely use
++ * the setting below */
+ qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
+ QEMU_PCI_CONNECT_TYPE_PCI);
+
+@@ -2005,7 +2041,16 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr next_addr,
+ qemuDomainPCIConnectFlags flags)
+ {
+- virDevicePCIAddress a = addrs->lastaddr;
++ /* default to starting the search for a free slot from
++ * 0000:00:00.0
++ */
++ virDevicePCIAddress a = { 0, 0, 0, 0, false };
++
++ /* except if this search is for the exact same type of device as
++ * last time, continue the search from the previous match
++ */
++ if (flags == addrs->lastFlags)
++ a = addrs->lastaddr;
+
+ if (addrs->nbuses == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
+@@ -2014,6 +2059,12 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+
+ /* Start the search at the last used bus and slot */
+ for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
++ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
++ flags, false)) {
++ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
++ a.domain, a.bus);
++ continue;
++ }
+ for (; a.slot <= QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) {
+ if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
+ goto success;
+@@ -2030,9 +2081,15 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
+ return -1;
+ goto success;
+- } else {
++ } else if (flags == addrs->lastFlags) {
+ /* Check the buses from 0 up to the last used one */
+ for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
++ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
++ flags, false)) {
++ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
++ a.domain, a.bus);
++ continue;
++ }
+ for (a.slot = 1; a.slot <= QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) {
+ if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
+ goto success;
+@@ -2072,6 +2129,7 @@ qemuDomainPCIAddressReserveNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ }
+
+ addrs->lastaddr = addr;
++ addrs->lastFlags = flags;
+ return 0;
+ }
+
+@@ -2285,15 +2343,26 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ goto error;
+ }
+
+- flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
+-
+ /* PCI controllers */
+ for (i = 0; i < def->ncontrollers; i++) {
+ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+- if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
+- continue;
+ if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
++ switch (def->controllers[i]->model) {
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
++ /* pci-root is implicit in the machine,
++ * and needs no address */
++ continue;
++ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
++ /* pci-bridge doesn't require hot-plug
++ * (although it does provide hot-plug in its slots)
++ */
++ flags = QEMU_PCI_CONNECT_TYPE_PCI;
++ break;
++ default:
++ flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
++ break;
++ }
+ if (qemuDomainPCIAddressReserveNextSlot(addrs,
+ &def->controllers[i]->info,
+ flags) < 0)
+@@ -2301,6 +2370,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ }
+ }
+
++ flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
++
+ for (i = 0; i < def->nfss; i++) {
+ if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
+--
+1.8.3.2
+
--- /dev/null
+From bdc09433303e6240ee0dca47642f39c41dd3fd8a Mon Sep 17 00:00:00 2001
+Message-Id: <bdc09433303e6240ee0dca47642f39c41dd3fd8a.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:26 -0600
+Subject: [PATCH] qemu: enable using implicit sata controller in q35 machines
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+q35 machines have an implicit ahci (sata) controller at 00:1F.2 which
+has no "id" associated with it. For this reason, we can't refer to it
+as "ahci0". Instead, we don't give an id on the commandline, which
+qemu interprets as "use the first ahci controller". We then need to
+specify the unit with "unit=%d" rather than adding it onto the bus
+arg.
+(cherry picked from commit 83718cfe230dc4178940571090909b26d7af28d2)
+---
+ src/qemu/qemu_command.c | 23 ++++++++++++++++++++---
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 ++
+ tests/qemuxml2argvdata/qemuxml2argv-q35.xml | 5 +++++
+ tests/qemuxml2argvtest.c | 2 +-
+ tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 5 +++++
+ 5 files changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index c7e7826..a8fce22 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -4211,9 +4211,26 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
+ virBufferAddLit(&opt, "ide-drive");
+ }
+
+- virBufferAsprintf(&opt, ",bus=ahci%d.%d",
+- disk->info.addr.drive.controller,
+- disk->info.addr.drive.unit);
++ if (qemuDomainMachineIsQ35(def) &&
++ disk->info.addr.drive.controller == 0) {
++ /* Q35 machines have an implicit ahci (sata) controller at
++ * 00:1F.2 which has no "id" associated with it. For this
++ * reason, we can't refer to it as "ahci0". Instead, we
++ * don't give an id, which qemu interprets as "use the
++ * first ahci controller". We then need to specify the
++ * unit with "unit=%d" rather than adding it onto the bus
++ * arg.
++ */
++ virBufferAsprintf(&opt, ",unit=%d", disk->info.addr.drive.unit);
++ } else {
++ /* All other ahci controllers have been created by
++ * libvirt, so they *do* have an id, and we can identify
++ * them that way.
++ */
++ virBufferAsprintf(&opt, ",bus=ahci%d.%d",
++ disk->info.addr.drive.controller,
++ disk->info.addr.drive.unit);
++ }
+ break;
+ case VIR_DOMAIN_DISK_BUS_VIRTIO:
+ if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+index 5ff4bc7..9e67be5 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -3,4 +3,6 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
++-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-sata0-0-0 \
++-device ide-drive,unit=0,drive=drive-sata0-0-0,id=sata0-0-0 \
+ -vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
+index 3541b14..edaf6cb 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
+@@ -14,6 +14,11 @@
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <disk type='block' device='disk'>
++ <source dev='/dev/HostVG/QEMUGuest1'/>
++ <target dev='sda' bus='sata'/>
++ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
++ </disk>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
+ <controller type='pci' index='2' model='pci-bridge'/>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 0068d27..679124e 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -1001,7 +1001,7 @@ mymain(void)
+ DO_TEST("q35",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+- QEMU_CAPS_ICH9_AHCI,
++ QEMU_CAPS_DRIVE, QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+ QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL);
+
+diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
+index 2a86e61..96f8eaf 100644
+--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
+@@ -14,6 +14,11 @@
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <disk type='block' device='disk'>
++ <source dev='/dev/HostVG/QEMUGuest1'/>
++ <target dev='sda' bus='sata'/>
++ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
++ </disk>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
+ <controller type='pci' index='2' model='pci-bridge'/>
+--
+1.8.3.2
+
--- /dev/null
+From b10d4b798bf274abe9cf51b1fe4b8105e9abab7b Mon Sep 17 00:00:00 2001
+Message-Id: <b10d4b798bf274abe9cf51b1fe4b8105e9abab7b.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:24 -0600
+Subject: [PATCH] qemu: fix handling of default/implicit devices for q35
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+This patch adds in special handling for a few devices that need to be
+treated differently for q35 domains:
+
+usb - there is no implicit/default usb controller for the q35
+machinetype. This is done because normally the default usb controller
+is added to a domain by just adding "-usb" to the qemu commandline,
+and it's assumed that this will add a single piix3 usb1 controller at
+slot 1 function 2. That's not what happens when the machinetype is
+q35, though. Instead, adding -usb to the commandline adds 3 usb
+(version 2) controllers to the domain at slot 0x1D.{1,2,7}. Rather
+than having
+
+ <controller type='usb' index='0'/>
+
+translate into 3 separate devices on the PCI bus, it's cleaner to not
+automatically add a default usb device; one can always be added
+explicitly if desired. Or we may decide that on q35 machines, 3 usb
+controllers will be automatically added when none is given. But for
+this initial commit, at least we aren't locking ourselves into
+something we later won't want.
+
+video - qemu always initializes the primary video device immediately
+after any integrated devices for the machinetype. Unless instructed
+otherwise (by using "-device vga..." instead of "-vga" which libvirt
+uses in many cases to work around deficiencies and bugs in various
+qemu versions) qemu will always pick the first unused slot. In the
+case of the "pc" machinetype and its derivatives, this is always slot
+2, but on q35 machinetypes, the first free slot is slot 1 (since the
+q35's integrated peripheral devices are placed in other slots,
+e.g. slot 0x1f). In order to make the PCI address of the video device
+predictable, that slot (1 or 2, depending on machinetype) is reserved
+even when no video device has been specified.
+
+sata - a q35 machine always has a sata controller implicitly added at
+slot 0x1F, function 2. There is no way to avoid this controller, so we
+always add it. Note that the xml2xml tests for the pcie-root and q35
+cases were changed to use DO_TEST_DIFFERENT() so that we can check for
+the sata controller being automatically added. This is especially
+important because we can't check for it in the xml2argv output (it has
+no effect on that output since it's an implicit device).
+
+ide - q35 has no ide controllers.
+
+isa and smbus controllers - these two are always present in a q35 (at
+slot 0x1F functions 0 and 3) but we have no way of modelling them in
+our config. We do need to reserve those functions so that the user
+doesn't attempt to put anything else there though. (note that the "pc"
+machine type also has an ISA controller, which we also ignore).
+(cherry picked from commit c27b0bb171d9bdac10a93492a2a99eaa22746694)
+---
+ src/qemu/qemu_command.c | 159 ++++++++++++++++++++-
+ src/qemu/qemu_domain.c | 7 +
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 4 +-
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml | 1 -
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 3 +-
+ tests/qemuxml2argvtest.c | 2 +
+ .../qemuxml2xmlout-pcie-root.xml | 2 +-
+ tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 26 ++++
+ tests/qemuxml2xmltest.c | 2 +-
+ 9 files changed, 198 insertions(+), 8 deletions(-)
+ create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 50f37ae..3e07360 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1686,6 +1686,18 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ break;
+ }
+ }
++ /* SATA controllers aren't hot-plugged, and can be put in either a
++ * PCI or PCIe slot
++ */
++ if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
++ device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA)
++ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
++
++ /* video cards aren't hot-plugged, and can be put in either a PCI
++ * or PCIe slot
++ */
++ if (device->type == VIR_DOMAIN_DEVICE_VIDEO)
++ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE;
+
+ /* Ignore implicit controllers on slot 0:0:1.0:
+ * implicit IDE controller on 0:0:1.1 (no qemu command line)
+@@ -2258,6 +2270,12 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ }
+
+ if (def->nvideos > 0) {
++ /* Because the PIIX3 integrated IDE/USB controllers are
++ * already at slot 1, when qemu looks for the first free slot
++ * to place the VGA controller (which is always the first
++ * device added after integrated devices), it *always* ends up
++ * at slot 2.
++ */
+ virDomainVideoDefPtr primaryVideo = def->videos[0];
+ if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+@@ -2318,6 +2336,136 @@ error:
+ }
+
+
++static bool
++qemuDomainMachineIsQ35(virDomainDefPtr def)
++{
++ return (STRPREFIX(def->os.machine, "pc-q35") ||
++ STREQ(def->os.machine, "q35"));
++}
++
++
++static int
++qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
++ virQEMUCapsPtr qemuCaps,
++ qemuDomainPCIAddressSetPtr addrs)
++{
++ size_t i;
++ virDevicePCIAddress tmp_addr;
++ bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
++ virDevicePCIAddressPtr addrptr;
++ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCIE;
++
++ /* Verify that the first SATA controller is at 00:1F.2 */
++ /* the q35 machine type *always* has a SATA controller at this address */
++ for (i = 0; i < def->ncontrollers; i++) {
++ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA &&
++ def->controllers[i]->idx == 0) {
++ if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
++ if (def->controllers[i]->info.addr.pci.domain != 0 ||
++ def->controllers[i]->info.addr.pci.bus != 0 ||
++ def->controllers[i]->info.addr.pci.slot != 0x1F ||
++ def->controllers[i]->info.addr.pci.function != 2) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Primary SATA controller must have PCI address 0:0:1f.2"));
++ goto error;
++ }
++ } else {
++ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
++ def->controllers[i]->info.addr.pci.domain = 0;
++ def->controllers[i]->info.addr.pci.bus = 0;
++ def->controllers[i]->info.addr.pci.slot = 0x1F;
++ def->controllers[i]->info.addr.pci.function = 2;
++ }
++ }
++ }
++
++ /* Reserve slot 0x1F function 0 (ISA bridge, not in config model)
++ * and function 3 (SMBus, also not (yet) in config model). As with
++ * the SATA controller, these devices are always present in a q35
++ * machine; there is no way to not have them.
++ */
++ if (addrs->nbuses) {
++ memset(&tmp_addr, 0, sizeof(tmp_addr));
++ tmp_addr.slot = 0x1F;
++ tmp_addr.function = 0;
++ tmp_addr.multi = 1;
++ if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
++ false, false) < 0)
++ goto error;
++ tmp_addr.function = 3;
++ tmp_addr.multi = 0;
++ if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
++ false, false) < 0)
++ goto error;
++ }
++
++ if (def->nvideos > 0) {
++ /* NB: unlike the pc machinetypes, on q35 machinetypes the
++ * integrated devices are at slot 0x1f, so when qemu looks for
++ * the first free lot for the first VGA, it will always be at
++ * slot 1 (which was used up by the integrated PIIX3 devices
++ * on pc machinetypes).
++ */
++ virDomainVideoDefPtr primaryVideo = def->videos[0];
++ if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
++ primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
++ primaryVideo->info.addr.pci.domain = 0;
++ primaryVideo->info.addr.pci.bus = 0;
++ primaryVideo->info.addr.pci.slot = 1;
++ primaryVideo->info.addr.pci.function = 0;
++ addrptr = &primaryVideo->info.addr.pci;
++
++ if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
++ goto error;
++
++ if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
++ if (qemuDeviceVideoUsable) {
++ virResetLastError();
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &primaryVideo->info,
++ flags) < 0)
++ goto error;
++ } else {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("PCI address 0:0:1.0 is in use, "
++ "QEMU needs it for primary video"));
++ goto error;
++ }
++ } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) {
++ goto error;
++ }
++ } else if (!qemuDeviceVideoUsable) {
++ if (primaryVideo->info.addr.pci.domain != 0 ||
++ primaryVideo->info.addr.pci.bus != 0 ||
++ primaryVideo->info.addr.pci.slot != 1 ||
++ primaryVideo->info.addr.pci.function != 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Primary video card must have PCI address 0:0:1.0"));
++ goto error;
++ }
++ /* If TYPE==PCI, then qemuCollectPCIAddress() function
++ * has already reserved the address, so we must skip */
++ }
++ } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
++ memset(&tmp_addr, 0, sizeof(tmp_addr));
++ tmp_addr.slot = 1;
++
++ if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
++ VIR_DEBUG("PCI address 0:0:1.0 in use, future addition of a video"
++ " device will not be possible without manual"
++ " intervention");
++ virResetLastError();
++ } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
++ goto error;
++ }
++ }
++ return 0;
++
++error:
++ return -1;
++}
++
++
+ /*
+ * This assigns static PCI slots to all configured devices.
+ * The ordering here is chosen to match the ordering used
+@@ -2368,6 +2516,11 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ goto error;
+ }
+
++ if (qemuDomainMachineIsQ35(def) &&
++ qemuDomainValidateDevicePCISlotsQ35(def, qemuCaps, addrs) < 0) {
++ goto error;
++ }
++
+ /* PCI controllers */
+ for (i = 0; i < def->ncontrollers; i++) {
+ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+@@ -7679,6 +7832,9 @@ qemuBuildCommandLine(virConnectPtr conn,
+ _("SATA is not supported with this "
+ "QEMU binary"));
+ goto error;
++ } else if (cont->idx == 0 && qemuDomainMachineIsQ35(def)) {
++ /* first SATA controller on Q35 machines is implicit */
++ continue;
+ } else {
+ char *devstr;
+
+@@ -7692,6 +7848,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ }
+ } else if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+ cont->model == -1 &&
++ !qemuDomainMachineIsQ35(def) &&
+ (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI) ||
+ def->os.arch == VIR_ARCH_PPC64)) {
+ if (usblegacy) {
+@@ -7716,7 +7873,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ }
+ }
+
+- if (usbcontroller == 0)
++ if (usbcontroller == 0 && !qemuDomainMachineIsQ35(def))
+ virCommandAddArg(cmd, "-usb");
+
+ for (i = 0; i < def->nhubs; i++) {
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index bdbe5a9..dc72722 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -700,6 +700,7 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ void *opaque ATTRIBUTE_UNUSED)
+ {
+ bool addDefaultUSB = true;
++ bool addImplicitSATA = false;
+ bool addPCIRoot = false;
+ bool addPCIeRoot = false;
+
+@@ -722,6 +723,7 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ STREQ(def->os.machine, "q35")) {
+ addPCIeRoot = true;
+ addDefaultUSB = false;
++ addImplicitSATA = true;
+ break;
+ }
+ if (!STRPREFIX(def->os.machine, "pc-0.") &&
+@@ -754,6 +756,11 @@ qemuDomainDefPostParse(virDomainDefPtr def,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, -1) < 0)
+ return -1;
+
++ if (addImplicitSATA &&
++ virDomainDefMaybeAddController(
++ def, VIR_DOMAIN_CONTROLLER_TYPE_SATA, 0, -1) < 0)
++ return -1;
++
+ if (addPCIRoot &&
+ virDomainDefMaybeAddController(
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+index 23db85c..cecef7b 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+@@ -1,5 +1,5 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
+ -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
+--device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 -usb
++-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x2 \
++-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
+index 1aa5455..d7fb90c 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml
+@@ -15,7 +15,6 @@
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
+ <controller type='pci' index='0' model='pcie-root'/>
+- <controller type='usb' index='0'/>
+ <memballoon model='none'/>
+ </devices>
+ </domain>
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+index ddff6f0..6c24407 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -1,7 +1,6 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+ /usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
++-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x2 \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+--usb \
+ -vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index aba0f88..0068d27 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -995,11 +995,13 @@ mymain(void)
+ DO_TEST("pci-bridge-many-disks",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+ DO_TEST("pcie-root",
++ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE);
+ DO_TEST("q35",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
++ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+ QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL);
+
+diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
+index 25c77f1..f10e85b 100644
+--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
+@@ -15,7 +15,7 @@
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
+ <controller type='pci' index='0' model='pcie-root'/>
+- <controller type='usb' index='0'/>
++ <controller type='sata' index='0'/>
+ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
+ <controller type='pci' index='2' model='pci-bridge'/>
+ <memballoon model='none'/>
+diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
+new file mode 100644
+index 0000000..2a86e61
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml
+@@ -0,0 +1,26 @@
++<domain type='qemu'>
++ <name>q35-test</name>
++ <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
++ <memory unit='KiB'>2097152</memory>
++ <currentMemory unit='KiB'>2097152</currentMemory>
++ <vcpu placement='static' cpuset='0-1'>2</vcpu>
++ <os>
++ <type arch='x86_64' machine='q35'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/libexec/qemu-kvm</emulator>
++ <controller type='pci' index='0' model='pcie-root'/>
++ <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
++ <controller type='pci' index='2' model='pci-bridge'/>
++ <controller type='sata' index='0'/>
++ <video>
++ <model type='qxl' ram='65536' vram='18432' heads='1'/>
++ </video>
++ <memballoon model='none'/>
++ </devices>
++</domain>
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index 8b4590a..5c6730d 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -295,7 +295,7 @@ mymain(void)
+ DO_TEST_DIFFERENT("pci-autoadd-addr");
+ DO_TEST_DIFFERENT("pci-autoadd-idx");
+ DO_TEST_DIFFERENT("pcie-root");
+- DO_TEST("q35");
++ DO_TEST_DIFFERENT("q35");
+
+ DO_TEST("hostdev-scsi-lsi");
+ DO_TEST("hostdev-scsi-virtio-scsi");
+--
+1.8.3.2
+
--- /dev/null
+From 26ad7ab7a6c2b626d79bde63f9a5199d8ed9362a Mon Sep 17 00:00:00 2001
+Message-Id: <26ad7ab7a6c2b626d79bde63f9a5199d8ed9362a.1382534061.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Mon, 21 Oct 2013 10:13:00 -0600
+Subject: [PATCH] qemu: fix removal of <interface type='hostdev'>
+
+This patch (and the two patches that precede it) resolve:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1005682
+
+When libvirt was changed to delay the final cleanup of device removal
+until the qemu process had signaled it with a DEVICE_DELETED event for
+that device, the hostdev removal function
+(qemuDomainRemoveHostDevice()) was written to properly handle the
+removal of a hostdev that was actually an SRIOV virtual function
+(defined with <interface type='hostdev'>). However, the function used
+to search for a device matching the alias name provided in the
+DEVICE_DELETED message (virDomainDefFindDevice()) would search through
+the list of netdevs before hostdevs, so qemuDomainRemoveHostDevice()
+was never called; instead the netdev function,
+qemuDomainRemoveNetDevice() (which *doesn't* properly cleanup after
+removal of <interface type='hostdev'>), was called.
+
+(As a reminder - each <interface type='hostdev'> results in a
+virDomainNetDef which contains a virDomainHostdevDef having a parent
+type of VIR_DOMAIN_DEVICE_NET, and parent.data.net pointing back to
+the virDomainNetDef; both Defs point to the same device info object
+(and the info contains the device's "alias", which is used by qemu to
+identify the device). The virDomainHostdevDef is added to the domain's
+hostdevs list *and* the virDomainNetDef is added to the domain's nets
+list, so searching either list for a particular alias will yield a
+positive result.)
+
+This function modifies the qemuDomainRemoveNetDevice() to short
+circuit itself and call qemu DomainRemoveHostDevice() instead when the
+actual device is a VIR_DOMAIN_NET_TYPE_HOSTDEV (similar logic to what
+is done in the higher level qemuDomainDetachNetDevice())
+
+Note that even if virDomainDefFindDevice() changes in the future so
+that it finds the hostdev entry first, the current code will continue
+to work properly.
+
+(cherry picked from commit 69e047ae214d92feea6e54dfe821b1498d0004a9)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 4d29e18..f87b893 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -2471,6 +2471,12 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
+ virDomainEventPtr event;
+ size_t i;
+
++ if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
++ /* this function handles all hostdev and netdev cleanup */
++ qemuDomainRemoveHostDevice(driver, vm, virDomainNetGetActualHostdev(net));
++ return;
++ }
++
+ VIR_DEBUG("Removing network interface %s from domain %p %s",
+ net->info.alias, vm, vm->def->name);
+
+--
+1.8.4
+
--- /dev/null
+From 676f5e9952f7cbc09ad54d77e09d864f61874a6d Mon Sep 17 00:00:00 2001
+Message-Id: <676f5e9952f7cbc09ad54d77e09d864f61874a6d.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:36 +0200
+Subject: [PATCH] qemu: hostdev: Add checks if PCI passthrough is available in
+ the host
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+Add code to check availability of PCI passhthrough using VFIO and the
+legacy KVM passthrough and use it when starting VMs and hotplugging
+devices to live machine.
+
+(cherry picked from commit 467b561ac2ca7cb968d7a1d781e715cdd7bf3d14)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hostdev.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 125 insertions(+)
+
+diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
+index 4127abd..7f3170d 100644
+--- a/src/qemu/qemu_hostdev.c
++++ b/src/qemu/qemu_hostdev.c
+@@ -23,6 +23,11 @@
+
+ #include <config.h>
+
++#include <dirent.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include <errno.h>
++
+ #include "qemu_hostdev.h"
+ #include "virlog.h"
+ #include "virerror.h"
+@@ -31,6 +36,7 @@
+ #include "virusb.h"
+ #include "virscsi.h"
+ #include "virnetdev.h"
++#include "virfile.h"
+
+ #define VIR_FROM_THIS VIR_FROM_QEMU
+
+@@ -486,6 +492,122 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
+ }
+
+
++static bool
++qemuHostdevHostSupportsPassthroughVFIO(void)
++{
++ DIR *iommuDir = NULL;
++ struct dirent *iommuGroup = NULL;
++ bool ret = false;
++
++ /* condition 1 - /sys/kernel/iommu_groups/ contains entries */
++ if (!(iommuDir = opendir("/sys/kernel/iommu_groups/")))
++ goto cleanup;
++
++ while ((iommuGroup = readdir(iommuDir))) {
++ /* skip ./ ../ */
++ if (STRPREFIX(iommuGroup->d_name, "."))
++ continue;
++
++ /* assume we found a group */
++ break;
++ }
++
++ if (!iommuGroup)
++ goto cleanup;
++ /* okay, iommu is on and recognizes groups */
++
++ /* condition 2 - /dev/vfio/vfio exists */
++ if (!virFileExists("/dev/vfio/vfio"))
++ goto cleanup;
++
++ ret = true;
++
++cleanup:
++ if (iommuDir)
++ closedir(iommuDir);
++
++ return ret;
++}
++
++
++#if HAVE_LINUX_KVM_H
++# include <linux/kvm.h>
++static bool
++qemuHostdevHostSupportsPassthroughLegacy(void)
++{
++ int kvmfd = -1;
++ bool ret = false;
++
++ if ((kvmfd = open("/dev/kvm", O_RDONLY)) < 0)
++ goto cleanup;
++
++# ifdef KVM_CAP_IOMMU
++ if ((ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IOMMU)) <= 0)
++ goto cleanup;
++
++ ret = true;
++# endif
++
++cleanup:
++ VIR_FORCE_CLOSE(kvmfd);
++
++ return ret;
++}
++#else
++static bool
++qemuHostdevHostSupportsPassthroughLegacy(void)
++{
++ return false;
++}
++#endif
++
++
++static bool
++qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
++ size_t nhostdevs)
++{
++ bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy();
++ bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
++ size_t i;
++
++ /* assign defaults for hostdev passthrough */
++ for (i = 0; i < nhostdevs; i++) {
++ virDomainHostdevDefPtr hostdev = hostdevs[i];
++ int *backend = &hostdev->source.subsys.u.pci.backend;
++
++ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
++ continue;
++ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
++ continue;
++
++ switch ((virDomainHostdevSubsysPciBackendType) *backend) {
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
++ if (!supportsPassthroughVFIO) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("host doesn't support VFIO PCI passthrough"));
++ return false;
++ }
++ break;
++
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
++ if (!supportsPassthroughKVM) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("host doesn't support legacy PCI passthrough"));
++ return false;
++ }
++
++ break;
++
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
++ break;
++ }
++ }
++
++ return true;
++}
++
++
+ int
+ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ const char *name,
+@@ -499,6 +621,9 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+ int ret = -1;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
++ if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs))
++ goto cleanup;
++
+ virObjectLock(driver->activePciHostdevs);
+ virObjectLock(driver->inactivePciHostdevs);
+
+--
+1.8.4
+
--- /dev/null
+From b6784357c6f65806e2fd70d9b2e6982b89587685 Mon Sep 17 00:00:00 2001
+Message-Id: <b6784357c6f65806e2fd70d9b2e6982b89587685.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:35 +0200
+Subject: [PATCH] qemu: hostdev: Fix function spacing and header formatting
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+(cherry picked from commit f24150b1f53530e0ec057405665b771c776af9ac)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hostdev.c | 60 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 42 insertions(+), 18 deletions(-)
+
+diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
+index 21fe47f..4127abd 100644
+--- a/src/qemu/qemu_hostdev.c
++++ b/src/qemu/qemu_hostdev.c
+@@ -85,6 +85,7 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs)
+ return list;
+ }
+
++
+ /*
+ * qemuGetActivePciHostDeviceList - make a new list with a *copy* of
+ * every virPCIDevice object that is found on the activePciHostdevs
+@@ -128,8 +129,10 @@ qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver,
+ return list;
+ }
+
+-int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
+- virDomainDefPtr def)
++
++int
++qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
++ virDomainDefPtr def)
+ {
+ virDomainHostdevDefPtr hostdev = NULL;
+ virPCIDevicePtr dev = NULL;
+@@ -188,6 +191,7 @@ cleanup:
+ return ret;
+ }
+
++
+ int
+ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver,
+ virDomainDefPtr def)
+@@ -274,8 +278,10 @@ cleanup:
+ return ret;
+ }
+
++
+ static int
+-qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, char **sysfs_path)
++qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev,
++ char **sysfs_path)
+ {
+ virPCIDeviceAddress config_address;
+
+@@ -287,6 +293,7 @@ qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, char **sysfs_path)
+ return virPCIDeviceAddressGetSysfsFile(&config_address, sysfs_path);
+ }
+
++
+ int
+ qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev)
+ {
+@@ -303,6 +310,7 @@ qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev)
+ return ret;
+ }
+
++
+ static int
+ qemuDomainHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
+ int *vf)
+@@ -331,6 +339,7 @@ cleanup:
+ return ret;
+ }
+
++
+ static int
+ qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
+ virNetDevVPortProfilePtr virtPort,
+@@ -370,6 +379,7 @@ qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
+ return ret;
+ }
+
++
+ int
+ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
+ const unsigned char *uuid,
+@@ -438,6 +448,7 @@ cleanup:
+ return ret;
+ }
+
++
+ int
+ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
+ char *stateDir)
+@@ -474,11 +485,13 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
+ return ret;
+ }
+
+-int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
+- const char *name,
+- const unsigned char *uuid,
+- virDomainHostdevDefPtr *hostdevs,
+- int nhostdevs)
++
++int
++qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
++ const char *name,
++ const unsigned char *uuid,
++ virDomainHostdevDefPtr *hostdevs,
++ int nhostdevs)
+ {
+ virPCIDeviceListPtr pcidevs;
+ int last_processed_hostdev_vf = -1;
+@@ -670,6 +683,7 @@ cleanup:
+ return ret;
+ }
+
++
+ int
+ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
+ const char *name,
+@@ -722,6 +736,7 @@ error:
+ return -1;
+ }
+
++
+ int
+ qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
+ bool mandatory,
+@@ -809,6 +824,7 @@ out:
+ return 0;
+ }
+
++
+ static int
+ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver,
+ virDomainDefPtr def,
+@@ -878,6 +894,7 @@ cleanup:
+ return ret;
+ }
+
++
+ int
+ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver,
+ const char *name,
+@@ -996,9 +1013,11 @@ cleanup:
+ return -1;
+ }
+
+-int qemuPrepareHostDevices(virQEMUDriverPtr driver,
+- virDomainDefPtr def,
+- bool coldBoot)
++
++int
++qemuPrepareHostDevices(virQEMUDriverPtr driver,
++ virDomainDefPtr def,
++ bool coldBoot)
+ {
+ if (!def->nhostdevs)
+ return 0;
+@@ -1022,7 +1041,8 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver,
+ * Pre-condition: driver->inactivePciHostdevs & driver->activePciHostdevs
+ * are locked
+ */
+-void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver)
++void
++qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver)
+ {
+ int retries = 100;
+
+@@ -1052,10 +1072,11 @@ void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver)
+ }
+
+
+-void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
+- const char *name,
+- virDomainHostdevDefPtr *hostdevs,
+- int nhostdevs)
++void
++qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
++ const char *name,
++ virDomainHostdevDefPtr *hostdevs,
++ int nhostdevs)
+ {
+ virPCIDeviceListPtr pcidevs;
+ size_t i;
+@@ -1140,6 +1161,7 @@ cleanup:
+ virObjectUnref(cfg);
+ }
+
++
+ static void
+ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
+ const char *name,
+@@ -1203,6 +1225,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
+ virObjectUnlock(driver->activeUsbHostdevs);
+ }
+
++
+ void
+ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver,
+ const char *name,
+@@ -1272,8 +1295,9 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver,
+ virObjectUnlock(driver->activeScsiHostdevs);
+ }
+
+-void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
+- virDomainDefPtr def)
++void
++qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
++ virDomainDefPtr def)
+ {
+ if (!def->nhostdevs)
+ return;
+--
+1.8.4
+
--- /dev/null
+From 3dfc4bd4183907b922c4f154720826605ac4c51e Mon Sep 17 00:00:00 2001
+Message-Id: <3dfc4bd4183907b922c4f154720826605ac4c51e.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:34 +0200
+Subject: [PATCH] qemu: hostdev: Refactor PCI passhrough handling
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+To simplify future patches dealing with this code, simplify and refactor
+some conditions to switch statements.
+
+(cherry picked from commit 9d13298901f2edb375d54a710480a6bf994cb0e5)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 27 ++++++++++++++++++---------
+ src/qemu/qemu_hotplug.c | 27 ++++++++++++++++-----------
+ 2 files changed, 34 insertions(+), 20 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index d455847..9c9b956 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -5348,14 +5348,25 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+- if (dev->source.subsys.u.pci.backend
+- == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+- virBufferAddLit(&buf, "vfio-pci");
+- } else {
++ switch ((virDomainHostdevSubsysPciBackendType)
++ dev->source.subsys.u.pci.backend) {
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
+ virBufferAddLit(&buf, "pci-assign");
+ if (configfd && *configfd)
+ virBufferAsprintf(&buf, ",configfd=%s", configfd);
++ break;
++
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
++ virBufferAddLit(&buf, "vfio-pci");
++ break;
++
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("PCI passhthrough type needs to be specified"));
++ break;
+ }
++
+ virBufferAsprintf(&buf, ",host=%.2x:%.2x.%.1x",
+ dev->source.subsys.u.pci.addr.bus,
+ dev->source.subsys.u.pci.addr.slot,
+@@ -9036,7 +9047,6 @@ qemuBuildCommandLine(virConnectPtr conn,
+ VIR_FREE(devstr);
+ }
+
+-
+ /* Add host passthrough hardware */
+ for (i = 0; i < def->nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+@@ -9109,9 +9119,9 @@ qemuBuildCommandLine(virConnectPtr conn,
+ /* PCI */
+ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
++ int backend = hostdev->source.subsys.u.pci.backend;
+
+- if (hostdev->source.subsys.u.pci.backend
+- == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
++ if (backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("VFIO PCI device assignment is not "
+@@ -9125,8 +9135,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+ char *configfd_name = NULL;
+- if ((hostdev->source.subsys.u.pci.backend
+- != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) &&
++ if ((backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) &&
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) {
+ int configfd = qemuOpenPCIConfig(hostdev);
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 7e884c0..0c42b0a 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1012,6 +1012,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ int configfd = -1;
+ char *configfd_name = NULL;
+ bool releaseaddr = false;
++ int backend = hostdev->source.subsys.u.pci.backend;
+
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
+ return -1;
+@@ -1020,10 +1021,8 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ &hostdev, 1) < 0)
+ return -1;
+
+- if (hostdev->source.subsys.u.pci.backend
+- == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+- unsigned long long memKB;
+-
++ switch ((virDomainHostdevSubsysPciBackendType) backend) {
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("VFIO PCI device assignment is not "
+@@ -1035,11 +1034,18 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ * In this case, the guest's memory may already be locked, but it
+ * doesn't hurt to "change" the limit to the same value.
+ */
+- vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+- memKB = vm->def->mem.hard_limit ?
+- vm->def->mem.hard_limit : vm->def->mem.max_balloon + 1024 * 1024;
+- virProcessSetMaxMemLock(vm->pid, memKB);
+- vm->def->hostdevs[vm->def->nhostdevs--] = NULL;
++ if (vm->def->mem.hard_limit)
++ virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit);
++ else
++ virProcessSetMaxMemLock(vm->pid,
++ vm->def->mem.max_balloon + (1024 * 1024));
++
++ break;
++
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
++ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
++ break;
+ }
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+@@ -1048,8 +1054,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, hostdev->info) < 0)
+ goto error;
+ releaseaddr = true;
+- if ((hostdev->source.subsys.u.pci.backend
+- != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) &&
++ if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) {
+ configfd = qemuOpenPCIConfig(hostdev);
+ if (configfd >= 0) {
+--
+1.8.4
+
--- /dev/null
+From 93617e955bbad37f73c800cbb962b30551f2ccad Mon Sep 17 00:00:00 2001
+Message-Id: <93617e955bbad37f73c800cbb962b30551f2ccad.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:27 -0600
+Subject: [PATCH] qemu: improve error reporting during PCI address validation
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+This patch addresses two concerns with the error reporting when an
+incompatible PCI address is specified for a device:
+
+1) It wasn't always apparent which device had the problem. With this
+patch applied, any error about an incompatible address will always
+contain the full address as given in the config, so it will be easier
+to determine which device's config aused the problem.
+
+2) In some cases when the problem came from bad config, the error
+message was erroneously classified as VIR_ERR_INTERNAL_ERROR. With
+this patch applied, the same error message will be changed to indicate
+either "internal" or "xml" error depending on whether the address came
+from the config, or was automatically generated by libvirt.
+
+Note that in the case of "internal" (due to bad auto-generation)
+errors, the PCI address won't be of much use in finding the location
+in config to change (because it was automatically generated). Of
+course that makes perfect sense, but still the address could provide a
+clue about a bug in libvirt attempting to use a type of pci bus that
+doesn't have its flags set correctly (or something similar). In other
+words, it's not perfect, but it is definitely better.
+(cherry picked from commit c033e210613b860bef4859a81e22088d0d2f0f29)
+---
+ src/qemu/qemu_command.c | 224 +++++++++++++++++++++++++++++-------------------
+ 1 file changed, 138 insertions(+), 86 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index a8fce22..b811e1d 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1445,10 +1445,15 @@ struct _qemuDomainPCIAddressSet {
+
+ static bool
+ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
++ const char *addrStr,
+ qemuDomainPCIConnectFlags busFlags,
+ qemuDomainPCIConnectFlags devFlags,
+- bool reportError)
++ bool reportError,
++ bool fromConfig)
+ {
++ virErrorNumber errType = (fromConfig
++ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
++
+ /* If this bus doesn't allow the type of connection (PCI
+ * vs. PCIe) required by the device, or if the device requires
+ * hot-plug and this bus doesn't have it, return false.
+@@ -1456,24 +1461,24 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ if (!(devFlags & busFlags & QEMU_PCI_CONNECT_TYPES_MASK)) {
+ if (reportError) {
+ if (devFlags & QEMU_PCI_CONNECT_TYPE_PCI) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("PCI bus %.4x:%.2x is not compatible with the "
+- "device. Device requires a standard PCI slot, "
+- "which is not provided by this bus"),
+- addr->domain, addr->bus);
++ virReportError(errType,
++ _("PCI bus is not compatible with the device "
++ "at %s. Device requires a standard PCI slot, "
++ "which is not provided by bus %.4x:%.2x"),
++ addrStr, addr->domain, addr->bus);
+ } else if (devFlags & QEMU_PCI_CONNECT_TYPE_PCIE) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("PCI bus %.4x:%.2x is not compatible with the "
+- "device. Device requires a PCI Express slot, "
+- "which is not provided by this bus"),
+- addr->domain, addr->bus);
++ virReportError(errType,
++ _("PCI bus is not compatible with the device "
++ "at %s. Device requires a PCI Express slot, "
++ "which is not provided by bus %.4x:%.2x"),
++ addrStr, addr->domain, addr->bus);
+ } else {
+ /* this should never happen. If it does, there is a
+ * bug in the code that sets the flag bits for devices.
+ */
+- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+- _("The device information has no PCI "
+- "connection types listed"));
++ virReportError(errType,
++ _("The device information for %s has no PCI "
++ "connection types listed"), addrStr);
+ }
+ }
+ return false;
+@@ -1481,11 +1486,11 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ if ((devFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE) &&
+ !(busFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE)) {
+ if (reportError) {
+- virReportError(VIR_ERR_INTERNAL_ERROR,
+- _("PCI bus %.4x:%.2x is not compatible with the "
+- "device. Device requires hot-plug capability, "
+- "which is not provided by the bus"),
+- addr->domain, addr->bus);
++ virReportError(errType,
++ _("PCI bus is not compatible with the device "
++ "at %s. Device requires hot-plug capability, "
++ "which is not provided by bus %.4x:%.2x"),
++ addrStr, addr->domain, addr->bus);
+ }
+ return false;
+ }
+@@ -1500,23 +1505,30 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ static bool
+ qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+- qemuDomainPCIConnectFlags flags)
++ const char *addrStr,
++ qemuDomainPCIConnectFlags flags,
++ bool fromConfig)
+ {
+ qemuDomainPCIAddressBusPtr bus;
++ virErrorNumber errType = (fromConfig
++ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+
+ if (addrs->nbuses == 0) {
+- virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
++ virReportError(errType, "%s", _("No PCI buses available"));
+ return false;
+ }
+ if (addr->domain != 0) {
+- virReportError(VIR_ERR_XML_ERROR, "%s",
+- _("Only PCI domain 0 is available"));
++ virReportError(errType,
++ _("Invalid PCI address %s. "
++ "Only PCI domain 0 is available"),
++ addrStr);
+ return false;
+ }
+ if (addr->bus >= addrs->nbuses) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Only PCI buses up to %zu are available"),
+- addrs->nbuses - 1);
++ virReportError(errType,
++ _("Invalid PCI address %s. "
++ "Only PCI buses up to %zu are available"),
++ addrStr, addrs->nbuses - 1);
+ return false;
+ }
+
+@@ -1525,26 +1537,27 @@ qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
+ /* assure that at least one of the requested connection types is
+ * provided by this bus
+ */
+- if (!qemuDomainPCIAddressFlagsCompatible(addr, bus->flags, flags, true))
++ if (!qemuDomainPCIAddressFlagsCompatible(addr, addrStr, bus->flags,
++ flags, true, fromConfig))
+ return false;
+
+ /* some "buses" are really just a single port */
+ if (bus->minSlot && addr->slot < bus->minSlot) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Invalid PCI address: slot must be >= %zu"),
+- bus->minSlot);
++ virReportError(errType,
++ _("Invalid PCI address %s. slot must be >= %zu"),
++ addrStr, bus->minSlot);
+ return false;
+ }
+ if (addr->slot > bus->maxSlot) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Invalid PCI address: slot must be <= %zu"),
+- bus->maxSlot);
++ virReportError(errType,
++ _("Invalid PCI address %s. slot must be <= %zu"),
++ addrStr, bus->maxSlot);
+ return false;
+ }
+ if (addr->function > QEMU_PCI_ADDRESS_FUNCTION_LAST) {
+- virReportError(VIR_ERR_XML_ERROR,
+- _("Invalid PCI address: function must be <= %u"),
+- QEMU_PCI_ADDRESS_FUNCTION_LAST);
++ virReportError(errType,
++ _("Invalid PCI address %s. function must be <= %u"),
++ addrStr, QEMU_PCI_ADDRESS_FUNCTION_LAST);
+ return false;
+ }
+ return true;
+@@ -1953,12 +1966,12 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ bool fromConfig)
+ {
+ int ret = -1;
+- char *str = NULL;
++ char *addrStr = NULL;
+ qemuDomainPCIAddressBusPtr bus;
+ virErrorNumber errType = (fromConfig
+ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+
+- if (!(str = qemuDomainPCIAddressAsString(addr)))
++ if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
+ goto cleanup;
+
+ /* Add an extra bus if necessary */
+@@ -1967,7 +1980,7 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ /* Check that the requested bus exists, is the correct type, and we
+ * are asking for a valid slot
+ */
+- if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
++ if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, fromConfig))
+ goto cleanup;
+
+ bus = &addrs->buses[addr->bus];
+@@ -1977,31 +1990,32 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ virReportError(errType,
+ _("Attempted double use of PCI slot %s "
+ "(may need \"multifunction='on'\" for "
+- "device on function 0)"), str);
++ "device on function 0)"), addrStr);
+ goto cleanup;
+ }
+ bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
+- VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", str);
++ VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", addrStr);
+ } else {
+ if (bus->slots[addr->slot] & (1 << addr->function)) {
+ if (addr->function == 0) {
+ virReportError(errType,
+- _("Attempted double use of PCI Address %s"), str);
++ _("Attempted double use of PCI Address %s"),
++ addrStr);
+ } else {
+ virReportError(errType,
+ _("Attempted double use of PCI Address %s "
+ "(may need \"multifunction='on'\" "
+- "for device on function 0)"), str);
++ "for device on function 0)"), addrStr);
+ }
+ goto cleanup;
+ }
+ bus->slots[addr->slot] |= (1 << addr->function);
+- VIR_DEBUG("Reserving PCI address %s", str);
++ VIR_DEBUG("Reserving PCI address %s", addrStr);
+ }
+
+ ret = 0;
+ cleanup:
+- VIR_FREE(str);
++ VIR_FREE(addrStr);
+ return ret;
+ }
+
+@@ -2017,7 +2031,8 @@ qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+ {
+- int ret = 0;
++ int ret = -1;
++ char *addrStr = NULL;
+ /* Flags should be set according to the particular device,
+ * but only the caller knows the type of device. Currently this
+ * function is only used for hot-plug, though, and hot-plug is
+@@ -2026,6 +2041,9 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
+ QEMU_PCI_CONNECT_TYPE_PCI);
+
++ if (!(addrStr = qemuDomainPCIAddressAsString(&dev->addr.pci)))
++ goto cleanup;
++
+ if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ /* We do not support hotplug multi-function PCI device now, so we should
+ * reserve the whole slot. The function of the PCI device must be 0.
+@@ -2034,16 +2052,20 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only PCI device addresses with function=0"
+ " are supported"));
+- return -1;
++ goto cleanup;
+ }
+
+- if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci, flags))
+- return -1;
++ if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci,
++ addrStr, flags, true))
++ goto cleanup;
+
+ ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
+ } else {
+ ret = qemuDomainPCIAddressReserveNextSlot(addrs, dev, flags);
+ }
++
++cleanup:
++ VIR_FREE(addrStr);
+ return ret;
+ }
+
+@@ -2063,12 +2085,20 @@ qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs,
+ * already had it, and are giving it back.
+ */
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPES_MASK;
++ int ret = -1;
++ char *addrStr = NULL;
+
+- if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
+- return -1;
++ if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
++ goto cleanup;
++
++ if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, false))
++ goto cleanup;
+
+ addrs->buses[addr->bus].slots[addr->slot] = 0;
+- return 0;
++ ret = 0;
++cleanup:
++ VIR_FREE(addrStr);
++ return ret;
+ }
+
+ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
+@@ -2090,6 +2120,7 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ * 0000:00:00.0
+ */
+ virDevicePCIAddress a = { 0, 0, 0, 0, false };
++ char *addrStr = NULL;
+
+ /* except if this search is for the exact same type of device as
+ * last time, continue the search from the previous match
+@@ -2099,13 +2130,17 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+
+ if (addrs->nbuses == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
+- return -1;
++ goto error;
+ }
+
+ /* Start the search at the last used bus and slot */
+ for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
+- if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
+- flags, false)) {
++ addrStr = NULL;
++ if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
++ goto error;
++ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrStr,
++ addrs->buses[a.bus].flags,
++ flags, false, false)) {
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
+ a.domain, a.bus);
+ continue;
+@@ -2124,13 +2159,17 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+ if (addrs->dryRun) {
+ /* a is already set to the first new bus and slot 1 */
+ if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
+- return -1;
++ goto error;
+ goto success;
+ } else if (flags == addrs->lastFlags) {
+ /* Check the buses from 0 up to the last used one */
+ for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
+- if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
+- flags, false)) {
++ addrStr = NULL;
++ if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
++ goto error;
++ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrStr,
++ addrs->buses[a.bus].flags,
++ flags, false, false)) {
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
+ a.domain, a.bus);
+ continue;
+@@ -2147,12 +2186,15 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No more available PCI slots"));
++error:
++ VIR_FREE(addrStr);
+ return -1;
+
+ success:
+ VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x",
+ a.domain, a.bus, a.slot);
+ *next_addr = a;
++ VIR_FREE(addrStr);
+ return 0;
+ }
+
+@@ -2217,10 +2259,12 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ virQEMUCapsPtr qemuCaps,
+ qemuDomainPCIAddressSetPtr addrs)
+ {
++ int ret = -1;
+ size_t i;
+ virDevicePCIAddress tmp_addr;
+ bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+ virDevicePCIAddressPtr addrptr;
++ char *addrStr = NULL;
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
+
+ /* Verify that first IDE and USB controllers (if any) is on the PIIX3, fn 1 */
+@@ -2235,7 +2279,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ def->controllers[i]->info.addr.pci.function != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Primary IDE controller must have PCI address 0:0:1.1"));
+- goto error;
++ goto cleanup;
+ }
+ } else {
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+@@ -2255,7 +2299,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ def->controllers[i]->info.addr.pci.function != 2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("PIIX3 USB controller must have PCI address 0:0:1.2"));
+- goto error;
++ goto cleanup;
+ }
+ } else {
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+@@ -2274,7 +2318,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ memset(&tmp_addr, 0, sizeof(tmp_addr));
+ tmp_addr.slot = 1;
+ if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+- goto error;
++ goto cleanup;
+ }
+
+ if (def->nvideos > 0) {
+@@ -2293,8 +2337,11 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ primaryVideo->info.addr.pci.function = 0;
+ addrptr = &primaryVideo->info.addr.pci;
+
+- if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
+- goto error;
++ if (!(addrStr = qemuDomainPCIAddressAsString(addrptr)))
++ goto cleanup;
++ if (!qemuDomainPCIAddressValidate(addrs, addrptr,
++ addrStr, flags, false))
++ goto cleanup;
+
+ if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
+ if (qemuDeviceVideoUsable) {
+@@ -2302,15 +2349,15 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ if (qemuDomainPCIAddressReserveNextSlot(addrs,
+ &primaryVideo->info,
+ flags) < 0)
+- goto error;
++ goto cleanup;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("PCI address 0:0:2.0 is in use, "
+ "QEMU needs it for primary video"));
+- goto error;
++ goto cleanup;
+ }
+ } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) {
+- goto error;
++ goto cleanup;
+ }
+ } else if (!qemuDeviceVideoUsable) {
+ if (primaryVideo->info.addr.pci.domain != 0 ||
+@@ -2319,7 +2366,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ primaryVideo->info.addr.pci.function != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Primary video card must have PCI address 0:0:2.0"));
+- goto error;
++ goto cleanup;
+ }
+ /* If TYPE==PCI, then qemuCollectPCIAddress() function
+ * has already reserved the address, so we must skip */
+@@ -2334,13 +2381,13 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ " intervention");
+ virResetLastError();
+ } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
+- goto error;
++ goto cleanup;
+ }
+ }
+- return 0;
+-
+-error:
+- return -1;
++ ret = 0;
++cleanup:
++ VIR_FREE(addrStr);
++ return ret;
+ }
+
+
+@@ -2357,10 +2404,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ virQEMUCapsPtr qemuCaps,
+ qemuDomainPCIAddressSetPtr addrs)
+ {
++ int ret = -1;
+ size_t i;
+ virDevicePCIAddress tmp_addr;
+ bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+ virDevicePCIAddressPtr addrptr;
++ char *addrStr = NULL;
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCIE;
+
+ /* Verify that the first SATA controller is at 00:1F.2 */
+@@ -2375,7 +2424,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ def->controllers[i]->info.addr.pci.function != 2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Primary SATA controller must have PCI address 0:0:1f.2"));
+- goto error;
++ goto cleanup;
+ }
+ } else {
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+@@ -2399,12 +2448,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ tmp_addr.multi = 1;
+ if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+ false, false) < 0)
+- goto error;
++ goto cleanup;
+ tmp_addr.function = 3;
+ tmp_addr.multi = 0;
+ if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+ false, false) < 0)
+- goto error;
++ goto cleanup;
+ }
+
+ if (def->nvideos > 0) {
+@@ -2423,8 +2472,11 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ primaryVideo->info.addr.pci.function = 0;
+ addrptr = &primaryVideo->info.addr.pci;
+
+- if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
+- goto error;
++ if (!(addrStr = qemuDomainPCIAddressAsString(addrptr)))
++ goto cleanup;
++ if (!qemuDomainPCIAddressValidate(addrs, addrptr,
++ addrStr, flags, false))
++ goto cleanup;
+
+ if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
+ if (qemuDeviceVideoUsable) {
+@@ -2432,15 +2484,15 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ if (qemuDomainPCIAddressReserveNextSlot(addrs,
+ &primaryVideo->info,
+ flags) < 0)
+- goto error;
++ goto cleanup;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("PCI address 0:0:1.0 is in use, "
+ "QEMU needs it for primary video"));
+- goto error;
++ goto cleanup;
+ }
+ } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) {
+- goto error;
++ goto cleanup;
+ }
+ } else if (!qemuDeviceVideoUsable) {
+ if (primaryVideo->info.addr.pci.domain != 0 ||
+@@ -2449,7 +2501,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ primaryVideo->info.addr.pci.function != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Primary video card must have PCI address 0:0:1.0"));
+- goto error;
++ goto cleanup;
+ }
+ /* If TYPE==PCI, then qemuCollectPCIAddress() function
+ * has already reserved the address, so we must skip */
+@@ -2464,13 +2516,13 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ " intervention");
+ virResetLastError();
+ } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
+- goto error;
++ goto cleanup;
+ }
+ }
+- return 0;
+-
+-error:
+- return -1;
++ ret = 0;
++cleanup:
++ VIR_FREE(addrStr);
++ return ret;
+ }
+
+
+--
+1.8.3.2
+
--- /dev/null
+From 5aa8358dbedddfd0e4fef74e84430d146780f76f Mon Sep 17 00:00:00 2001
+Message-Id: <5aa8358dbedddfd0e4fef74e84430d146780f76f.1382534061.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Mon, 14 Oct 2013 16:38:47 +0200
+Subject: [PATCH] qemu: managedsave: Add support for compressing managed save
+ images
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1017227
+
+The regular save image code has the support to compress images using a
+specified algorithm. This was not implemented for managed save although
+it shares most of the backend code.
+
+(cherry picked from commit 550cae847bd018ed1a4f68b987d093fd3abb07df)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu.conf | 6 +++---
+ src/qemu/qemu_driver.c | 23 +++++++++++++++++++++--
+ 2 files changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
+index cdf1ec4..a2735cb 100644
+--- a/src/qemu/qemu.conf
++++ b/src/qemu/qemu.conf
+@@ -260,9 +260,9 @@
+ # saving a domain in order to save disk space; the list above is in descending
+ # order by performance and ascending order by compression ratio.
+ #
+-# save_image_format is used when you use 'virsh save' at scheduled
+-# saving, and it is an error if the specified save_image_format is
+-# not valid, or the requested compression program can't be found.
++# save_image_format is used when you use 'virsh save' or 'virsh managedsave'
++# at scheduled saving, and it is an error if the specified save_image_format
++# is not valid, or the requested compression program can't be found.
+ #
+ # dump_image_format is used when you use 'virsh dump' at emergency
+ # crashdump, and if the specified dump_image_format is not valid, or
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 3820303..14b0d57 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -3237,6 +3237,8 @@ static int
+ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
+ {
+ virQEMUDriverPtr driver = dom->conn->privateData;
++ virQEMUDriverConfigPtr cfg = NULL;
++ int compressed = QEMU_SAVE_FORMAT_RAW;
+ virDomainObjPtr vm;
+ char *name = NULL;
+ int ret = -1;
+@@ -3262,13 +3264,29 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
+ goto cleanup;
+ }
+
++ cfg = virQEMUDriverGetConfig(driver);
++ if (cfg->saveImageFormat) {
++ compressed = qemuSaveCompressionTypeFromString(cfg->saveImageFormat);
++ if (compressed < 0) {
++ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
++ _("Invalid save image format specified "
++ "in configuration file"));
++ goto cleanup;
++ }
++ if (!qemuCompressProgramAvailable(compressed)) {
++ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
++ _("Compression program for image format "
++ "in configuration file isn't available"));
++ goto cleanup;
++ }
++ }
++
+ if (!(name = qemuDomainManagedSavePath(driver, vm)))
+ goto cleanup;
+
+ VIR_INFO("Saving state of domain '%s' to '%s'", vm->def->name, name);
+
+- if ((ret = qemuDomainSaveInternal(driver, dom, vm, name,
+- QEMU_SAVE_FORMAT_RAW,
++ if ((ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
+ NULL, flags)) == 0)
+ vm->hasManagedSave = true;
+
+@@ -3278,6 +3296,7 @@ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ VIR_FREE(name);
++ virObjectUnref(cfg);
+
+ return ret;
+ }
+--
+1.8.4
+
--- /dev/null
+From 432c46e973b5c41951fe83dace4c07506f95a062 Mon Sep 17 00:00:00 2001
+Message-Id: <432c46e973b5c41951fe83dace4c07506f95a062.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:30 +0200
+Subject: [PATCH] qemu: monitor: Add infrastructure to access VM logs for
+ better err msgs
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+Early VM startup errors usually produce a better error message in the
+machine log file. Currently we were accessing it only when the process
+exited during certain phases of startup. This will help adding a more
+comprehensive error extraction for early qemu startup phases.
+
+This patch adds infrastructure to keep a file descriptor for the machine
+log file that will be used in case an error happens.
+
+(cherry picked from commit 8519e9ecdcc26f9753dbd85e897daabbaa82dee8)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_monitor.c | 27 +++++++++++++++++++++++++++
+ src/qemu/qemu_monitor.h | 2 ++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index e22a2b2..2eb536c 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -87,6 +87,9 @@ struct _qemuMonitor {
+ /* If found, path to the virtio memballoon driver */
+ char *balloonpath;
+ bool ballooninit;
++
++ /* Log file fd of the qemu process to dig for usable info */
++ int logfd;
+ };
+
+ static virClassPtr qemuMonitorClass;
+@@ -255,6 +258,7 @@ static void qemuMonitorDispose(void *obj)
+ VIR_FREE(mon->buffer);
+ virJSONValueFree(mon->options);
+ VIR_FREE(mon->balloonpath);
++ VIR_FORCE_CLOSE(mon->logfd);
+ }
+
+
+@@ -717,6 +721,7 @@ qemuMonitorOpenInternal(virDomainObjPtr vm,
+ return NULL;
+
+ mon->fd = -1;
++ mon->logfd = -1;
+ if (virCondInit(&mon->notify) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot initialize monitor condition"));
+@@ -3841,3 +3846,25 @@ qemuMonitorGetDeviceAliases(qemuMonitorPtr mon,
+
+ return qemuMonitorJSONGetDeviceAliases(mon, aliases);
+ }
++
++
++/**
++ * qemuMonitorSetDomainLog:
++ * Set the file descriptor of the open VM log file to report potential
++ * early startup errors of qemu.
++ *
++ * @mon: Monitor object to set the log file reading on
++ * @logfd: File descriptor of the already open log file
++ */
++int
++qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd)
++{
++ VIR_FORCE_CLOSE(mon->logfd);
++ if (logfd >= 0 &&
++ (mon->logfd = dup(logfd)) < 0) {
++ virReportSystemError(errno, "%s", _("failed to duplicate log fd"));
++ return -1;
++ }
++
++ return 0;
++}
+diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
+index 4a55501..85ae533 100644
+--- a/src/qemu/qemu_monitor.h
++++ b/src/qemu/qemu_monitor.h
+@@ -717,6 +717,8 @@ int qemuMonitorDetachCharDev(qemuMonitorPtr mon,
+ int qemuMonitorGetDeviceAliases(qemuMonitorPtr mon,
+ char ***aliases);
+
++int qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd);
++
+ /**
+ * When running two dd process and using <> redirection, we need a
+ * shell that will not truncate files. These two strings serve that
+--
+1.8.4
+
--- /dev/null
+From d1105a7417a983af1cc6fa4ea6a0657fa6413481 Mon Sep 17 00:00:00 2001
+Message-Id: <d1105a7417a983af1cc6fa4ea6a0657fa6413481.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:31 +0200
+Subject: [PATCH] qemu: monitor: Produce better errors on monitor hangup
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+Change the monitor error code to add the ability to access the qemu log
+file using a file descriptor so that we can dig in it for a more useful
+error message. The error is now logged on monitor hangups and overwrites
+a possible lesser error. A hangup on the monitor usualy means that qemu
+has crashed and there's a significant chance it produced a useful error
+message.
+
+The functionality will be latent until the next patch.
+
+(cherry picked from commit 90139a6236eb20a5cd2595af39ea11adae7d54de)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_monitor.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 60 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index 2eb536c..cf4f954 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -32,6 +32,8 @@
+ #include "qemu_monitor.h"
+ #include "qemu_monitor_text.h"
+ #include "qemu_monitor_json.h"
++#include "qemu_domain.h"
++#include "qemu_process.h"
+ #include "virerror.h"
+ #include "viralloc.h"
+ #include "virlog.h"
+@@ -332,6 +334,35 @@ qemuMonitorOpenPty(const char *monitor)
+ }
+
+
++/* Get a possible error from qemu's log. This function closes the
++ * corresponding log fd */
++static char *
++qemuMonitorGetErrorFromLog(qemuMonitorPtr mon)
++{
++ int len;
++ char *logbuf = NULL;
++ int orig_errno = errno;
++
++ if (mon->logfd < 0)
++ return NULL;
++
++ if (VIR_ALLOC_N_QUIET(logbuf, 4096) < 0)
++ goto error;
++
++ if ((len = qemuProcessReadLog(mon->logfd, logbuf, 4096 - 1, 0, true)) <= 0)
++ goto error;
++
++cleanup:
++ errno = orig_errno;
++ VIR_FORCE_CLOSE(mon->logfd);
++ return logbuf;
++
++error:
++ VIR_FREE(logbuf);
++ goto cleanup;
++}
++
++
+ /* This method processes data that has been received
+ * from the monitor. Looking for async events and
+ * replies/errors.
+@@ -565,6 +596,7 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
+ qemuMonitorPtr mon = opaque;
+ bool error = false;
+ bool eof = false;
++ bool hangup = false;
+
+ virObjectRef(mon);
+
+@@ -615,12 +647,14 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
+ }
+ }
+
+- if (!error &&
+- events & VIR_EVENT_HANDLE_HANGUP) {
+- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+- _("End of file from monitor"));
+- eof = true;
+- events &= ~VIR_EVENT_HANDLE_HANGUP;
++ if (events & VIR_EVENT_HANDLE_HANGUP) {
++ hangup = true;
++ if (!error) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("End of file from monitor"));
++ eof = true;
++ events &= ~VIR_EVENT_HANDLE_HANGUP;
++ }
+ }
+
+ if (!error && !eof &&
+@@ -639,6 +673,26 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
+ }
+
+ if (error || eof) {
++ if (hangup) {
++ /* Check if an error message from qemu is available and if so, use
++ * it to overwrite the actual message. It's done only in early
++ * startup phases where the message from qemu is certainly more
++ * interesting than a "connection reset by peer" message.
++ */
++ char *qemuMessage;
++
++ if ((qemuMessage = qemuMonitorGetErrorFromLog(mon))) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("early end of file from monitor: "
++ "possible problem:\n%s"),
++ qemuMessage);
++ virCopyLastError(&mon->lastError);
++ virResetLastError();
++ }
++
++ VIR_FREE(qemuMessage);
++ }
++
+ if (mon->lastError.code != VIR_ERR_OK) {
+ /* Already have an error, so clear any new error */
+ virResetLastError();
+--
+1.8.4
+
--- /dev/null
+From 0294bbbfa178f4328c4f95c2686210f1dd08b93d Mon Sep 17 00:00:00 2001
+Message-Id: <0294bbbfa178f4328c4f95c2686210f1dd08b93d.1382534061.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Mon, 21 Oct 2013 10:12:59 -0600
+Subject: [PATCH] qemu: move qemuDomainRemoveNetDevice to avoid forward
+ reference
+
+This is a prerequisite for the fix to
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1005682
+
+pure code movement to setup for next patch.
+
+(cherry picked from commit c5561644d8551d80d94b648b9ab828c9859e1667)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 122 ++++++++++++++++++++++++------------------------
+ 1 file changed, 61 insertions(+), 61 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index dcee86c..4d29e18 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -2332,67 +2332,6 @@ qemuDomainRemoveControllerDevice(virQEMUDriverPtr driver,
+
+
+ static void
+-qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
+- virDomainObjPtr vm,
+- virDomainNetDefPtr net)
+-{
+- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+- virNetDevVPortProfilePtr vport;
+- virDomainEventPtr event;
+- size_t i;
+-
+- VIR_DEBUG("Removing network interface %s from domain %p %s",
+- net->info.alias, vm, vm->def->name);
+-
+- virDomainAuditNet(vm, net, NULL, "detach", true);
+-
+- event = virDomainEventDeviceRemovedNewFromObj(vm, net->info.alias);
+- if (event)
+- qemuDomainEventQueue(driver, event);
+-
+- for (i = 0; i < vm->def->nnets; i++) {
+- if (vm->def->nets[i] == net) {
+- virDomainNetRemove(vm->def, i);
+- break;
+- }
+- }
+-
+- qemuDomainReleaseDeviceAddress(vm, &net->info, NULL);
+- virDomainConfNWFilterTeardown(net);
+-
+- if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
+- ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
+- net->ifname, &net->mac,
+- virDomainNetGetActualDirectDev(net),
+- virDomainNetGetActualDirectMode(net),
+- virDomainNetGetActualVirtPortProfile(net),
+- cfg->stateDir));
+- VIR_FREE(net->ifname);
+- }
+-
+- if (cfg->macFilter && (net->ifname != NULL)) {
+- if ((errno = networkDisallowMacOnPort(driver,
+- net->ifname,
+- &net->mac))) {
+- virReportSystemError(errno,
+- _("failed to remove ebtables rule on '%s'"),
+- net->ifname);
+- }
+- }
+-
+- vport = virDomainNetGetActualVirtPortProfile(net);
+- if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+- ignore_value(virNetDevOpenvswitchRemovePort(
+- virDomainNetGetActualBridgeName(net),
+- net->ifname));
+-
+- networkReleaseActualDevice(net);
+- virDomainNetDefFree(net);
+- virObjectUnref(cfg);
+-}
+-
+-
+-static void
+ qemuDomainRemovePCIHostDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainHostdevDefPtr hostdev)
+@@ -2523,6 +2462,67 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
+
+
+ static void
++qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
++ virDomainObjPtr vm,
++ virDomainNetDefPtr net)
++{
++ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
++ virNetDevVPortProfilePtr vport;
++ virDomainEventPtr event;
++ size_t i;
++
++ VIR_DEBUG("Removing network interface %s from domain %p %s",
++ net->info.alias, vm, vm->def->name);
++
++ virDomainAuditNet(vm, net, NULL, "detach", true);
++
++ event = virDomainEventDeviceRemovedNewFromObj(vm, net->info.alias);
++ if (event)
++ qemuDomainEventQueue(driver, event);
++
++ for (i = 0; i < vm->def->nnets; i++) {
++ if (vm->def->nets[i] == net) {
++ virDomainNetRemove(vm->def, i);
++ break;
++ }
++ }
++
++ qemuDomainReleaseDeviceAddress(vm, &net->info, NULL);
++ virDomainConfNWFilterTeardown(net);
++
++ if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
++ ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
++ net->ifname, &net->mac,
++ virDomainNetGetActualDirectDev(net),
++ virDomainNetGetActualDirectMode(net),
++ virDomainNetGetActualVirtPortProfile(net),
++ cfg->stateDir));
++ VIR_FREE(net->ifname);
++ }
++
++ if (cfg->macFilter && (net->ifname != NULL)) {
++ if ((errno = networkDisallowMacOnPort(driver,
++ net->ifname,
++ &net->mac))) {
++ virReportSystemError(errno,
++ _("failed to remove ebtables rule on '%s'"),
++ net->ifname);
++ }
++ }
++
++ vport = virDomainNetGetActualVirtPortProfile(net);
++ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
++ ignore_value(virNetDevOpenvswitchRemovePort(
++ virDomainNetGetActualBridgeName(net),
++ net->ifname));
++
++ networkReleaseActualDevice(net);
++ virDomainNetDefFree(net);
++ virObjectUnref(cfg);
++}
++
++
++static void
+ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainChrDefPtr chr)
+--
+1.8.4
+
--- /dev/null
+From 0befde5c74a0d886f4683d1fb669641fbe053cc2 Mon Sep 17 00:00:00 2001
+Message-Id: <0befde5c74a0d886f4683d1fb669641fbe053cc2.1380112457.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 23 Sep 2013 11:10:03 -0600
+Subject: [PATCH] qemu: only parse basename when determining emulator
+ properties
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1010617
+
+'virsh domxml-from-native' and 'virsh qemu-attach' could misbehave
+for an emulator installed in (a somewhat unlikely) location
+such as /usr/local/qemu-1.6/qemu-system-x86_64 or (an even less
+likely) /opt/notxen/qemu-system-x86_64. Limit the strstr seach
+to just the basename of the file where we are assuming details
+about the binary based on its name.
+
+While testing, I accidentally triggered a core dump during strcmp
+when I forgot to set os.type on one of my code paths; this patch
+changes such a coding error to raise a nicer internal error instead.
+
+* src/qemu/qemu_command.c (qemuParseCommandLine): Compute basename
+earlier.
+* src/conf/domain_conf.c (virDomainDefPostParseInternal): Avoid
+NULL deref.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 6a373fb2c95300d632a7371c893a301364f8dcb5)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c | 6 ++++++
+ src/qemu/qemu_command.c | 22 ++++++++++------------
+ 2 files changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 566940c..b46381f 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -2704,6 +2704,12 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
+ {
+ size_t i;
+
++ if (!def->os.type) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("hypervisor type must be specified"));
++ return -1;
++ }
++
+ /* verify init path for container based domains */
+ if (STREQ(def->os.type, "exe") && !def->os.init) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 6a6b3cd..dd63e01 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -28,6 +28,7 @@
+ #include "qemu_capabilities.h"
+ #include "qemu_bridge_filter.h"
+ #include "cpu/cpu.h"
++#include "dirname.h"
+ #include "passfd.h"
+ #include "viralloc.h"
+ #include "virlog.h"
+@@ -10765,29 +10766,25 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ if (VIR_STRDUP(def->emulator, progargv[0]) < 0)
+ goto error;
+
+- if (strstr(def->emulator, "kvm")) {
+- def->virtType = VIR_DOMAIN_VIRT_KVM;
+- def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+- }
+-
++ if (!(path = last_component(def->emulator)))
++ goto error;
+
+- if (strstr(def->emulator, "xenner")) {
++ if (strstr(path, "xenner")) {
+ def->virtType = VIR_DOMAIN_VIRT_KVM;
+ if (VIR_STRDUP(def->os.type, "xen") < 0)
+ goto error;
+ } else {
+ if (VIR_STRDUP(def->os.type, "hvm") < 0)
+ goto error;
++ if (strstr(path, "kvm")) {
++ def->virtType = VIR_DOMAIN_VIRT_KVM;
++ def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
++ }
+ }
+
+- if (STRPREFIX(def->emulator, "qemu"))
+- path = def->emulator;
+- else
+- path = strstr(def->emulator, "qemu");
+ if (def->virtType == VIR_DOMAIN_VIRT_KVM)
+ def->os.arch = qemuCaps->host.arch;
+- else if (path &&
+- STRPREFIX(path, "qemu-system-"))
++ else if (STRPREFIX(path, "qemu-system-"))
+ def->os.arch = virArchFromString(path + strlen("qemu-system-"));
+ else
+ def->os.arch = VIR_ARCH_I686;
+@@ -10796,6 +10793,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ (def->os.arch == VIR_ARCH_X86_64))
+ def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI)
+ /*| (1 << VIR_DOMAIN_FEATURE_APIC)*/;
++
+ #define WANT_VALUE() \
+ const char *val = progargv[++i]; \
+ if (!val) { \
+--
+1.8.3.2
+
--- /dev/null
+From 20ee7e81fe4ea6ca051a5a759d0719986aa75ef5 Mon Sep 17 00:00:00 2001
+Message-Id: <20ee7e81fe4ea6ca051a5a759d0719986aa75ef5.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:45 -0600
+Subject: [PATCH] qemu: prefer to put a Q35 machine's dmi-to-pci-bridge at
+ 00:1E.0
+
+This resolves one of the issues listed in:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+00:1E.0 is the location of this controller on at least some actual Q35
+hardware, so we try to replicate the placement. The bridge should work
+just as well in any other location though, so if 00:1E.0 isn't
+available, just allow it to be auto-assigned anywhere appropriate.
+
+(cherry picked from commit 386ebb47a5d707829edf0dccf4d80056ca199e63)
+
+Conflicts:
+ tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args
+ - this is a file added upstream, but not present on the
+ RHEL7.0 branch.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 22 ++++++++++++++++++++++
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +-
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +-
+ 3 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 47bb22a..47b488a 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -2491,6 +2491,28 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ }
+ }
+ break;
++
++ case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
++ if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE &&
++ def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
++ /* Try to assign this bridge to 00:1E.0 (because that
++ * is its standard location on real hardware) unless
++ * it's already taken, but don't insist on it.
++ */
++ memset(&tmp_addr, 0, sizeof(tmp_addr));
++ tmp_addr.slot = 0x1E;
++ if (!qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
++ if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr,
++ flags, true, false) < 0)
++ goto cleanup;
++ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
++ def->controllers[i]->info.addr.pci.domain = 0;
++ def->controllers[i]->info.addr.pci.bus = 0;
++ def->controllers[i]->info.addr.pci.slot = 0x1E;
++ def->controllers[i]->info.addr.pci.function = 0;
++ }
++ }
++ break;
+ }
+ }
+
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+index 84428f9..d7e9acc 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+@@ -1,5 +1,5 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
+ -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
++-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+index 151863e..45e6ec8 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -1,7 +1,7 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+ /usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
++-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+ -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-sata0-0-0 \
+ -device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \
+--
+1.8.3.2
+
--- /dev/null
+From 910a705253fc87dcd8fe0f1657a2466e14ccb5df Mon Sep 17 00:00:00 2001
+Message-Id: <910a705253fc87dcd8fe0f1657a2466e14ccb5df.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:33 +0200
+Subject: [PATCH] qemu: process: Silence coverity warning when rewinding log
+ file
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+The change in ef29de14c37d14abc546e90555a0093797facfdd that introduced
+better error logging from qemu introduced a warning from coverity about
+unused return value from lseek. Silence this warning and fix typo in the
+corresponding error message.
+
+Reported by: John Ferlan
+
+(cherry picked from commit 59e21e973fdbfc9065ff5aa421ae36dbd1c4073a)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index c991d04..f979877 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -1818,10 +1818,10 @@ cleanup:
+ }
+
+ len = strlen(buf);
+- /* best effor seek - we need to reset to the original position, so that
++ /* best effort seek - we need to reset to the original position, so that
+ * a possible read of the fd in the monitor code doesn't influence this
+ * error delivery option */
+- lseek(logfd, pos, SEEK_SET);
++ ignore_value(lseek(logfd, pos, SEEK_SET));
+ qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("process exited while connecting to monitor: %s"),
+--
+1.8.4
+
--- /dev/null
+From 9a68121178334ac95dd057c98a3b8922a243fb93 Mon Sep 17 00:00:00 2001
+Message-Id: <9a68121178334ac95dd057c98a3b8922a243fb93.1383922567.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:35 +0100
+Subject: [PATCH] qemu: process: Validate specific CPUID flags of a guest
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+When starting a VM the qemu process may filter out some requested
+features of a domain as it's not supported either by the host or by
+qemu. Libvirt didn't check if this happened which might end up in
+changing of the guest ABI when migrating.
+
+The proof of concept implementation adds the check for the recently
+introduced kvm_pv_unhalt cpuid feature bit. This feature depends on both
+qemu and host kernel support and thus increase the possibility of guest
+ABI breakage.
+
+(cherry picked from commit d94b7817719b064849818b9ba6c37e403b7c003c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index e0097df..40e3754 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -43,6 +43,7 @@
+ #include "qemu_bridge_filter.h"
+ #include "qemu_migration.h"
+
++#include "cpu/cpu.h"
+ #include "datatypes.h"
+ #include "virlog.h"
+ #include "virerror.h"
+@@ -3437,6 +3438,47 @@ qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
+ return true;
+ }
+
++
++static bool
++qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm)
++{
++ virDomainDefPtr def = vm->def;
++ virArch arch = def->os.arch;
++ virCPUDataPtr guestcpu = NULL;
++ qemuDomainObjPrivatePtr priv = vm->privateData;
++ bool ret = false;
++
++ switch (arch) {
++ case VIR_ARCH_I686:
++ case VIR_ARCH_X86_64:
++ qemuDomainObjEnterMonitor(driver, vm);
++ guestcpu = qemuMonitorGetGuestCPU(priv->mon, arch);
++ qemuDomainObjExitMonitor(driver, vm);
++
++ if (!(guestcpu))
++ goto cleanup;
++
++ if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_DOMAIN_FEATURE_STATE_ON) {
++ if (!cpuHasFeature(guestcpu, VIR_CPU_x86_KVM_PV_UNHALT)) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("host doesn't support paravirtual spinlocks"));
++ goto cleanup;
++ }
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ ret = true;
++
++cleanup:
++ cpuDataFree(guestcpu);
++ return ret;
++}
++
++
+ int qemuProcessStart(virConnectPtr conn,
+ virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+@@ -3904,6 +3946,10 @@ int qemuProcessStart(virConnectPtr conn,
+ priv->agentError = true;
+ }
+
++ VIR_DEBUG("Detecting if required emulator features are present");
++ if (!qemuProcessVerifyGuestCPU(driver, vm))
++ goto cleanup;
++
+ VIR_DEBUG("Detecting VCPU PIDs");
+ if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
+ goto cleanup;
+--
+1.8.4.2
+
--- /dev/null
+From 9e884c4b9c843ad6ca60ac8cc5ece2e17d32f7a9 Mon Sep 17 00:00:00 2001
+Message-Id: <9e884c4b9c843ad6ca60ac8cc5ece2e17d32f7a9.1377873637.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:25 -0600
+Subject: [PATCH] qemu: properly set/use device alias for pci controllers
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+We had been setting the device alias in the devinceinfo for pci
+controllers to "pci%u", but then hardcoding "pci.%u" when creating the
+device address for other devices using that pci bus. This all worked
+just fine until we encountered the built-in "pcie.0" bus (the PCIe
+root complex) in Q35 machines.
+
+In order to create the correct commandline for this one case, this
+patch:
+
+1) sets the alias for PCI controllers correctly, to "pci.%u" (or
+"pcie.%u" for the pcie-root controller)
+
+2) eliminates the hardcoded "pci.%u" for pci controllers when
+generatuing device address strings, and instead uses the controller's
+alias.
+
+3) plumbs a pointer to the virDomainDef all the way down to
+qemuBuildDeviceAddressStr. This was necessary in order to make the
+aliase of the controller *used by a device* available (previously
+qemuBuildDeviceAddressStr only had the deviceinfo of the device
+itself, *not* of the controller it was connecting to). This made for a
+larger than desired diff, but at least in the future we won't have to
+do it again, since all the information we could possibly ever need for
+future enhancements is in the virDomainDef. (right?)
+
+This should be done for *all* controllers, but for now we just do it
+in the case of PCI controllers, to reduce the likelyhood of
+regression.
+(cherry picked from commit 01b8812765f17d1a2592bcec2708315f136fb611)
+---
+ src/qemu/qemu_command.c | 164 ++++++++++++++-------
+ src/qemu/qemu_command.h | 28 ++--
+ src/qemu/qemu_hotplug.c | 6 +-
+ tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +-
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +-
+ 5 files changed, 136 insertions(+), 66 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 3e07360..c7e7826 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -860,10 +860,18 @@ qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller)
+ {
+ const char *prefix = virDomainControllerTypeToString(controller->type);
+
+- if (virAsprintf(&controller->info.alias, "%s%d", prefix,
+- controller->idx) < 0)
+- return -1;
+- return 0;
++ if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
++ /* only pcie-root uses a different naming convention
++ * ("pcie.0"), because it is hardcoded that way in qemu. All
++ * other buses use the consistent "pci.%u".
++ */
++ if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
++ return virAsprintf(&controller->info.alias, "pcie.%d", controller->idx);
++ else
++ return virAsprintf(&controller->info.alias, "pci.%d", controller->idx);
++ }
++
++ return virAsprintf(&controller->info.alias, "%s%d", prefix, controller->idx);
+ }
+
+ static ssize_t
+@@ -2793,22 +2801,57 @@ qemuUsbId(virBufferPtr buf, int idx)
+
+ static int
+ qemuBuildDeviceAddressStr(virBufferPtr buf,
++ virDomainDefPtr domainDef,
+ virDomainDeviceInfoPtr info,
+ virQEMUCapsPtr qemuCaps)
+ {
++ int ret = -1;
++ char *devStr = NULL;
++
+ if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
++ const char *contAlias = NULL;
++ size_t i;
++
++ if (!(devStr = qemuDomainPCIAddressAsString(&info->addr.pci)))
++ goto cleanup;
++ for (i = 0; i < domainDef->ncontrollers; i++) {
++ virDomainControllerDefPtr cont = domainDef->controllers[i];
++
++ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
++ cont->idx == info->addr.pci.bus) {
++ contAlias = cont->info.alias;
++ if (!contAlias) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Device alias was not set for PCI "
++ "controller with index %u required "
++ "for device at address %s"),
++ info->addr.pci.bus, devStr);
++ goto cleanup;
++ }
++ break;
++ }
++ }
++ if (!contAlias) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("Could not find PCI "
++ "controller with index %u required "
++ "for device at address %s"),
++ info->addr.pci.bus, devStr);
++ goto cleanup;
++ }
++
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
+ if (info->addr.pci.function != 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only PCI device addresses with function=0 "
+ "are supported with this QEMU binary"));
+- return -1;
++ goto cleanup;
+ }
+ if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("'multifunction=on' is not supported with "
+ "this QEMU binary"));
+- return -1;
++ goto cleanup;
+ }
+ }
+
+@@ -2822,18 +2865,19 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
+ */
+ if (info->addr.pci.bus != 0) {
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) {
+- virBufferAsprintf(buf, ",bus=pci.%u", info->addr.pci.bus);
++ virBufferAsprintf(buf, ",bus=%s", contAlias);
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Multiple PCI buses are not supported "
+ "with this QEMU binary"));
+- return -1;
++ goto cleanup;
+ }
+ } else {
+- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIBUS))
+- virBufferAddLit(buf, ",bus=pci.0");
+- else
++ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIBUS)) {
++ virBufferAsprintf(buf, ",bus=%s", contAlias);
++ } else {
+ virBufferAddLit(buf, ",bus=pci");
++ }
+ }
+ if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON)
+ virBufferAddLit(buf, ",multifunction=on");
+@@ -2857,7 +2901,10 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
+ info->addr.ccw.devno);
+ }
+
+- return 0;
++ ret = 0;
++cleanup:
++ VIR_FREE(devStr);
++ return ret;
+ }
+
+ static int
+@@ -4191,13 +4238,13 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
+ (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN)
+ ? "on" : "off");
+ }
+- if (qemuBuildDeviceAddressStr(&opt, &disk->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
+ goto error;
+ break;
+ case VIR_DOMAIN_DISK_BUS_USB:
+ virBufferAddLit(&opt, "usb-storage");
+
+- if (qemuBuildDeviceAddressStr(&opt, &disk->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
+ goto error;
+ break;
+ default:
+@@ -4321,7 +4368,8 @@ error:
+
+
+ char *
+-qemuBuildFSDevStr(virDomainFSDefPtr fs,
++qemuBuildFSDevStr(virDomainDefPtr def,
++ virDomainFSDefPtr fs,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+@@ -4337,7 +4385,7 @@ qemuBuildFSDevStr(virDomainFSDefPtr fs,
+ virBufferAsprintf(&opt, ",fsdev=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
+ virBufferAsprintf(&opt, ",mount_tag=%s", fs->dst);
+
+- if (qemuBuildDeviceAddressStr(&opt, &fs->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&opt, def, &fs->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&opt)) {
+@@ -4557,7 +4605,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ if (def->queues)
+ virBufferAsprintf(&buf, ",num_queues=%u", def->queues);
+
+- if (qemuBuildDeviceAddressStr(&buf, &def->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, domainDef, &def->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -4595,7 +4643,8 @@ qemuBuildNicStr(virDomainNetDefPtr net,
+
+
+ char *
+-qemuBuildNicDevStr(virDomainNetDefPtr net,
++qemuBuildNicDevStr(virDomainDefPtr def,
++ virDomainNetDefPtr net,
+ int vlan,
+ int bootindex,
+ virQEMUCapsPtr qemuCaps)
+@@ -4657,7 +4706,7 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
+ virBufferAsprintf(&buf, ",id=%s", net->info.alias);
+ virBufferAsprintf(&buf, ",mac=%s",
+ virMacAddrFormat(&net->mac, macaddr));
+- if (qemuBuildDeviceAddressStr(&buf, &net->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &net->info, qemuCaps) < 0)
+ goto error;
+ if (qemuBuildRomStr(&buf, &net->info, qemuCaps) < 0)
+ goto error;
+@@ -4812,7 +4861,8 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
+
+
+ char *
+-qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
++qemuBuildWatchdogDevStr(virDomainDefPtr def,
++ virDomainWatchdogDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -4825,7 +4875,7 @@ qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
+ }
+
+ virBufferAsprintf(&buf, "%s,id=%s", model, dev->info.alias);
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -4842,7 +4892,8 @@ error:
+
+
+ char *
+-qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev,
++qemuBuildMemballoonDevStr(virDomainDefPtr def,
++ virDomainMemballoonDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -4862,7 +4913,7 @@ qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev,
+ }
+
+ virBufferAsprintf(&buf, ",id=%s", dev->info.alias);
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -4905,7 +4956,8 @@ error:
+ }
+
+ char *
+-qemuBuildUSBInputDevStr(virDomainInputDefPtr dev,
++qemuBuildUSBInputDevStr(virDomainDefPtr def,
++ virDomainInputDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -4914,7 +4966,7 @@ qemuBuildUSBInputDevStr(virDomainInputDefPtr dev,
+ dev->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
+ "usb-mouse" : "usb-tablet", dev->info.alias);
+
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -4931,7 +4983,8 @@ error:
+
+
+ char *
+-qemuBuildSoundDevStr(virDomainSoundDefPtr sound,
++qemuBuildSoundDevStr(virDomainDefPtr def,
++ virDomainSoundDefPtr sound,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -4952,7 +5005,7 @@ qemuBuildSoundDevStr(virDomainSoundDefPtr sound,
+ model = "intel-hda";
+
+ virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
+- if (qemuBuildDeviceAddressStr(&buf, &sound->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &sound->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -5012,7 +5065,8 @@ error:
+ }
+
+ static char *
+-qemuBuildDeviceVideoStr(virDomainVideoDefPtr video,
++qemuBuildDeviceVideoStr(virDomainDefPtr def,
++ virDomainVideoDefPtr video,
+ virQEMUCapsPtr qemuCaps,
+ bool primary)
+ {
+@@ -5066,7 +5120,7 @@ qemuBuildDeviceVideoStr(virDomainVideoDefPtr video,
+ virBufferAsprintf(&buf, ",vram_size=%u", video->vram * 1024);
+ }
+
+- if (qemuBuildDeviceAddressStr(&buf, &video->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &video->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -5106,7 +5160,9 @@ qemuOpenPCIConfig(virDomainHostdevDefPtr dev)
+ }
+
+ char *
+-qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd,
++qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
++ virDomainHostdevDefPtr dev,
++ const char *configfd,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -5126,7 +5182,7 @@ qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd,
+ virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
+ if (dev->info->bootIndex)
+ virBufferAsprintf(&buf, ",bootindex=%d", dev->info->bootIndex);
+- if (qemuBuildDeviceAddressStr(&buf, dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
+ goto error;
+ if (qemuBuildRomStr(&buf, dev->info, qemuCaps) < 0)
+ goto error;
+@@ -5232,7 +5288,7 @@ qemuBuildRedirdevDevStr(virDomainDefPtr def,
+ virBufferAsprintf(&buf, ",bootindex=%d", dev->info.bootIndex);
+ }
+
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -5248,7 +5304,8 @@ error:
+ }
+
+ char *
+-qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
++qemuBuildUSBHostdevDevStr(virDomainDefPtr def,
++ virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -5271,7 +5328,7 @@ qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
+ if (dev->info->bootIndex)
+ virBufferAsprintf(&buf, ",bootindex=%d", dev->info->bootIndex);
+
+- if (qemuBuildDeviceAddressStr(&buf, dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -5288,7 +5345,8 @@ error:
+
+
+ char *
+-qemuBuildHubDevStr(virDomainHubDefPtr dev,
++qemuBuildHubDevStr(virDomainDefPtr def,
++ virDomainHubDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -5308,7 +5366,7 @@ qemuBuildHubDevStr(virDomainHubDefPtr dev,
+
+ virBufferAddLit(&buf, "usb-hub");
+ virBufferAsprintf(&buf, ",id=%s", dev->info.alias);
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto error;
+
+ if (virBufferError(&buf)) {
+@@ -5829,6 +5887,7 @@ cleanup:
+
+ static int
+ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
++ virDomainDefPtr def,
+ virDomainRNGDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+ {
+@@ -5858,7 +5917,7 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
+ virBufferAddLit(&buf, ",period=1000");
+ }
+
+- if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+ goto cleanup;
+
+ virCommandAddArg(cmd, "-device");
+@@ -7133,7 +7192,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
+ virCommandAddArgList(cmd, "-netdev", host, NULL);
+ }
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+- if (!(nic = qemuBuildNicDevStr(net, vlan, bootindex, qemuCaps)))
++ if (!(nic = qemuBuildNicDevStr(def, net, vlan, bootindex, qemuCaps)))
+ goto cleanup;
+ virCommandAddArgList(cmd, "-device", nic, NULL);
+ } else {
+@@ -7881,7 +7940,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ char *optstr;
+
+ virCommandAddArg(cmd, "-device");
+- if (!(optstr = qemuBuildHubDevStr(hub, qemuCaps)))
++ if (!(optstr = qemuBuildHubDevStr(def, hub, qemuCaps)))
+ goto error;
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
+@@ -8102,7 +8161,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ VIR_FREE(optstr);
+
+ virCommandAddArg(cmd, "-device");
+- if (!(optstr = qemuBuildFSDevStr(fs, qemuCaps)))
++ if (!(optstr = qemuBuildFSDevStr(def, fs, qemuCaps)))
+ goto error;
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
+@@ -8460,7 +8519,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+ char *optstr;
+ virCommandAddArg(cmd, "-device");
+- if (!(optstr = qemuBuildUSBInputDevStr(input, qemuCaps)))
++ if (!(optstr = qemuBuildUSBInputDevStr(def, input, qemuCaps)))
+ goto error;
+ virCommandAddArg(cmd, optstr);
+ VIR_FREE(optstr);
+@@ -8517,7 +8576,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ for (i = 0; i < def->nvideos; i++) {
+ char *str;
+ virCommandAddArg(cmd, "-device");
+- if (!(str = qemuBuildDeviceVideoStr(def->videos[i], qemuCaps, !i)))
++ if (!(str = qemuBuildDeviceVideoStr(def, def->videos[i], qemuCaps, !i)))
+ goto error;
+
+ virCommandAddArg(cmd, str);
+@@ -8591,7 +8650,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+
+ virCommandAddArg(cmd, "-device");
+
+- if (!(str = qemuBuildDeviceVideoStr(def->videos[i], qemuCaps, false)))
++ if (!(str = qemuBuildDeviceVideoStr(def, def->videos[i], qemuCaps, false)))
+ goto error;
+
+ virCommandAddArg(cmd, str);
+@@ -8655,7 +8714,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
+ } else {
+ virCommandAddArg(cmd, "-device");
+- if (!(str = qemuBuildSoundDevStr(sound, qemuCaps)))
++ if (!(str = qemuBuildSoundDevStr(def, sound, qemuCaps)))
+ goto error;
+
+ virCommandAddArg(cmd, str);
+@@ -8731,7 +8790,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+ virCommandAddArg(cmd, "-device");
+
+- optstr = qemuBuildWatchdogDevStr(watchdog, qemuCaps);
++ optstr = qemuBuildWatchdogDevStr(def, watchdog, qemuCaps);
+ if (!optstr)
+ goto error;
+ } else {
+@@ -8844,7 +8903,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+ virCommandAddArg(cmd, "-device");
+- if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev, qemuCaps)))
++ if (!(devstr = qemuBuildUSBHostdevDevStr(def, hostdev, qemuCaps)))
+ goto error;
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+@@ -8892,7 +8951,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ }
+ }
+ virCommandAddArg(cmd, "-device");
+- devstr = qemuBuildPCIHostdevDevStr(hostdev, configfd_name, qemuCaps);
++ devstr = qemuBuildPCIHostdevDevStr(def, hostdev, configfd_name, qemuCaps);
+ VIR_FREE(configfd_name);
+ if (!devstr)
+ goto error;
+@@ -9021,7 +9080,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ char *optstr;
+ virCommandAddArg(cmd, "-device");
+
+- optstr = qemuBuildMemballoonDevStr(def->memballoon, qemuCaps);
++ optstr = qemuBuildMemballoonDevStr(def, def->memballoon, qemuCaps);
+ if (!optstr)
+ goto error;
+ virCommandAddArg(cmd, optstr);
+@@ -9037,7 +9096,7 @@ qemuBuildCommandLine(virConnectPtr conn,
+ goto error;
+
+ /* add the device */
+- if (qemuBuildRNGDeviceArgs(cmd, def->rng, qemuCaps) < 0)
++ if (qemuBuildRNGDeviceArgs(cmd, def, def->rng, qemuCaps) < 0)
+ goto error;
+ }
+
+@@ -9115,6 +9174,7 @@ error:
+ */
+ static int
+ qemuBuildSerialChrDeviceStr(char **deviceStr,
++ virDomainDefPtr def,
+ virDomainChrDefPtr serial,
+ virQEMUCapsPtr qemuCaps,
+ virArch arch,
+@@ -9127,7 +9187,7 @@ qemuBuildSerialChrDeviceStr(char **deviceStr,
+ serial->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) {
+ virBufferAsprintf(&cmd, "spapr-vty,chardev=char%s",
+ serial->info.alias);
+- if (qemuBuildDeviceAddressStr(&cmd, &serial->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&cmd, def, &serial->info, qemuCaps) < 0)
+ goto error;
+ }
+ } else {
+@@ -9149,7 +9209,7 @@ qemuBuildSerialChrDeviceStr(char **deviceStr,
+ goto error;
+ }
+
+- if (qemuBuildDeviceAddressStr(&cmd, &serial->info, qemuCaps) < 0)
++ if (qemuBuildDeviceAddressStr(&cmd, def, &serial->info, qemuCaps) < 0)
+ goto error;
+ }
+ }
+@@ -9264,7 +9324,7 @@ qemuBuildChrDeviceStr(char **deviceStr,
+
+ switch ((enum virDomainChrDeviceType) chr->deviceType) {
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+- ret = qemuBuildSerialChrDeviceStr(deviceStr, chr, qemuCaps,
++ ret = qemuBuildSerialChrDeviceStr(deviceStr, vmdef, chr, qemuCaps,
+ vmdef->os.arch,
+ vmdef->os.machine);
+ break;
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index e5111d2..5c5c025 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -98,7 +98,8 @@ char * qemuBuildNicStr(virDomainNetDefPtr net,
+ int vlan);
+
+ /* Current, best practice */
+-char * qemuBuildNicDevStr(virDomainNetDefPtr net,
++char * qemuBuildNicDevStr(virDomainDefPtr def,
++ virDomainNetDefPtr net,
+ int vlan,
+ int bootindex,
+ virQEMUCapsPtr qemuCaps);
+@@ -119,7 +120,8 @@ char * qemuBuildDriveDevStr(virDomainDefPtr def,
+ virDomainDiskDefPtr disk,
+ int bootindex,
+ virQEMUCapsPtr qemuCaps);
+-char * qemuBuildFSDevStr(virDomainFSDefPtr fs,
++char * qemuBuildFSDevStr(virDomainDefPtr domainDef,
++ virDomainFSDefPtr fs,
+ virQEMUCapsPtr qemuCaps);
+ /* Current, best practice */
+ char * qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+@@ -127,22 +129,27 @@ char * qemuBuildControllerDevStr(virDomainDefPtr domainDef,
+ virQEMUCapsPtr qemuCaps,
+ int *nusbcontroller);
+
+-char * qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev,
++char * qemuBuildWatchdogDevStr(virDomainDefPtr domainDef,
++ virDomainWatchdogDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
+-char * qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev,
++char * qemuBuildMemballoonDevStr(virDomainDefPtr domainDef,
++ virDomainMemballoonDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
+-char * qemuBuildUSBInputDevStr(virDomainInputDefPtr dev,
++char * qemuBuildUSBInputDevStr(virDomainDefPtr domainDef,
++ virDomainInputDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
+-char * qemuBuildSoundDevStr(virDomainSoundDefPtr sound,
++char * qemuBuildSoundDevStr(virDomainDefPtr domainDef,
++ virDomainSoundDefPtr sound,
+ virQEMUCapsPtr qemuCaps);
+
+ /* Legacy, pre device support */
+ char * qemuBuildPCIHostdevPCIDevStr(virDomainHostdevDefPtr dev);
+ /* Current, best practice */
+-char * qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev,
++char * qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
++ virDomainHostdevDefPtr dev,
+ const char *configfd,
+ virQEMUCapsPtr qemuCaps);
+
+@@ -151,7 +158,8 @@ int qemuOpenPCIConfig(virDomainHostdevDefPtr dev);
+ /* Legacy, pre device support */
+ char * qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev);
+ /* Current, best practice */
+-char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
++char * qemuBuildUSBHostdevDevStr(virDomainDefPtr def,
++ virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
+ char * qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
+@@ -162,7 +170,9 @@ char * qemuBuildSCSIHostdevDevStr(virDomainDefPtr def,
+ virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+
+-char * qemuBuildHubDevStr(virDomainHubDefPtr dev, virQEMUCapsPtr qemuCaps);
++char * qemuBuildHubDevStr(virDomainDefPtr def,
++ virDomainHubDefPtr dev,
++ virQEMUCapsPtr qemuCaps);
+ char * qemuBuildRedirdevDevStr(virDomainDefPtr def,
+ virDomainRedirdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 032de69..7a6946e 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -859,7 +859,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
+ }
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+- if (!(nicstr = qemuBuildNicDevStr(net, vlan, 0, priv->qemuCaps)))
++ if (!(nicstr = qemuBuildNicDevStr(vm->def, net, vlan, 0, priv->qemuCaps)))
+ goto try_remove;
+ } else {
+ if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
+@@ -1057,7 +1057,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ goto error;
+ }
+
+- if (!(devstr = qemuBuildPCIHostdevDevStr(hostdev, configfd_name,
++ if (!(devstr = qemuBuildPCIHostdevDevStr(vm->def, hostdev, configfd_name,
+ priv->qemuCaps)))
+ goto error;
+
+@@ -1302,7 +1302,7 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+ if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
+ goto cleanup;
+- if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev, priv->qemuCaps)))
++ if (!(devstr = qemuBuildUSBHostdevDevStr(vm->def, hostdev, priv->qemuCaps)))
+ goto cleanup;
+ }
+
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+index cecef7b..84428f9 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
+@@ -1,5 +1,5 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
+ -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x2 \
++-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+index 6c24407..5ff4bc7 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -1,6 +1,6 @@
+ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+ /usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+--device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x2 \
++-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+ -vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
+--
+1.8.3.2
+
--- /dev/null
+From cf9c2028ba2892a200cd733617346e40069c1660 Mon Sep 17 00:00:00 2001
+Message-Id: <cf9c2028ba2892a200cd733617346e40069c1660.1380112457.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 23 Sep 2013 11:10:04 -0600
+Subject: [PATCH] qemu: recognize -machine accel=kvm when parsing native
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1010617
+
+In Fedora 19, 'qemu-kvm' is a simple wrapper that calls
+'qemu-system-x86_64 -machine accel=kvm'. Attempting
+to use 'virsh qemu-attach $pid' to a machine started as:
+
+qemu-kvm -cdrom /var/lib/libvirt/images/foo.img \
+ -monitor unix:/tmp/demo,server,nowait -name foo \
+ --uuid cece4f9f-dff0-575d-0e8e-01fe380f12ea
+
+was failing with:
+error: XML error: No PCI buses available
+
+because we did not see 'kvm' in the executable name read from
+/proc/$pid/cmdline, and tried to assign os.machine as
+"accel=kvm" instead of "pc"; this in turn led to refusal to
+recognize the pci bus.
+
+Noticed while investigating https://bugzilla.redhat.com/995312
+although there are still other issues to fix before that bug
+will be completely solved.
+
+I've concluded that the existing parser code for native-to-xml
+is a horrendous hodge-podge of ad-hoc approaches; I basically
+rewrote the -machine section to be a bit saner.
+
+* src/qemu/qemu_command.c (qemuParseCommandLine): Don't assume
+-machine argument is always appropriate for os.machine; set
+virtType if accel is present.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 2b1ef11c6cb14239feaeb1e426d85377983accb8)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 57 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 32 insertions(+), 25 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index dd63e01..d596f09 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -11172,35 +11172,42 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
+ VIR_FREE(def->name);
+ } else if (STREQ(arg, "-M") ||
+ STREQ(arg, "-machine")) {
+- char *params;
++ char **list;
++ char *param;
++ size_t j = 0;
++
++ /* -machine [type=]name[,prop[=value][,...]]
++ * Set os.machine only if first parameter lacks '=' or
++ * contains explicit type='...' */
+ WANT_VALUE();
+- params = strchr(val, ',');
+- if (params == NULL) {
+- if (VIR_STRDUP(def->os.machine, val) < 0)
+- goto error;
+- } else {
+- if (VIR_STRNDUP(def->os.machine, val, params - val) < 0)
++ list = virStringSplit(val, ",", 0);
++ param = list[0];
++
++ if (STRPREFIX(param, "type="))
++ param += strlen("type=");
++ if (!strchr(param, '=')) {
++ if (VIR_STRDUP(def->os.machine, param) < 0) {
++ virStringFreeList(list);
+ goto error;
+-
+- while (params++) {
+- /* prepared for more "-machine" parameters */
+- char *tmp = params;
+- params = strchr(params, ',');
+-
+- if (STRPREFIX(tmp, "dump-guest-core=")) {
+- tmp += strlen("dump-guest-core=");
+- if (params && VIR_STRNDUP(tmp, tmp, params - tmp) < 0)
+- goto error;
+- def->mem.dump_core = virDomainMemDumpTypeFromString(tmp);
+- if (def->mem.dump_core <= 0)
+- def->mem.dump_core = VIR_DOMAIN_MEM_DUMP_DEFAULT;
+- if (params)
+- VIR_FREE(tmp);
+- } else if (STRPREFIX(tmp, "mem-merge=off")) {
+- def->mem.nosharepages = true;
+- }
++ }
++ j++;
++ }
++
++ /* handle all remaining "-machine" parameters */
++ while ((param = list[j++])) {
++ if (STRPREFIX(param, "dump-guest-core=")) {
++ param += strlen("dump-guest-core=");
++ def->mem.dump_core = virDomainMemDumpTypeFromString(param);
++ if (def->mem.dump_core <= 0)
++ def->mem.dump_core = VIR_DOMAIN_MEM_DUMP_DEFAULT;
++ } else if (STRPREFIX(param, "mem-merge=off")) {
++ def->mem.nosharepages = true;
++ } else if (STRPREFIX(param, "accel=kvm")) {
++ def->virtType = VIR_DOMAIN_VIRT_KVM;
++ def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+ }
+ }
++ virStringFreeList(list);
+ } else if (STREQ(arg, "-serial")) {
+ WANT_VALUE();
+ if (STRNEQ(val, "none")) {
+--
+1.8.3.2
+
--- /dev/null
+From e32ede7d892db2b5903039e43bed2d490120625a Mon Sep 17 00:00:00 2001
+Message-Id: <e32ede7d892db2b5903039e43bed2d490120625a.1377873637.git.jdenemar@redhat.com>
+From: Guannan Ren <gren@redhat.com>
+Date: Thu, 8 Aug 2013 16:07:26 +0800
+Subject: [PATCH] qemu: refactor qemuDomainCheckDiskPresence for only disk
+ presence check
+
+Resovles:https://bugzilla.redhat.com/show_bug.cgi?id=910171
+(cherry picked from commit e2ccc96cf0ea53aa6198efdfba79996c360567d7)
+
+Refactor this function to make it focus on disk presence checking,
+including diskchain checking, and not only for CDROM and Floppy.
+This change is good for the following patches.
+---
+ src/qemu/qemu_domain.c | 98 +++++++++++++++++++++++++++++---------------------
+ 1 file changed, 58 insertions(+), 40 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index dc72722..13303da 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -2067,6 +2067,61 @@ cleanup:
+ virObjectUnref(cfg);
+ }
+
++static int
++qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
++ virDomainObjPtr vm,
++ virDomainDiskDefPtr disk,
++ bool cold_boot)
++{
++ char uuid[VIR_UUID_STRING_BUFLEN];
++ virDomainEventPtr event = NULL;
++ int startupPolicy = disk->startupPolicy;
++
++ virUUIDFormat(vm->def->uuid, uuid);
++
++ switch ((enum virDomainStartupPolicy) startupPolicy) {
++ case VIR_DOMAIN_STARTUP_POLICY_OPTIONAL:
++ break;
++
++ case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
++ virReportSystemError(errno,
++ _("cannot access file '%s'"),
++ disk->src);
++ goto error;
++ break;
++
++ case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
++ if (cold_boot) {
++ virReportSystemError(errno,
++ _("cannot access file '%s'"),
++ disk->src);
++ goto error;
++ }
++ break;
++
++ case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
++ case VIR_DOMAIN_STARTUP_POLICY_LAST:
++ /* this should never happen */
++ break;
++ }
++
++ VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
++ "due to inaccessible source '%s'",
++ disk->dst, vm->def->name, uuid, disk->src);
++
++ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
++ VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
++ if (event)
++ qemuDomainEventQueue(driver, event);
++
++ VIR_FREE(disk->src);
++
++ return 0;
++
++error:
++ return -1;
++}
++
+ int
+ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+@@ -2075,12 +2130,8 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ int ret = -1;
+ size_t i;
+ virDomainDiskDefPtr disk;
+- char uuid[VIR_UUID_STRING_BUFLEN];
+- virDomainEventPtr event = NULL;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
+- virUUIDFormat(vm->def->uuid, uuid);
+-
+ for (i = 0; i < vm->def->ndisks; i++) {
+ disk = vm->def->disks[i];
+
+@@ -2094,42 +2145,9 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ continue;
+ }
+
+- switch ((enum virDomainStartupPolicy) disk->startupPolicy) {
+- case VIR_DOMAIN_STARTUP_POLICY_OPTIONAL:
+- break;
+-
+- case VIR_DOMAIN_STARTUP_POLICY_MANDATORY:
+- virReportSystemError(errno,
+- _("cannot access file '%s'"),
+- disk->src);
+- goto cleanup;
+- break;
+-
+- case VIR_DOMAIN_STARTUP_POLICY_REQUISITE:
+- if (cold_boot) {
+- virReportSystemError(errno,
+- _("cannot access file '%s'"),
+- disk->src);
+- goto cleanup;
+- }
+- break;
+-
+- case VIR_DOMAIN_STARTUP_POLICY_DEFAULT:
+- case VIR_DOMAIN_STARTUP_POLICY_LAST:
+- /* this should never happen */
+- break;
+- }
+-
+- VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
+- "due to inaccessible source '%s'",
+- disk->dst, vm->def->name, uuid, disk->src);
+-
+- event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
+- VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
+- if (event)
+- qemuDomainEventQueue(driver, event);
+-
+- VIR_FREE(disk->src);
++ if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
++ cold_boot) < 0)
++ goto cleanup;
+ }
+
+ ret = 0;
+--
+1.8.3.2
+
--- /dev/null
+From 16e88f683d1a8d41596202d1dfa3d3c6b52655c5 Mon Sep 17 00:00:00 2001
+Message-Id: <16e88f683d1a8d41596202d1dfa3d3c6b52655c5.1377873636.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 6 Aug 2013 13:23:19 -0600
+Subject: [PATCH] qemu: rename some functions in qemu_command.c
+
+This patch is part of the resolution to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=819968
+
+* qemuDomainPCIAddressSetNextAddr
+
+The name of this function was confusing because 1) other functions in
+the file that end in "Addr" are only operating on a single function of
+one PCI slot, not the entire slot, while functions that do something
+with the entire slot end in "Slot", and 2) it didn't contain a verb
+describing what it is doing (the "Set" refers to the set that contains
+all PCI buses in the system, used to keep track of which slots in
+which buses are already reserved for use).
+
+It is now renamed to qemuDomainPCIAddressReserveNextSlot, which more
+clearly describes what it is doing. Arguably, it could have been
+changed to qemuDomainPCIAddressSetReserveNextSlot, but 1) the word
+"set" is confusing in this context because it could be intended as a
+verb or as a noun, and 2) most other functions that operate on a
+single slot or address within this set are also named
+qemuDomainPCIAddress... rather than qemuDomainPCIAddressSet... Only
+the Create, Free, and Grow functions for an address set (which modify the
+entire set, not just one element) use "Set" in their name.
+
+* qemuPCIAddressAsString, qemuPCIAddressValidate
+
+All the other functions in this set are named
+qemuDomainPCIAddressxxxxx, so I renamed these to be consistent.
+(cherry picked from commit 29e3a1df474aeb35b5eeca4930e7748cd2664472)
+---
+ src/qemu/qemu_command.c | 78 ++++++++++++++++++++++++++++++-------------------
+ src/qemu/qemu_command.h | 6 ++--
+ 2 files changed, 51 insertions(+), 33 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index aa3a2fd..4345456 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1439,9 +1439,9 @@ struct _qemuDomainPCIAddressSet {
+ * with the specified PCI address set.
+ */
+ static bool
+-qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UNUSED,
+- virDevicePCIAddressPtr addr,
+- qemuDomainPCIConnectFlags flags)
++qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
++ virDevicePCIAddressPtr addr,
++ qemuDomainPCIConnectFlags flags)
+ {
+ qemuDomainPCIAddressBusPtr bus;
+
+@@ -1578,7 +1578,7 @@ qemuDomainPCIAddressSetGrow(qemuDomainPCIAddressSetPtr addrs,
+
+
+ static char *
+-qemuPCIAddressAsString(virDevicePCIAddressPtr addr)
++qemuDomainPCIAddressAsString(virDevicePCIAddressPtr addr)
+ {
+ char *str;
+
+@@ -1648,10 +1648,10 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ * that the bus is of the correct type for the device (via
+ * comparing the flags).
+ */
+- if (!qemuPCIAddressValidate(addrs, addr, flags))
++ if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
+ return -1;
+
+- if (!(str = qemuPCIAddressAsString(addr)))
++ if (!(str = qemuDomainPCIAddressAsString(addr)))
+ goto cleanup;
+
+ /* check if already in use */
+@@ -1729,7 +1729,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+ if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
+ goto cleanup;
+ /* Reserve 1 extra slot for a (potential) bridge */
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
+ goto cleanup;
+
+ for (i = 1; i < addrs->nbuses; i++) {
+@@ -1740,7 +1740,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+ i, bus->model)) < 0)
+ goto cleanup;
+ /* If we added a new bridge, we will need one more address */
+- if (rv > 0 && qemuDomainPCIAddressSetNextAddr(addrs, &info, flags) < 0)
++ if (rv > 0 && qemuDomainPCIAddressReserveNextSlot(addrs, &info,
++ flags) < 0)
+ goto cleanup;
+ }
+ nbuses = addrs->nbuses;
+@@ -1881,7 +1882,7 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
+ return -1;
+
+- if (!(str = qemuPCIAddressAsString(addr)))
++ if (!(str = qemuDomainPCIAddressAsString(addr)))
+ return -1;
+
+ VIR_DEBUG("Reserving PCI addr %s", str);
+@@ -1923,7 +1924,7 @@ qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
+ return -1;
+
+- if (!(str = qemuPCIAddressAsString(addr)))
++ if (!(str = qemuDomainPCIAddressAsString(addr)))
+ return -1;
+
+ VIR_DEBUG("Reserving PCI slot %s", str);
+@@ -1959,12 +1960,12 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ return -1;
+ }
+
+- if (!qemuPCIAddressValidate(addrs, &dev->addr.pci, flags))
++ if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci, flags))
+ return -1;
+
+ ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
+ } else {
+- ret = qemuDomainPCIAddressSetNextAddr(addrs, dev, flags);
++ ret = qemuDomainPCIAddressReserveNextSlot(addrs, dev, flags);
+ }
+ return ret;
+ }
+@@ -1986,7 +1987,7 @@ qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs,
+ */
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPES_MASK;
+
+- if (!qemuPCIAddressValidate(addrs, addr, flags))
++ if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
+ return -1;
+
+ addrs->buses[addr->bus].slots[addr->slot] = 0;
+@@ -2059,9 +2060,9 @@ success:
+ }
+
+ int
+-qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
+- virDomainDeviceInfoPtr dev,
+- qemuDomainPCIConnectFlags flags)
++qemuDomainPCIAddressReserveNextSlot(qemuDomainPCIAddressSetPtr addrs,
++ virDomainDeviceInfoPtr dev,
++ qemuDomainPCIConnectFlags flags)
+ {
+ virDevicePCIAddress addr;
+ if (qemuDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0)
+@@ -2188,14 +2189,16 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+ primaryVideo->info.addr.pci.function = 0;
+ addrptr = &primaryVideo->info.addr.pci;
+
+- if (!qemuPCIAddressValidate(addrs, addrptr, flags))
++ if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
+ goto error;
+
+ if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
+ if (qemuDeviceVideoUsable) {
+ virResetLastError();
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &primaryVideo->info, flags) < 0)
+- goto error;;
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &primaryVideo->info,
++ flags) < 0)
++ goto error;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("PCI address 0:0:2.0 is in use, "
+@@ -2296,7 +2299,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ continue;
+ if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &def->controllers[i]->info,
++ flags) < 0)
+ goto error;
+ }
+ }
+@@ -2307,7 +2312,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+
+ /* Only support VirtIO-9p-pci so far. If that changes,
+ * we might need to skip devices here */
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->fss[i]->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2321,7 +2327,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
+ continue;
+ }
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2334,7 +2341,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK)
+ continue;
+
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->sounds[i]->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2409,7 +2417,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ def->controllers[i]->info.addr.pci = addr;
+ } else {
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &def->controllers[i]->info,
++ flags) < 0)
+ goto error;
+ }
+ }
+@@ -2434,7 +2444,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ goto error;
+ }
+
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2446,7 +2457,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+- if (qemuDomainPCIAddressSetNextAddr(addrs, def->hostdevs[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ def->hostdevs[i]->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2454,7 +2467,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ if (def->memballoon &&
+ def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
+ def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->memballoon->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &def->memballoon->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2462,7 +2477,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ if (def->rng &&
+ def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
+ def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->rng->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs,
++ &def->rng->info, flags) < 0)
+ goto error;
+ }
+
+@@ -2470,7 +2486,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ if (def->watchdog &&
+ def->watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_IB700 &&
+ def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->watchdog->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->watchdog->info,
++ flags) < 0)
+ goto error;
+ }
+
+@@ -2483,7 +2500,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
+ }
+ if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
+- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info, flags) < 0)
++ if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info,
++ flags) < 0)
+ goto error;
+ }
+ for (i = 0; i < def->ninputs; i++) {
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index 2b02d6e..c9f1600 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -254,9 +254,9 @@ int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
+ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ qemuDomainPCIConnectFlags flags);
+-int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
+- virDomainDeviceInfoPtr dev,
+- qemuDomainPCIConnectFlags flags);
++int qemuDomainPCIAddressReserveNextSlot(qemuDomainPCIAddressSetPtr addrs,
++ virDomainDeviceInfoPtr dev,
++ qemuDomainPCIConnectFlags flags);
+ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev);
+ int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
+--
+1.8.3.2
+
--- /dev/null
+From 2d3d991158a202c50c6c74c6b910b0facb5dcc37 Mon Sep 17 00:00:00 2001
+Message-Id: <2d3d991158a202c50c6c74c6b910b0facb5dcc37.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:42 -0600
+Subject: [PATCH] qemu: replace multiple strcmps with a switch on an enum
+
+I'm not sure why this code was written to compare the strings that it
+had just retrieved from an enum->string conversion, rather than just
+look at the original enum values, but this yields the same results,
+and is much more efficient (especially as you add more devices).
+
+This is a prerequisite for patches to resolve:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+(cherry picked from commit 8e0dab3a8e2e4b0c580739587fa4a474c7a4afc8)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index f025e8c..8b03470 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -5131,13 +5131,18 @@ qemuBuildSoundDevStr(virDomainDefPtr def,
+ goto error;
+ }
+
+- /* Hack for weirdly unusual devices name in QEMU */
+- if (STREQ(model, "es1370"))
++ /* Hack for devices with different names in QEMU and libvirt */
++ switch (sound->model) {
++ case VIR_DOMAIN_SOUND_MODEL_ES1370:
+ model = "ES1370";
+- else if (STREQ(model, "ac97"))
++ break;
++ case VIR_DOMAIN_SOUND_MODEL_AC97:
+ model = "AC97";
+- else if (STREQ(model, "ich6"))
++ break;
++ case VIR_DOMAIN_SOUND_MODEL_ICH6:
+ model = "intel-hda";
++ break;
++ }
+
+ virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
+ if (qemuBuildDeviceAddressStr(&buf, def, &sound->info, qemuCaps) < 0)
+--
+1.8.3.2
+
--- /dev/null
+From 823e31ecb90aeb3d3362d9ff22f689e062d0e28e Mon Sep 17 00:00:00 2001
+Message-Id: <823e31ecb90aeb3d3362d9ff22f689e062d0e28e.1382534061.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Mon, 21 Oct 2013 10:12:58 -0600
+Subject: [PATCH] qemu: simplify calling qemuDomainHostdevNetConfigRestore
+
+This is a prerequisite to the fix for
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1005682
+
+This function was called in three places, and in each the call was
+qualified by a slightly different conditional. In reality, this
+function should only be called for a hostdev if all of the following
+are true:
+
+ 1) mode='subsystem'
+ 2) type='pci'
+ 3) there is a parent device definition which is an <interface>
+ (VIR_DOMAIN_DEVICE_NET)
+
+We can simplify the callers and make them more consistent by checking
+these conditions at the top ov qemuDomainHostdevNetConfigRestore and
+returning 0 if one of them isn't satisfied.
+
+The location of the call to qemuDomainHostdevNetConfigRestore() has
+also been changed in the hot-plug case - it is moved into the caller
+of its previous location (i.e. from qemuDomainRemovePCIHostDevice() to
+qemuDomainRemoveHostDevice()). This was done to be more consistent
+about which functions pay attention to whether or not this is one of
+the special <interface> hostdevs or just a normal hostdev -
+qemuDomainRemoveHostDevice() already contained a call to
+networkReleaseActualDevice() and virDomainNetDefFree(), so it makes
+sense for it to also handle the resetting of the device's MAC address
+and vlan tag (which is what's done by
+qemuDomainHostdevNetConfigRestore()).
+
+(cherry picked from commit 7a600cf77fb649e3412d4bf4f9eefba046562880)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hostdev.c | 33 ++++++++++++++-------------------
+ src/qemu/qemu_hotplug.c | 13 ++++---------
+ 2 files changed, 18 insertions(+), 28 deletions(-)
+
+diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
+index 43c03cc..ca26dde 100644
+--- a/src/qemu/qemu_hostdev.c
++++ b/src/qemu/qemu_hostdev.c
+@@ -466,6 +466,15 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
+ bool port_profile_associate = false;
+ int isvf;
+
++ /* This is only needed for PCI devices that have been defined
++ * using <interface type='hostdev'>. For all others, it is a NOP.
++ */
++ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
++ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI ||
++ hostdev->parent.type != VIR_DOMAIN_DEVICE_NET ||
++ !hostdev->parent.data.net)
++ return 0;
++
+ isvf = qemuDomainHostdevIsVirtualFunction(hostdev);
+ if (isvf <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+@@ -799,14 +808,9 @@ inactivedevs:
+ }
+
+ resetvfnetconfig:
+- for (i = 0; last_processed_hostdev_vf != -1 &&
+- i < last_processed_hostdev_vf; i++) {
+- virDomainHostdevDefPtr hostdev = hostdevs[i];
+- if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+- hostdev->parent.data.net) {
+- qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
+- }
+- }
++ for (i = 0;
++ last_processed_hostdev_vf != -1 && i < last_processed_hostdev_vf; i++)
++ qemuDomainHostdevNetConfigRestore(hostdevs[i], cfg->stateDir);
+
+ reattachdevs:
+ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
+@@ -1270,17 +1274,8 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
+ * For SRIOV net host devices, unset mac and port profile before
+ * reset and reattach device
+ */
+- for (i = 0; i < nhostdevs; i++) {
+- virDomainHostdevDefPtr hostdev = hostdevs[i];
+- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+- continue;
+- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+- continue;
+- if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+- hostdev->parent.data.net) {
+- qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
+- }
+- }
++ for (i = 0; i < nhostdevs; i++)
++ qemuDomainHostdevNetConfigRestore(hostdevs[i], cfg->stateDir);
+
+ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
+ virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index cdbafa7..dcee86c 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -2397,18 +2397,10 @@ qemuDomainRemovePCIHostDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainHostdevDefPtr hostdev)
+ {
+- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
+ virPCIDevicePtr pci;
+ virPCIDevicePtr activePci;
+
+- /*
+- * For SRIOV net host devices, unset mac and port profile before
+- * reset and reattach device
+- */
+- if (hostdev->parent.data.net)
+- qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
+-
+ virObjectLock(driver->activePciHostdevs);
+ virObjectLock(driver->inactivePciHostdevs);
+ pci = virPCIDeviceNew(subsys->u.pci.addr.domain, subsys->u.pci.addr.bus,
+@@ -2429,7 +2421,6 @@ qemuDomainRemovePCIHostDevice(virQEMUDriverPtr driver,
+ virObjectUnlock(driver->inactivePciHostdevs);
+
+ qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
+- virObjectUnref(cfg);
+ }
+
+ static void
+@@ -2465,6 +2456,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainHostdevDefPtr hostdev)
+ {
++ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virDomainNetDefPtr net = NULL;
+ virDomainEventPtr event;
+ size_t i;
+@@ -2496,6 +2488,8 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
+
+ virDomainAuditHostdev(vm, hostdev, "detach", true);
+
++ qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
++
+ switch ((enum virDomainHostdevSubsysType) hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ qemuDomainRemovePCIHostDevice(driver, vm, hostdev);
+@@ -2524,6 +2518,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
+ networkReleaseActualDevice(net);
+ virDomainNetDefFree(net);
+ }
++ virObjectUnref(cfg);
+ }
+
+
+--
+1.8.4
+
--- /dev/null
+From 28c7179c49ed6b21301c9bbf9adb896422816e7c Mon Sep 17 00:00:00 2001
+Message-Id: <28c7179c49ed6b21301c9bbf9adb896422816e7c.1382534061.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Mon, 14 Oct 2013 16:38:48 +0200
+Subject: [PATCH] qemu: snapshot: Add support for compressing external snapshot
+ memory
+
+The regular save image code has the support to compress images using a
+specified algorithm. This was not implemented for external checkpoints
+although it shares most of the backend code.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1017227
+(cherry picked from commit 7df5093f67f0560d0440807b4363746e032ad942)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/libvirtd_qemu.aug | 1 +
+ src/qemu/qemu.conf | 6 ++++++
+ src/qemu/qemu_conf.c | 2 ++
+ src/qemu/qemu_conf.h | 1 +
+ src/qemu/qemu_driver.c | 23 +++++++++++++++++++++--
+ src/qemu/test_libvirtd_qemu.aug.in | 1 +
+ 6 files changed, 32 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
+index 5344125..3a874ca 100644
+--- a/src/qemu/libvirtd_qemu.aug
++++ b/src/qemu/libvirtd_qemu.aug
+@@ -56,6 +56,7 @@ module Libvirtd_qemu =
+
+ let save_entry = str_entry "save_image_format"
+ | str_entry "dump_image_format"
++ | str_entry "snapshot_image_format"
+ | str_entry "auto_dump_path"
+ | bool_entry "auto_dump_bypass_cache"
+ | bool_entry "auto_start_bypass_cache"
+diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
+index a2735cb..be6ab2a 100644
+--- a/src/qemu/qemu.conf
++++ b/src/qemu/qemu.conf
+@@ -269,8 +269,14 @@
+ # the requested compression program can't be found, this falls
+ # back to "raw" compression.
+ #
++# snapshot_image_format specifies the compression algorithm of the memory save
++# image when an external snapshot of a domain is taken. This does not apply
++# on disk image format. It is an error if the specified format isn't valid,
++# or the requested compression program can't be found.
++#
+ #save_image_format = "raw"
+ #dump_image_format = "raw"
++#snapshot_image_format = "raw"
+
+ # When a domain is configured to be auto-dumped when libvirtd receives a
+ # watchdog event from qemu guest, libvirtd will save dump files in directory
+diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
+index 86ed9ed..c9d90db 100644
+--- a/src/qemu/qemu_conf.c
++++ b/src/qemu/qemu_conf.c
+@@ -502,6 +502,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
+
+ GET_VALUE_STR("save_image_format", cfg->saveImageFormat);
+ GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat);
++ GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat);
++
+ GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath);
+ GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache);
+ GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache);
+diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
+index 8229cfc..dc5f8db 100644
+--- a/src/qemu/qemu_conf.h
++++ b/src/qemu/qemu_conf.h
+@@ -143,6 +143,7 @@ struct _virQEMUDriverConfig {
+
+ char *saveImageFormat;
+ char *dumpImageFormat;
++ char *snapshotImageFormat;
+
+ char *autoDumpPath;
+ bool autoDumpBypassCache;
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 14b0d57..3d0b56e 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -12391,6 +12391,8 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
+ bool transaction = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION);
+ int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
+ bool pmsuspended = false;
++ virQEMUDriverConfigPtr cfg = NULL;
++ int compressed = QEMU_SAVE_FORMAT_RAW;
+
+ if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SNAPSHOT) < 0)
+ goto cleanup;
+@@ -12452,12 +12454,28 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
+ JOB_MASK(QEMU_JOB_SUSPEND) |
+ JOB_MASK(QEMU_JOB_MIGRATION_OP));
+
++ cfg = virQEMUDriverGetConfig(driver);
++ if (cfg->snapshotImageFormat) {
++ compressed = qemuSaveCompressionTypeFromString(cfg->snapshotImageFormat);
++ if (compressed < 0) {
++ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
++ _("Invalid snapshot image format specified "
++ "in configuration file"));
++ goto cleanup;
++ }
++ if (!qemuCompressProgramAvailable(compressed)) {
++ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
++ _("Compression program for image format "
++ "in configuration file isn't available"));
++ goto cleanup;
++ }
++ }
++
+ if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)))
+ goto endjob;
+
+ if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file,
+- xml, QEMU_SAVE_FORMAT_RAW,
+- resume, 0,
++ xml, compressed, resume, 0,
+ QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
+ goto endjob;
+
+@@ -12546,6 +12564,7 @@ endjob:
+
+ cleanup:
+ VIR_FREE(xml);
++ virObjectUnref(cfg);
+ if (memory_unlink && ret < 0)
+ unlink(snap->def->file);
+
+diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
+index d4e4fae..d5df46c 100644
+--- a/src/qemu/test_libvirtd_qemu.aug.in
++++ b/src/qemu/test_libvirtd_qemu.aug.in
+@@ -48,6 +48,7 @@ module Test_libvirtd_qemu =
+ }
+ { "save_image_format" = "raw" }
+ { "dump_image_format" = "raw" }
++{ "snapshot_image_format" = "raw" }
+ { "auto_dump_path" = "/var/lib/libvirt/qemu/dump" }
+ { "auto_dump_bypass_cache" = "0" }
+ { "auto_start_bypass_cache" = "0" }
+--
+1.8.4
+
--- /dev/null
+From bc76fb17caf756582784cf9a0fbae2a0956ec3c5 Mon Sep 17 00:00:00 2001
+Message-Id: <bc76fb17caf756582784cf9a0fbae2a0956ec3c5.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:43 -0600
+Subject: [PATCH] qemu: support ich9-intel-hda audio device
+
+This resolves one of the issues in:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+This device is identical to qemu's "intel-hda" device (known as "ich6"
+in libvirt), but has a different PCI device ID (which matches the ID
+of the hda audio built into the ich9 chipset, of course). It's not
+supported in earlier versions of qemu, so it requires a capability
+bit.
+
+(cherry picked from commit b83d26f6c434f80c71a2a7a0823b1ec16b798ca3)
+
+Conflicts:
+ src/qemu/qemu_capabilities.c
+ src/qemu/qemu_capabilities.h
+
+ There were a few other capabilities added upstream that
+ haven't yet been added to the RHEL7 branch; these caused a
+ mismatch in the capabilities enum.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/schemas/domaincommon.rng | 1 +
+ src/conf/domain_conf.c | 6 ++++--
+ src/conf/domain_conf.h | 1 +
+ src/qemu/qemu_capabilities.c | 2 ++
+ src/qemu/qemu_capabilities.h | 1 +
+ src/qemu/qemu_command.c | 16 ++++++++++++++--
+ tests/qemuxml2argvdata/qemuxml2argv-sound-device.args | 7 ++++++-
+ tests/qemuxml2argvdata/qemuxml2argv-sound-device.xml | 5 +++++
+ tests/qemuxml2argvtest.c | 3 ++-
+ 9 files changed, 36 insertions(+), 6 deletions(-)
+
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index dfcd61c..838f657 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -2896,6 +2896,7 @@
+ <value>pcspk</value>
+ <value>ac97</value>
+ <value>ich6</value>
++ <value>ich9</value>
+ </choice>
+ </attribute>
+ <interleave>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index c391eae..bca2151 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -455,7 +455,8 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
+ "es1370",
+ "pcspk",
+ "ac97",
+- "ich6")
++ "ich6",
++ "ich9")
+
+ VIR_ENUM_IMPL(virDomainMemDump, VIR_DOMAIN_MEM_DUMP_LAST,
+ "default",
+@@ -8397,7 +8398,8 @@ virDomainSoundDefParseXML(const xmlNodePtr node,
+ goto error;
+ }
+
+- if (def->model == VIR_DOMAIN_SOUND_MODEL_ICH6) {
++ if (def->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
++ def->model == VIR_DOMAIN_SOUND_MODEL_ICH9) {
+ int ncodecs;
+ xmlNodePtr *codecNodes = NULL;
+
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index b9e9600..5d2cb83 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -1237,6 +1237,7 @@ enum virDomainSoundModel {
+ VIR_DOMAIN_SOUND_MODEL_PCSPK,
+ VIR_DOMAIN_SOUND_MODEL_AC97,
+ VIR_DOMAIN_SOUND_MODEL_ICH6,
++ VIR_DOMAIN_SOUND_MODEL_ICH9,
+
+ VIR_DOMAIN_SOUND_MODEL_LAST
+ };
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 47cc07a..9b1d9f5 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -235,6 +235,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+ "vnc-share-policy", /* 150 */
+ "device-del-event",
+ "dmi-to-pci-bridge",
++ "ich9-intel-hda",
+ );
+
+ struct _virQEMUCaps {
+@@ -1383,6 +1384,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
+ { "vfio-pci", QEMU_CAPS_DEVICE_VFIO_PCI },
+ { "scsi-generic", QEMU_CAPS_DEVICE_SCSI_GENERIC },
+ { "i82801b11-bridge", QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE },
++ { "ich9-intel-hda", QEMU_CAPS_DEVICE_ICH9_INTEL_HDA },
+ };
+
+ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index 074e55d..c992dcb 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -191,6 +191,7 @@ enum virQEMUCapsFlags {
+ QEMU_CAPS_VNC_SHARE_POLICY = 150, /* set display sharing policy */
+ QEMU_CAPS_DEVICE_DEL_EVENT = 151, /* DEVICE_DELETED event */
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE = 152, /* -device i82801b11-bridge */
++ QEMU_CAPS_DEVICE_ICH9_INTEL_HDA = 153, /* -device ich9-intel-hda */
+
+ QEMU_CAPS_LAST, /* this must always be the last item */
+ };
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 8b03470..2de7678 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -1758,6 +1758,7 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ case VIR_DOMAIN_DEVICE_SOUND:
+ switch (device->data.sound->model) {
+ case VIR_DOMAIN_SOUND_MODEL_ICH6:
++ case VIR_DOMAIN_SOUND_MODEL_ICH9:
+ flags = (QEMU_PCI_CONNECT_TYPE_PCI |
+ QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
+ break;
+@@ -5142,6 +5143,15 @@ qemuBuildSoundDevStr(virDomainDefPtr def,
+ case VIR_DOMAIN_SOUND_MODEL_ICH6:
+ model = "intel-hda";
+ break;
++ case VIR_DOMAIN_SOUND_MODEL_ICH9:
++ model = "ich9-intel-hda";
++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ICH9_INTEL_HDA)) {
++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
++ _("The ich9-intel-hda audio controller "
++ "is not supported in this QEMU binary"));
++ goto error;
++ }
++ break;
+ }
+
+ virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
+@@ -8866,7 +8876,8 @@ qemuBuildCommandLine(virConnectPtr conn,
+
+ virCommandAddArg(cmd, str);
+
+- if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6) {
++ if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
++ sound->model == VIR_DOMAIN_SOUND_MODEL_ICH9) {
+ char *codecstr = NULL;
+
+ for (j = 0; j < sound->ncodecs; j++) {
+@@ -8912,7 +8923,8 @@ qemuBuildCommandLine(virConnectPtr conn,
+ goto error;
+ }
+
+- if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6) {
++ if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
++ sound->model == VIR_DOMAIN_SOUND_MODEL_ICH9) {
+ VIR_FREE(modstr);
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary lacks hda support"));
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args
+index 7c5f05c..997e458 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args
+@@ -8,4 +8,9 @@ id=sound4-codec0,bus=sound4.0,cad=0 \
+ -device intel-hda,id=sound5,bus=pci.0,addr=0x6 \
+ -device hda-micro,id=sound5-codec0,bus=sound5.0,cad=0 \
+ -device hda-duplex,id=sound5-codec1,bus=sound5.0,cad=1 \
+--device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7
++-device ich9-intel-hda,id=sound6,bus=pci.0,addr=0x7 -device hda-duplex,\
++id=sound6-codec0,bus=sound6.0,cad=0 \
++-device ich9-intel-hda,id=sound7,bus=pci.0,addr=0x8 \
++-device hda-micro,id=sound7-codec0,bus=sound7.0,cad=0 \
++-device hda-duplex,id=sound7-codec1,bus=sound7.0,cad=1 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x9
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.xml b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.xml
+index 7bf9ff9..8ce718e 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.xml
++++ b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.xml
+@@ -31,6 +31,11 @@
+ <codec type='micro'/>
+ <codec type='duplex'/>
+ </sound>
++ <sound model='ich9'/>
++ <sound model='ich9'>
++ <codec type='micro'/>
++ <codec type='duplex'/>
++ </sound>
+ <memballoon model='virtio'/>
+ </devices>
+ </domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index aa43145..23ea2ee 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -841,7 +841,8 @@ mymain(void)
+ DO_TEST("sound", NONE);
+ DO_TEST("sound-device",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+- QEMU_CAPS_HDA_DUPLEX, QEMU_CAPS_HDA_MICRO);
++ QEMU_CAPS_HDA_DUPLEX, QEMU_CAPS_HDA_MICRO,
++ QEMU_CAPS_DEVICE_ICH9_INTEL_HDA);
+ DO_TEST("fs9p",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_FSDEV,
+ QEMU_CAPS_FSDEV_WRITEOUT);
+--
+1.8.3.2
+
--- /dev/null
+From 538c19af8b18ecaeda0dc30aa3140bc933283035 Mon Sep 17 00:00:00 2001
+Message-Id: <538c19af8b18ecaeda0dc30aa3140bc933283035.1377873637.git.jdenemar@redhat.com>
+From: Guannan Ren <gren@redhat.com>
+Date: Thu, 8 Aug 2013 16:07:30 +0800
+Subject: [PATCH] qemu: support to drop disk with 'optional' startupPolicy
+
+Resovles: https://bugzilla.redhat.com/show_bug.cgi?id=910171
+(cherry picked from commit 8a160f11afe916284c569d4c23adb24f755e459e)
+
+Go through disks of guest, if one disk doesn't exist or its backing
+chain is broken, with 'optional' startupPolicy, for CDROM and Floppy
+we only discard its source path definition in xml, for disks we drop
+it from disk list and free it.
+---
+ include/libvirt/libvirt.h.in | 1 +
+ src/qemu/qemu_domain.c | 68 ++++++++++++++++++++++++++++++++------------
+ 2 files changed, 51 insertions(+), 18 deletions(-)
+
+diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
+index 7bd3559..52ac95d 100644
+--- a/include/libvirt/libvirt.h.in
++++ b/include/libvirt/libvirt.h.in
+@@ -4727,6 +4727,7 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr conn,
+ */
+ typedef enum {
+ VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
++ VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = 1,
+
+ #ifdef VIR_ENUM_SENTINELS
+ VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index d0f09ae..393af6b 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -2068,13 +2068,53 @@ cleanup:
+ }
+
+ static int
++qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver,
++ virDomainObjPtr vm,
++ virDomainDiskDefPtr disk)
++{
++ char uuid[VIR_UUID_STRING_BUFLEN];
++ virDomainEventPtr event = NULL;
++ virDomainDiskDefPtr del_disk = NULL;
++
++ virUUIDFormat(vm->def->uuid, uuid);
++
++ VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
++ "due to inaccessible source '%s'",
++ disk->dst, vm->def->name, uuid, disk->src);
++
++ if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
++ disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
++
++ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
++ disk->info.alias,
++ VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
++ VIR_FREE(disk->src);
++ } else {
++ event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
++ disk->info.alias,
++ VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START);
++
++ if (!(del_disk = virDomainDiskRemoveByName(vm->def, disk->src))) {
++ virReportError(VIR_ERR_INVALID_ARG,
++ _("no source device %s"), disk->src);
++ return -1;
++ }
++ virDomainDiskDefFree(del_disk);
++ }
++
++ if (event)
++ qemuDomainEventQueue(driver, event);
++
++ return 0;
++}
++
++static int
+ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ bool cold_boot)
+ {
+ char uuid[VIR_UUID_STRING_BUFLEN];
+- virDomainEventPtr event = NULL;
+ int startupPolicy = disk->startupPolicy;
+
+ virUUIDFormat(vm->def->uuid, uuid);
+@@ -2097,17 +2137,8 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
+ break;
+ }
+
+- virResetLastError();
+- VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
+- "due to inaccessible source '%s'",
+- disk->dst, vm->def->name, uuid, disk->src);
+-
+- event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
+- VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
+- if (event)
+- qemuDomainEventQueue(driver, event);
+-
+- VIR_FREE(disk->src);
++ if (qemuDomainCheckRemoveOptionalDisk(driver, vm, disk) < 0)
++ goto error;
+
+ return 0;
+
+@@ -2125,8 +2156,8 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ virDomainDiskDefPtr disk;
+
+ VIR_DEBUG("Checking for disk presence");
+- for (i = 0; i < vm->def->ndisks; i++) {
+- disk = vm->def->disks[i];
++ for (i = vm->def->ndisks; i > 0; i--) {
++ disk = vm->def->disks[i - 1];
+
+ if (!disk->src)
+ continue;
+@@ -2135,10 +2166,11 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
+ qemuDiskChainCheckBroken(disk) >= 0)
+ continue;
+
+- if (disk->startupPolicy) {
+- if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
+- cold_boot) >= 0)
+- continue;
++ if (disk->startupPolicy &&
++ qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
++ cold_boot) >= 0) {
++ virResetLastError();
++ continue;
+ }
+
+ goto error;
+--
+1.8.3.2
+
--- /dev/null
+From 543a43a569296df0aefa2493def35dc3fab594f0 Mon Sep 17 00:00:00 2001
+Message-Id: <543a43a569296df0aefa2493def35dc3fab594f0.1380703761.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 27 Sep 2013 05:19:44 -0600
+Subject: [PATCH] qemu: turn if into switch in
+ qemuDomainValidateDevicePCISlotsQ35
+
+This will make it simpler to add checks for other types of
+controllers.
+
+This is a prerequisite for patches to resolve:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1003983
+
+(cherry picked from commit c484fe16cb58174b9ea1c532eeea70be5893ca3c)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 41 +++++++++++++++++++++++------------------
+ 1 file changed, 23 insertions(+), 18 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 2de7678..47bb22a 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -2465,27 +2465,32 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+ char *addrStr = NULL;
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCIE;
+
+- /* Verify that the first SATA controller is at 00:1F.2 */
+- /* the q35 machine type *always* has a SATA controller at this address */
+ for (i = 0; i < def->ncontrollers; i++) {
+- if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA &&
+- def->controllers[i]->idx == 0) {
+- if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+- if (def->controllers[i]->info.addr.pci.domain != 0 ||
+- def->controllers[i]->info.addr.pci.bus != 0 ||
+- def->controllers[i]->info.addr.pci.slot != 0x1F ||
+- def->controllers[i]->info.addr.pci.function != 2) {
+- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+- _("Primary SATA controller must have PCI address 0:0:1f.2"));
+- goto cleanup;
++ switch (def->controllers[i]->type) {
++ case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
++ /* Verify that the first SATA controller is at 00:1F.2 the
++ * q35 machine type *always* has a SATA controller at this
++ * address.
++ */
++ if (def->controllers[i]->idx == 0) {
++ if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
++ if (def->controllers[i]->info.addr.pci.domain != 0 ||
++ def->controllers[i]->info.addr.pci.bus != 0 ||
++ def->controllers[i]->info.addr.pci.slot != 0x1F ||
++ def->controllers[i]->info.addr.pci.function != 2) {
++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++ _("Primary SATA controller must have PCI address 0:0:1f.2"));
++ goto cleanup;
++ }
++ } else {
++ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
++ def->controllers[i]->info.addr.pci.domain = 0;
++ def->controllers[i]->info.addr.pci.bus = 0;
++ def->controllers[i]->info.addr.pci.slot = 0x1F;
++ def->controllers[i]->info.addr.pci.function = 2;
+ }
+- } else {
+- def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+- def->controllers[i]->info.addr.pci.domain = 0;
+- def->controllers[i]->info.addr.pci.bus = 0;
+- def->controllers[i]->info.addr.pci.slot = 0x1F;
+- def->controllers[i]->info.addr.pci.function = 2;
+ }
++ break;
+ }
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 9c3b9ce8260ffc476f7539cc683e7efe59eba979 Mon Sep 17 00:00:00 2001
+Message-Id: <9c3b9ce8260ffc476f7539cc683e7efe59eba979.1380112457.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 20 Sep 2013 05:16:21 -0600
+Subject: [PATCH] qemu: use "ide" as device name for implicit SATA controller
+ on Q35
+
+This resolves https://bugzilla.redhat.com/show_bug.cgi?id=1008903
+
+The Q35 machinetype has an implicit SATA controller at 00:1F.2 which
+isn't given the "expected" id of ahci0 by qemu when it's created. The
+original suggested solution to this problem was to not specify any
+controller for the disks that use the default controller and just
+specify "unit=n" instead; qemu should then use the first IDE or SATA
+controller for the disk.
+
+Unfortunately, this "solution" is ignorant of the fact that in the
+case of SATA disks, the "unit" attribute in the disk XML is actually
+*not* being used for the unit, but is instead used to specify the
+"bus" number; each SATA controller has 6 buses, and each bus only
+allows a single unit. This makes it nonsensical to specify unit='n'
+where n is anything other than 0. It also means that the only way to
+connect more than a single device to the implicit SATA controller is
+to explicitly give the bus names, which happen to be "ide.$n", where
+$n can be replaced by the disk's "unit" number.
+
+(cherry picked from commit 30bb4c4b54ed3a23adc90c52540dd96b0cbcfbcc)
+
+Conflicts:
+
+tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args - this upstream
+file didn't yet exist in the libvirt release used as the base for the
+RHEL7 build.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c | 15 ++++++---------
+ tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +-
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 6e9657f..6a6b3cd 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -4280,18 +4280,15 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
+ if (qemuDomainMachineIsQ35(def) &&
+ disk->info.addr.drive.controller == 0) {
+ /* Q35 machines have an implicit ahci (sata) controller at
+- * 00:1F.2 which has no "id" associated with it. For this
+- * reason, we can't refer to it as "ahci0". Instead, we
+- * don't give an id, which qemu interprets as "use the
+- * first ahci controller". We then need to specify the
+- * unit with "unit=%d" rather than adding it onto the bus
+- * arg.
++ * 00:1F.2 which for some reason is hardcoded with the id
++ * "ide" instead of the seemingly more reasonable "ahci0"
++ * or "sata0".
+ */
+- virBufferAsprintf(&opt, ",unit=%d", disk->info.addr.drive.unit);
++ virBufferAsprintf(&opt, ",bus=ide.%d", disk->info.addr.drive.unit);
+ } else {
+ /* All other ahci controllers have been created by
+- * libvirt, so they *do* have an id, and we can identify
+- * them that way.
++ * libvirt, and we gave them the id "ahci${n}" where ${n}
++ * is the controller number. So we identify them that way.
+ */
+ virBufferAsprintf(&opt, ",bus=ahci%d.%d",
+ disk->info.addr.drive.controller,
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+index 9e67be5..151863e 100644
+--- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args
++++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
+@@ -4,5 +4,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
+ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+ -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-sata0-0-0 \
+--device ide-drive,unit=0,drive=drive-sata0-0-0,id=sata0-0-0 \
++-device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \
+ -vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
+--
+1.8.3.2
+
--- /dev/null
+From 3d2c6bc59a4cfb28b94a46d11484ec7a4562716c Mon Sep 17 00:00:00 2001
+Message-Id: <3d2c6bc59a4cfb28b94a46d11484ec7a4562716c.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:49 +0200
+Subject: [PATCH] qemuBuildCommandLine: Fall back to mem balloon if there's no
+ hard_limit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+If there's no hard_limit set and domain uses VFIO we still must lock the
+guest memory (prerequisite from qemu). Hence, we should compute the
+amount to be locked from max_balloon.
+(cherry picked from commit a7f94a40bb2554c56d0c6bea98a5843690dc3933)
+---
+ src/qemu/qemu_command.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 7bbfd03..6dfd141 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -9239,8 +9239,19 @@ qemuBuildCommandLine(virConnectPtr conn,
+ goto error;
+ }
+
+- if (mlock)
+- virCommandSetMaxMemLock(cmd, def->mem.hard_limit * 1024);
++ if (mlock) {
++ unsigned long long memKB;
++
++ /* VFIO requires all of the guest's memory to be
++ * locked resident, plus some amount for IO
++ * space. Alex Williamson suggested adding 1GiB for IO
++ * space just to be safe (some finer tuning might be
++ * nice, though).
++ */
++ memKB = def->mem.hard_limit ?
++ def->mem.hard_limit : def->mem.max_balloon + 1024 * 1024;
++ virCommandSetMaxMemLock(cmd, memKB * 1024);
++ }
+
+ virObjectUnref(cfg);
+ return cmd;
+--
+1.8.3.2
+
--- /dev/null
+From 893a8a0b2313e2634e86fc8dd754957ee6caada4 Mon Sep 17 00:00:00 2001
+Message-Id: <893a8a0b2313e2634e86fc8dd754957ee6caada4.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 22 Aug 2013 15:24:42 +0200
+Subject: [PATCH] qemuBuildNicDevStr: Add mq=on for multiqueue networking
+
+https://bugzilla.redhat.com/show_bug.cgi?id=651941
+
+If user requested multiqueue networking, beside multiple /dev/tap and
+/dev/vhost-net openings, we forgot to pass mq=on onto the -device
+virtio-net-pci command line. This is advised at:
+
+ http://www.linux-kvm.org/page/Multiqueue#Enable_MQ_feature
+(cherry picked from commit 4c2d0b29d7790df55d12216a56dbf0b29bcb00e3)
+---
+ src/qemu/qemu_command.c | 8 +++++++-
+ src/qemu/qemu_command.h | 1 +
+ src/qemu/qemu_hotplug.c | 5 ++++-
+ 3 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 43934f1..af8a5b4 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -4730,6 +4730,7 @@ qemuBuildNicDevStr(virDomainDefPtr def,
+ virDomainNetDefPtr net,
+ int vlan,
+ int bootindex,
++ bool multiqueue,
+ virQEMUCapsPtr qemuCaps)
+ {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+@@ -4782,6 +4783,8 @@ qemuBuildNicDevStr(virDomainDefPtr def,
+ virDomainVirtioEventIdxTypeToString(net->driver.virtio.event_idx));
+ }
+ }
++ if (usingVirtio && multiqueue)
++ virBufferAddLit(&buf, ",mq=on");
+ if (vlan == -1)
+ virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
+ else
+@@ -7275,7 +7278,10 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
+ virCommandAddArgList(cmd, "-netdev", host, NULL);
+ }
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+- if (!(nic = qemuBuildNicDevStr(def, net, vlan, bootindex, qemuCaps)))
++ bool multiqueue = tapfdSize > 1 || vhostfdSize > 1;
++
++ if (!(nic = qemuBuildNicDevStr(def, net, vlan, bootindex,
++ multiqueue, qemuCaps)))
+ goto cleanup;
+ virCommandAddArgList(cmd, "-device", nic, NULL);
+ } else {
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index 5c5c025..a9854a3 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -102,6 +102,7 @@ char * qemuBuildNicDevStr(virDomainDefPtr def,
+ virDomainNetDefPtr net,
+ int vlan,
+ int bootindex,
++ bool multiqueue,
+ virQEMUCapsPtr qemuCaps);
+
+ char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index cbe7072..b1f4586 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -859,7 +859,10 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
+ }
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+- if (!(nicstr = qemuBuildNicDevStr(vm->def, net, vlan, 0, priv->qemuCaps)))
++ bool multiqueue = tapfdSize > 1 || vhostfdSize > 1;
++
++ if (!(nicstr = qemuBuildNicDevStr(vm->def, net, vlan, 0,
++ multiqueue, priv->qemuCaps)))
+ goto try_remove;
+ } else {
+ if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
+--
+1.8.3.2
+
--- /dev/null
+From 487610941b91468f80e6fd91ad9379cef4a77c60 Mon Sep 17 00:00:00 2001
+Message-Id: <487610941b91468f80e6fd91ad9379cef4a77c60.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:50 +0200
+Subject: [PATCH] qemuDomainAttachHostPciDevice: Fall back to mem balloon if
+ there's no hard_limit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+If there's no hard_limit set and domain uses VFIO we still must lock
+the guest memory (prerequisite from qemu). Hence, we should compute
+the amount to be locked from max_balloon.
+(cherry picked from commit a45ec678e9bbe8a6157cb440f334b5d21e40f0b4)
+---
+ src/qemu/qemu_hotplug.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 89df4ad..98b8ad1 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1022,6 +1022,8 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+
+ if (hostdev->source.subsys.u.pci.backend
+ == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
++ unsigned long long memKB;
++
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("VFIO PCI device assignment is not "
+@@ -1034,8 +1036,9 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
+ * doesn't hurt to "change" the limit to the same value.
+ */
+ vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+- virProcessSetMaxMemLock(vm->pid,
+- vm->def->mem.hard_limit * 1024);
++ memKB = vm->def->mem.hard_limit ?
++ vm->def->mem.hard_limit : vm->def->mem.max_balloon + 1024 * 1024;
++ virProcessSetMaxMemLock(vm->pid, memKB);
+ vm->def->hostdevs[vm->def->nhostdevs--] = NULL;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From ffcc2cde1df1883b541ecb03b14e4edecd36d2ca Mon Sep 17 00:00:00 2001
+Message-Id: <ffcc2cde1df1883b541ecb03b14e4edecd36d2ca.1383922565.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 7 Nov 2013 14:49:06 +0100
+Subject: [PATCH] qemuMigrationBeginPhase: Check for 'drive-mirror' for NBD
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1022393
+
+So far we are checking if qemu supports 'nbd-server-start'. This,
+however, makes no sense on the source as nbd-server-* is used on the
+destination. On the source the 'drive-mirror' is used instead.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit b2f31af701cbd0da74b173d2625c5c53604eb999)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_migration.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
+index 379e381..fb5568e 100644
+--- a/src/qemu/qemu_migration.c
++++ b/src/qemu/qemu_migration.c
+@@ -1990,7 +1990,7 @@ static char
+ goto cleanup;
+
+ if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) &&
+- virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) {
++ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR)) {
+ /* TODO support NBD for TUNNELLED migration */
+ if (flags & VIR_MIGRATE_TUNNELLED) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+--
+1.8.4.2
+
--- /dev/null
+From 1a0c6817d8b67ccd2f2b059bf4c15ca3ab5345d2 Mon Sep 17 00:00:00 2001
+Message-Id: <1a0c6817d8b67ccd2f2b059bf4c15ca3ab5345d2.1377873642.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 26 Aug 2013 17:41:48 +0200
+Subject: [PATCH] qemuSetupMemoryCgroup: Handle hard_limit properly
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001143
+
+Since 16bcb3 we have a regression. The hard_limit is set
+unconditionally. By default the limit is zero. Hence, if user hasn't
+configured any, we set the zero in cgroup subsystem making the kernel
+kill the corresponding qemu process immediately. The proper fix is to
+set hard_limit iff user has configured any.
+(cherry picked from commit 94a24dd3a953f415596dd2800287c9010fa51c4c)
+---
+ src/qemu/qemu_cgroup.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index f07c450..3ebbeb7 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -428,7 +428,8 @@ qemuSetupMemoryCgroup(virDomainObjPtr vm)
+ }
+ }
+
+- if (virCgroupSetMemoryHardLimit(priv->cgroup, vm->def->mem.hard_limit) < 0)
++ if (vm->def->mem.hard_limit != 0 &&
++ virCgroupSetMemoryHardLimit(priv->cgroup, vm->def->mem.hard_limit) < 0)
+ return -1;
+
+ if (vm->def->mem.soft_limit != 0 &&
+--
+1.8.3.2
+
--- /dev/null
+From 9b8bdf3b99fed3cea29886a6c309a67e6e53924e Mon Sep 17 00:00:00 2001
+Message-Id: <9b8bdf3b99fed3cea29886a6c309a67e6e53924e.1377873641.git.jdenemar@redhat.com>
+From: Osier Yang <jyang@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:24 -0400
+Subject: [PATCH] qemu_conf: Fix broken logic for adding passthrough iscsi lun
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000159
+
+Following XML would fail :
+
+ <disk type='network' device='lun'>
+ <driver name='qemu' type='raw'/>
+ <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi/1'>
+ <host name='example.com' port='3260'/>
+ </source>
+ <target dev='sda' bus='scsi'/>
+ </disk>
+
+With the message:
+
+error: Failed to start domain iscsilun
+error: Unable to get device ID 'iqn.2013-07.com.example:iscsi/1': No such fi
+
+Cause was commit id '1f49b05a' which added 'virDomainDiskSourceIsBlockType'
+
+(cherry picked from commit 109d026a16bcb9f315dbeb665916bad718480957)
+---
+ src/qemu/qemu_conf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
+index 18e926c..86ed9ed 100644
+--- a/src/qemu/qemu_conf.c
++++ b/src/qemu/qemu_conf.c
+@@ -1065,7 +1065,7 @@ qemuSetUnprivSGIO(virDomainDeviceDefPtr dev)
+ disk = dev->data.disk;
+
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
+- virDomainDiskSourceIsBlockType(disk))
++ !virDomainDiskSourceIsBlockType(disk))
+ return 0;
+
+ path = disk->src;
+--
+1.8.3.2
+
--- /dev/null
+From 7d3cfd66fca3cea0ae883fa2cc565b9240cecfcd Mon Sep 17 00:00:00 2001
+Message-Id: <7d3cfd66fca3cea0ae883fa2cc565b9240cecfcd.1382534061.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 11:24:36 +0200
+Subject: [PATCH] qemu_conf: Introduce "migration_address"
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015215
+
+This configuration knob is there to override default listen address for
+-incoming for all qemu domains.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 1606d89c86545e63402ae4e379ceb98a1ca818e3)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/libvirtd_qemu.aug | 3 +++
+ src/qemu/qemu.conf | 6 ++++++
+ src/qemu/qemu_conf.c | 2 ++
+ src/qemu/qemu_conf.h | 3 +++
+ src/qemu/qemu_driver.c | 10 ++++++----
+ src/qemu/test_libvirtd_qemu.aug.in | 1 +
+ 6 files changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
+index 3a874ca..8ce6885 100644
+--- a/src/qemu/libvirtd_qemu.aug
++++ b/src/qemu/libvirtd_qemu.aug
+@@ -77,6 +77,8 @@ module Libvirtd_qemu =
+ | int_entry "keepalive_interval"
+ | int_entry "keepalive_count"
+
++ let network_entry = str_entry "migration_address"
++
+ (* Each entry in the config is one of the following ... *)
+ let entry = vnc_entry
+ | spice_entry
+@@ -86,6 +88,7 @@ module Libvirtd_qemu =
+ | process_entry
+ | device_entry
+ | rpc_entry
++ | network_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 be6ab2a..541db64 100644
+--- a/src/qemu/qemu.conf
++++ b/src/qemu/qemu.conf
+@@ -421,3 +421,9 @@
+ # Defaults to -1.
+ #
+ #seccomp_sandbox = 1
++
++
++
++# Override the listen address for all incoming migrations. Defaults to
++# 0.0.0.0 or :: in case if both host and qemu are capable of IPv6.
++#migration_address = "127.0.0.1"
+diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
+index c9d90db..cea139d 100644
+--- a/src/qemu/qemu_conf.c
++++ b/src/qemu/qemu_conf.c
+@@ -529,6 +529,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
+
+ GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox);
+
++ GET_VALUE_STR("migration_address", cfg->migrationAddress);
++
+ ret = 0;
+
+ cleanup:
+diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
+index dc5f8db..356e501 100644
+--- a/src/qemu/qemu_conf.h
++++ b/src/qemu/qemu_conf.h
+@@ -155,6 +155,9 @@ struct _virQEMUDriverConfig {
+ unsigned int keepAliveCount;
+
+ int seccompSandbox;
++
++ /* The default for -incoming */
++ char *migrationAddress;
+ };
+
+ /* Main driver state */
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 91549fb..c2445d9 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -10556,17 +10556,18 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ unsigned int flags)
+ {
+ virQEMUDriverPtr driver = dconn->privateData;
++ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virDomainDefPtr def = NULL;
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
+ const char *uri_in = NULL;
+- const char *listenAddress = NULL;
++ const char *listenAddress = cfg->migrationAddress;
+ char *origname = NULL;
+ int ret = -1;
+
+- virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
++ virCheckFlagsGoto(QEMU_MIGRATION_FLAGS, cleanup);
+ if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
+- return -1;
++ goto cleanup;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_XML,
+@@ -10580,7 +10581,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
+ &listenAddress) < 0)
+- return -1;
++ goto cleanup;
+
+ if (flags & VIR_MIGRATE_TUNNELLED) {
+ /* this is a logical error; we never should have gotten here with
+@@ -10607,6 +10608,7 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn,
+ cleanup:
+ VIR_FREE(origname);
+ virDomainDefFree(def);
++ virObjectUnref(cfg);
+ return ret;
+ }
+
+diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
+index d5df46c..be4518c 100644
+--- a/src/qemu/test_libvirtd_qemu.aug.in
++++ b/src/qemu/test_libvirtd_qemu.aug.in
+@@ -66,3 +66,4 @@ module Test_libvirtd_qemu =
+ { "keepalive_interval" = "5" }
+ { "keepalive_count" = "5" }
+ { "seccomp_sandbox" = "1" }
++{ "migration_address" = "127.0.0.1" }
+--
+1.8.4
+
--- /dev/null
+From 9fea9b854c82af06f17830c5e1fb585fdf78fff8 Mon Sep 17 00:00:00 2001
+Message-Id: <9fea9b854c82af06f17830c5e1fb585fdf78fff8.1381871411.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 2 Oct 2013 11:04:08 +0200
+Subject: [PATCH] qemu_hotplug: Allow QoS update in qemuDomainChangeNet
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1014503
+
+The qemuDomainChangeNet() is called when 'virsh update-device' is
+invoked on a NIC. Currently, we fail to update the QoS even though
+we have routines for that.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 9fa10d3901a14997f724fe50ad8a33d7f0d23abe)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 83e193b..7e884c0 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1677,6 +1677,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
+ bool needFilterChange = false;
+ bool needLinkStateChange = false;
+ bool needReplaceDevDef = false;
++ bool needBandwidthSet = false;
+ int ret = -1;
+
+ if (!devslot || !(olddev = *devslot)) {
+@@ -1940,8 +1941,6 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
+ virDomainNetGetActualDirectMode(olddev) != virDomainNetGetActualDirectMode(olddev) ||
+ !virNetDevVPortProfileEqual(virDomainNetGetActualVirtPortProfile(olddev),
+ virDomainNetGetActualVirtPortProfile(newdev)) ||
+- !virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
+- virDomainNetGetActualBandwidth(newdev)) ||
+ !virNetDevVlanEqual(virDomainNetGetActualVlan(olddev),
+ virDomainNetGetActualVlan(newdev))) {
+ needReconnect = true;
+@@ -1950,6 +1949,10 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
+ if (olddev->linkstate != newdev->linkstate)
+ needLinkStateChange = true;
+
++ if (!virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
++ virDomainNetGetActualBandwidth(newdev)))
++ needBandwidthSet = true;
++
+ /* FINALLY - actually perform the required actions */
+
+ if (needReconnect) {
+@@ -1959,6 +1962,18 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
+ goto cleanup;
+ }
+
++ if (needBandwidthSet) {
++ if (virNetDevBandwidthSet(newdev->ifname,
++ virDomainNetGetActualBandwidth(newdev),
++ false) < 0) {
++ virReportError(VIR_ERR_INTERNAL_ERROR,
++ _("cannot set bandwidth limits on %s"),
++ newdev->ifname);
++ goto cleanup;
++ }
++ needReplaceDevDef = true;
++ }
++
+ if (needBridgeChange) {
+ if (qemuDomainChangeNetBridge(dom->conn, vm, olddev, newdev) < 0)
+ goto cleanup;
+--
+1.8.3.2
+
--- /dev/null
+From a8a37a6d612e710f4c63c21e83529e6c9ebd7806 Mon Sep 17 00:00:00 2001
+Message-Id: <a8a37a6d612e710f4c63c21e83529e6c9ebd7806.1381871412.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 17:18:10 +0200
+Subject: [PATCH] qemu_migration: Avoid crashing if domain dies too quickly
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1018267
+
+I've noticed a SIGSEGV-ing libvirtd on the destination when the qemu
+died too quickly = in Prepare phase. What is happening here is:
+
+1) [Thread 3493] We are in qemuMigrationPrepareAny() and calling
+qemuProcessStart() which subsequently calls qemuProcessWaitForMonitor()
+and qemuConnectMonitor(). So far so good. The qemuMonitorOpen()
+succeeds, however switching monitor to QMP mode fails as qemu died
+meanwhile. That is qemuMonitorSetCapabilities() returns -1.
+
+2013-10-08 15:54:10.629+0000: 3493: debug : qemuMonitorSetCapabilities:1356 : mon=0x14a53da0
+2013-10-08 15:54:10.630+0000: 3493: debug : qemuMonitorJSONCommandWithFd:262 : Send command '{"execute":"qmp_capabilities","id":"libvirt-1"}' for write with FD -1
+2013-10-08 15:54:10.630+0000: 3493: debug : virEventPollUpdateHandle:147 : EVENT_POLL_UPDATE_HANDLE: watch=17 events=13
+...
+2013-10-08 15:54:10.631+0000: 3493: debug : qemuMonitorSend:956 : QEMU_MONITOR_SEND_MSG: mon=0x14a53da0 msg={"execute":"qmp_capabilities","id":"libvirt-1"}
+ fd=-1
+2013-10-08 15:54:10.631+0000: 3262: debug : virEventPollRunOnce:641 : Poll got 1 event(s)
+
+2) [Thread 3262] The event loop is trying to do the talking to monitor.
+However, qemu is dead already, remember?
+
+2013-10-08 15:54:13.436+0000: 3262: error : qemuMonitorIORead:551 : Unable to read from monitor: Connection reset by peer
+2013-10-08 15:54:13.516+0000: 3262: debug : virFileClose:90 : Closed fd 25
+...
+2013-10-08 15:54:13.533+0000: 3493: debug : qemuMonitorSend:968 : Send command resulted in error internal error: early end of file from monitor: possible problem:
+
+3) [Thread 3493] qemuProcessStart() failed. No big deal. Go to the
+'endjob' label and subsequently to the 'cleanup'. Since the domain is
+not persistent and ret is -1, the qemuDomainRemoveInactive() is called.
+This has an (unpleasant) effect of virObjectUnref()-in the @vm object.
+Unpleasant because the event loop which is about to trigger EOF callback
+still holds a pointer to the @vm (not the reference). See the valgrind
+output below.
+
+4) [Thread 3262] So the event loop starts triggering EOF:
+
+2013-10-08 15:54:13.542+0000: 3262: debug : qemuMonitorIO:729 : Triggering EOF callback
+2013-10-08 15:54:13.543+0000: 3262: debug : qemuProcessHandleMonitorEOF:294 : Received EOF on 0x14549110 'migt10'
+
+And the monitor is cleaned up. This results in calling
+qemuProcessHandleMonitorEOF with the @vm pointer passed. The pointer is
+kept in qemuMonitor struct.
+
+==3262== Thread 1:
+==3262== Invalid read of size 4
+==3262== at 0x77ECCAA: pthread_mutex_lock (in /lib64/libpthread-2.15.so)
+==3262== by 0x52FAA06: virMutexLock (virthreadpthread.c:85)
+==3262== by 0x52E3891: virObjectLock (virobject.c:320)
+==3262== by 0x11626743: qemuProcessHandleMonitorEOF (qemu_process.c:296)
+==3262== by 0x11642593: qemuMonitorIO (qemu_monitor.c:730)
+==3262== by 0x52BD526: virEventPollDispatchHandles (vireventpoll.c:501)
+==3262== by 0x52BDD49: virEventPollRunOnce (vireventpoll.c:648)
+==3262== by 0x52BBC68: virEventRunDefaultImpl (virevent.c:274)
+==3262== by 0x542D3D9: virNetServerRun (virnetserver.c:1112)
+==3262== by 0x11F368: main (libvirtd.c:1513)
+==3262== Address 0x14549128 is 24 bytes inside a block of size 136 free'd
+==3262== at 0x4C2AF5C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==3262== by 0x529B1FF: virFree (viralloc.c:580)
+==3262== by 0x52E3703: virObjectUnref (virobject.c:270)
+==3262== by 0x531557E: virDomainObjListRemove (domain_conf.c:2355)
+==3262== by 0x1160E899: qemuDomainRemoveInactive (qemu_domain.c:2061)
+==3262== by 0x1163A0C6: qemuMigrationPrepareAny (qemu_migration.c:2450)
+==3262== by 0x1163A923: qemuMigrationPrepareDirect (qemu_migration.c:2626)
+==3262== by 0x11682D71: qemuDomainMigratePrepare3Params (qemu_driver.c:10309)
+==3262== by 0x53B0976: virDomainMigratePrepare3Params (libvirt.c:7266)
+==3262== by 0x1502D3: remoteDispatchDomainMigratePrepare3Params (remote.c:4797)
+==3262== by 0x12DECA: remoteDispatchDomainMigratePrepare3ParamsHelper (remote_dispatch.h:5741)
+==3262== by 0x54322EB: virNetServerProgramDispatchCall (virnetserverprogram.c:435)
+
+The mon->vm is set in qemuMonitorOpenInternal() which is the correct
+place to increase @vm ref counter. The correct place to decrease the ref
+counter is then qemuMonitorDispose().
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit c7ac2519b7fe8b4f9c0ecc05cf7e46dea64b5e15)
+
+Conflicts:
+ src/qemu/qemu_capabilities.c: Context
+ src/qemu/qemu_monitor.c: Context
+ Both due to 809ee6ba not being backported yet.
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 14 ++++++++++----
+ src/qemu/qemu_monitor.c | 4 +++-
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 9b1d9f5..b95a984 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2482,7 +2482,8 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps,
+ char *monpath = NULL;
+ char *pidfile = NULL;
+ pid_t pid = 0;
+- virDomainObj vm;
++ virDomainObjPtr vm = NULL;
++ virDomainXMLOptionPtr xmlopt = NULL;
+
+ /* the ".sock" sufix is important to avoid a possible clash with a qemu
+ * domain called "capabilities"
+@@ -2545,10 +2546,13 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps,
+ goto cleanup;
+ }
+
+- memset(&vm, 0, sizeof(vm));
+- vm.pid = pid;
++ if (!(xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL)) ||
++ !(vm = virDomainObjNew(xmlopt)))
++ goto cleanup;
++
++ vm->pid = pid;
+
+- if (!(mon = qemuMonitorOpen(&vm, &config, true, &callbacks))) {
++ if (!(mon = qemuMonitorOpen(vm, &config, true, &callbacks))) {
+ ret = 0;
+ goto cleanup;
+ }
+@@ -2629,6 +2633,8 @@ cleanup:
+ VIR_FREE(monarg);
+ VIR_FREE(monpath);
+ VIR_FREE(package);
++ virObjectUnref(vm);
++ virObjectUnref(xmlopt);
+
+ if (pid != 0) {
+ char ebuf[1024];
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index 5b2fb04..e22a2b2 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -249,6 +249,8 @@ static void qemuMonitorDispose(void *obj)
+ VIR_DEBUG("mon=%p", mon);
+ if (mon->cb && mon->cb->destroy)
+ (mon->cb->destroy)(mon, mon->vm);
++ virObjectUnref(mon->vm);
++
+ virCondDestroy(&mon->notify);
+ VIR_FREE(mon->buffer);
+ virJSONValueFree(mon->options);
+@@ -722,7 +724,7 @@ qemuMonitorOpenInternal(virDomainObjPtr vm,
+ }
+ mon->fd = fd;
+ mon->hasSendFD = hasSendFD;
+- mon->vm = vm;
++ mon->vm = virObjectRef(vm);
+ mon->json = json;
+ if (json)
+ mon->waitGreeting = true;
+--
+1.8.3.2
+
--- /dev/null
+From aaffe43897ee06be10aca64861022dfeea735ed3 Mon Sep 17 00:00:00 2001
+Message-Id: <aaffe43897ee06be10aca64861022dfeea735ed3.1382534060.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 10 Oct 2013 13:56:29 +0200
+Subject: [PATCH] qemu_process: Make qemuProcessReadLog() more versatile and
+ reusable
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001738
+
+Teach the function to skip character device definitions printed by qemu
+at startup in addition to libvirt log messages and make it usable from
+outside of qemu_process.c. Also add documentation about the func.
+
+(cherry picked from commit 310651a5e346b23db9015061452b1887335aed67)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 24 +++++++++++++++++++-----
+ src/qemu/qemu_process.h | 2 ++
+ 2 files changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 1bd0d04..063cd78 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -1428,8 +1428,20 @@ error:
+ return ret;
+ }
+
+-static int
+-qemuProcessReadLog(int fd, char *buf, int buflen, int off)
++
++/**
++ * qemuProcessReadLog: Read log file of a qemu VM
++ * @fd: File descriptor of the log file
++ * @buf: buffer to store the read messages
++ * @buflen: allocated space available in @buf
++ * @off: Offset to start reading from
++ * @skipchar: Skip messages about created character devices
++ *
++ * Reads log of a qemu VM. Skips messages not produced by qemu or irrelevant
++ * messages. Returns length of the message stored in @buf, or -1 on error.
++ */
++int
++qemuProcessReadLog(int fd, char *buf, int buflen, int off, bool skipchar)
+ {
+ char *filter_next = buf;
+ ssize_t bytes;
+@@ -1450,7 +1462,9 @@ qemuProcessReadLog(int fd, char *buf, int buflen, int off)
+ /* Filter out debug messages from intermediate libvirt process */
+ while ((eol = strchr(filter_next, '\n'))) {
+ *eol = '\0';
+- if (virLogProbablyLogMessage(filter_next)) {
++ if (virLogProbablyLogMessage(filter_next) ||
++ (skipchar &&
++ STRPREFIX(filter_next, "char device redirected to"))) {
+ memmove(filter_next, eol + 1, off - (eol - buf));
+ off -= eol + 1 - filter_next;
+ } else {
+@@ -1493,7 +1507,7 @@ qemuProcessReadLogOutput(virDomainObjPtr vm,
+
+ isdead = kill(vm->pid, 0) == -1 && errno == ESRCH;
+
+- got = qemuProcessReadLog(fd, buf, buflen, got);
++ got = qemuProcessReadLog(fd, buf, buflen, got, false);
+ if (got < 0) {
+ virReportSystemError(errno,
+ _("Failure while reading %s log output"),
+@@ -1804,7 +1818,7 @@ cleanup:
+ }
+
+ len = strlen(buf);
+- qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0);
++ qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("process exited while connecting to monitor: %s"),
+ buf);
+diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
+index 8c81e40..2f6c4f5 100644
+--- a/src/qemu/qemu_process.h
++++ b/src/qemu/qemu_process.h
+@@ -101,4 +101,6 @@ bool qemuProcessAutoDestroyActive(virQEMUDriverPtr driver,
+ virBitmapPtr qemuPrepareCpumap(virQEMUDriverPtr driver,
+ virBitmapPtr nodemask);
+
++int qemuProcessReadLog(int fd, char *buf, int buflen, int off, bool skipchar);
++
+ #endif /* __QEMU_PROCESS_H__ */
+--
+1.8.4
+
--- /dev/null
+From 15d641feff137696f82aade8aaa56dea976cefeb Mon Sep 17 00:00:00 2001
+Message-Id: <15d641feff137696f82aade8aaa56dea976cefeb.1377873639.git.jdenemar@redhat.com>
+From: Alex Jia <ajia@redhat.com>
+Date: Wed, 14 Aug 2013 13:55:26 +0200
+Subject: [PATCH] remote: Fix a segfault in remoteDomainCreateWithFlags
+
+Valgrind defects memory error:
+
+==16759== 1 errors in context 1 of 8:
+==16759== Invalid free() / delete / delete[] / realloc()
+==16759== at 0x4A074C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==16759== by 0x83CD329: xdr_string (in /usr/lib64/libc-2.17.so)
+==16759== by 0x4D93E4D: xdr_remote_nonnull_string (remote_protocol.c:31)
+==16759== by 0x4D94350: xdr_remote_nonnull_domain (remote_protocol.c:58)
+==16759== by 0x4D976C8: xdr_remote_domain_create_with_flags_ret (remote_protocol.c:1762)
+==16759== by 0x83CC734: xdr_free (in /usr/lib64/libc-2.17.so)
+==16759== by 0x4D7F1E0: remoteDomainCreateWithFlags (remote_driver.c:2441)
+==16759== by 0x4D4BF17: virDomainCreateWithFlags (libvirt.c:9499)
+==16759== by 0x13127A: cmdStart (virsh-domain.c:3376)
+==16759== by 0x12BF83: vshCommandRun (virsh.c:1751)
+==16759== by 0x126FFB: main (virsh.c:3205)
+==16759== Address 0xe1394a0 is not stack'd, malloc'd or (recently) free'd
+
+==16759== 1 errors in context 2 of 8:
+==16759== Conditional jump or move depends on uninitialised value(s)
+==16759== at 0x4A07477: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==16759== by 0x83CD329: xdr_string (in /usr/lib64/libc-2.17.so)
+==16759== by 0x4D93E4D: xdr_remote_nonnull_string (remote_protocol.c:31)
+==16759== by 0x4D94350: xdr_remote_nonnull_domain (remote_protocol.c:58)
+==16759== by 0x4D976C8: xdr_remote_domain_create_with_flags_ret (remote_protocol.c:1762)
+==16759== by 0x83CC734: xdr_free (in /usr/lib64/libc-2.17.so)
+==16759== by 0x4D7F1E0: remoteDomainCreateWithFlags (remote_driver.c:2441)
+==16759== by 0x4D4BF17: virDomainCreateWithFlags (libvirt.c:9499)
+==16759== by 0x13127A: cmdStart (virsh-domain.c:3376)
+==16759== by 0x12BF83: vshCommandRun (virsh.c:1751)
+==16759== by 0x126FFB: main (virsh.c:3205)
+==16759== Uninitialised value was created by a stack allocation
+==16759== at 0x4D7F120: remoteDomainCreateWithFlags (remote_driver.c:2423)
+
+How to reproduce?
+
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=994855
+
+Signed-off-by: Alex Jia <ajia@redhat.com>
+(cherry picked from commit be7a89e8cabbc0e222b9e39c6266ece576295fe3)
+---
+ src/remote/remote_driver.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index f828eef..71d0034 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -2431,6 +2431,7 @@ remoteDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
+ make_nonnull_domain(&args.dom, dom);
+ args.flags = flags;
+
++ memset(&ret, 0, sizeof(ret));
+ if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS,
+ (xdrproc_t)xdr_remote_domain_create_with_flags_args, (char *)&args,
+ (xdrproc_t)xdr_remote_domain_create_with_flags_ret, (char *)&ret) == -1) {
+--
+1.8.3.2
+
--- /dev/null
+From 4d309f7dbb762fe062783c1f0d6ad28d987075bd Mon Sep 17 00:00:00 2001
+Message-Id: <4d309f7dbb762fe062783c1f0d6ad28d987075bd.1382534061.git.jdenemar@redhat.com>
+From: Zhou Yimin <zhouyimin@huawei.com>
+Date: Fri, 18 Oct 2013 15:13:33 +0200
+Subject: [PATCH] remote: fix regression in event deregistration
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1020376
+
+Introduced by 7b87a3
+When I quit the process which only register VIR_DOMAIN_EVENT_ID_REBOOT,
+I got error like:
+"libvirt: XML-RPC error : internal error: domain event 0 not registered".
+Then I add the following code, it fixed.
+
+Signed-off-by: Zhou Yimin <zhouyimin@huawei.com>
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 9712c2510ec87a87578576a407768380e250a6a4)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/remote/remote_driver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
+index 62e77a5..dcd433b 100644
+--- a/src/remote/remote_driver.c
++++ b/src/remote/remote_driver.c
+@@ -5137,7 +5137,7 @@ static int remoteConnectDomainEventDeregisterAny(virConnectPtr conn,
+ /* If that was the last callback for this eventID, we need to disable
+ * events on the server */
+ if (count == 0) {
+- args.eventID = callbackID;
++ args.eventID = eventID;
+
+ if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER_ANY,
+ (xdrproc_t) xdr_remote_connect_domain_event_deregister_any_args, (char *) &args,
+--
+1.8.4
+
--- /dev/null
+From 91616a6d6ef5c22502d82bff045d4d44f4a230af Mon Sep 17 00:00:00 2001
+Message-Id: <91616a6d6ef5c22502d82bff045d4d44f4a230af.1379193141.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Thu, 12 Sep 2013 06:32:05 -0600
+Subject: [PATCH] rename "struct interface_driver" to virNetcfDriverState
+
+Prerequisite for the patch to fix:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=983026
+
+This better fits the modern naming scheme in libvirt, and anticipates
+an upcoming change where a single instance of this state will be
+maintained by a separate state driver, and every instance of the netcf
+driver will share the same state.
+
+(cherry picked from commit 4c5fa430972246b82d60c875654fc57e48adfcce)
+---
+ src/interface/interface_backend_netcf.c | 52 +++++++++++++++++----------------
+ 1 file changed, 27 insertions(+), 25 deletions(-)
+
+diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interface_backend_netcf.c
+index b92b0ce..f47669e 100644
+--- a/src/interface/interface_backend_netcf.c
++++ b/src/interface/interface_backend_netcf.c
+@@ -2,7 +2,7 @@
+ * interface_driver.c: backend driver methods to handle physical
+ * interface configuration using the netcf library.
+ *
+- * Copyright (C) 2006-2012 Red Hat, Inc.
++ * Copyright (C) 2006-2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -36,20 +36,22 @@
+
+ #define VIR_FROM_THIS VIR_FROM_INTERFACE
+
++#define INTERFACE_DRIVER_NAME "netcf"
++
+ /* Main driver state */
+-struct interface_driver
++typedef struct
+ {
+ virMutex lock;
+ struct netcf *netcf;
+-};
++} virNetcfDriverState, *virNetcfDriverStatePtr;
+
+
+-static void interfaceDriverLock(struct interface_driver *driver)
++static void interfaceDriverLock(virNetcfDriverStatePtr driver)
+ {
+ virMutexLock(&driver->lock);
+ }
+
+-static void interfaceDriverUnlock(struct interface_driver *driver)
++static void interfaceDriverUnlock(virNetcfDriverStatePtr driver)
+ {
+ virMutexUnlock(&driver->lock);
+ }
+@@ -150,7 +152,7 @@ static virDrvOpenStatus netcfInterfaceOpen(virConnectPtr conn,
+ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+ unsigned int flags)
+ {
+- struct interface_driver *driverState;
++ virNetcfDriverStatePtr driverState;
+
+ virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+@@ -191,7 +193,7 @@ static int netcfInterfaceClose(virConnectPtr conn)
+
+ if (conn->interfacePrivateData != NULL)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+
+ /* close netcf instance */
+ ncf_close(driver->netcf);
+@@ -208,7 +210,7 @@ static int netcfConnectNumOfInterfacesImpl(virConnectPtr conn,
+ int status,
+ virInterfaceObjListFilter filter)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int count;
+ int want = 0;
+ int ret = -1;
+@@ -302,7 +304,7 @@ static int netcfConnectListInterfacesImpl(virConnectPtr conn,
+ char **const names, int nnames,
+ virInterfaceObjListFilter filter)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int count = 0;
+ int want = 0;
+ int ret = -1;
+@@ -401,7 +403,7 @@ cleanup:
+ static int netcfConnectNumOfInterfaces(virConnectPtr conn)
+ {
+ int count;
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+
+ if (virConnectNumOfInterfacesEnsureACL(conn) < 0)
+ return -1;
+@@ -416,7 +418,7 @@ static int netcfConnectNumOfInterfaces(virConnectPtr conn)
+
+ static int netcfConnectListInterfaces(virConnectPtr conn, char **const names, int nnames)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int count;
+
+ if (virConnectListInterfacesEnsureACL(conn) < 0)
+@@ -435,7 +437,7 @@ static int netcfConnectListInterfaces(virConnectPtr conn, char **const names, in
+ static int netcfConnectNumOfDefinedInterfaces(virConnectPtr conn)
+ {
+ int count;
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+
+ if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0)
+ return -1;
+@@ -450,7 +452,7 @@ static int netcfConnectNumOfDefinedInterfaces(virConnectPtr conn)
+
+ static int netcfConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int nnames)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int count;
+
+ if (virConnectListDefinedInterfacesEnsureACL(conn) < 0)
+@@ -472,7 +474,7 @@ netcfConnectListAllInterfaces(virConnectPtr conn,
+ virInterfacePtr **ifaces,
+ unsigned int flags)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int count;
+ size_t i;
+ struct netcf_if *iface = NULL;
+@@ -627,7 +629,7 @@ cleanup:
+ static virInterfacePtr netcfInterfaceLookupByName(virConnectPtr conn,
+ const char *name)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ struct netcf_if *iface;
+ virInterfacePtr ret = NULL;
+ virInterfaceDefPtr def = NULL;
+@@ -667,7 +669,7 @@ cleanup:
+ static virInterfacePtr netcfInterfaceLookupByMACString(virConnectPtr conn,
+ const char *macstr)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ struct netcf_if *iface;
+ int niface;
+ virInterfacePtr ret = NULL;
+@@ -716,7 +718,7 @@ cleanup:
+ static char *netcfInterfaceGetXMLDesc(virInterfacePtr ifinfo,
+ unsigned int flags)
+ {
+- struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = ifinfo->conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ char *xmlstr = NULL;
+ virInterfaceDefPtr ifacedef = NULL;
+@@ -774,7 +776,7 @@ static virInterfacePtr netcfInterfaceDefineXML(virConnectPtr conn,
+ const char *xml,
+ unsigned int flags)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ char *xmlstr = NULL;
+ virInterfaceDefPtr ifacedef = NULL;
+@@ -821,7 +823,7 @@ cleanup:
+ }
+
+ static int netcfInterfaceUndefine(virInterfacePtr ifinfo) {
+- struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = ifinfo->conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ virInterfaceDefPtr def = NULL;
+ int ret = -1;
+@@ -862,7 +864,7 @@ cleanup:
+ static int netcfInterfaceCreate(virInterfacePtr ifinfo,
+ unsigned int flags)
+ {
+- struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = ifinfo->conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ virInterfaceDefPtr def = NULL;
+ int ret = -1;
+@@ -905,7 +907,7 @@ cleanup:
+ static int netcfInterfaceDestroy(virInterfacePtr ifinfo,
+ unsigned int flags)
+ {
+- struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = ifinfo->conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ virInterfaceDefPtr def = NULL;
+ int ret = -1;
+@@ -947,7 +949,7 @@ cleanup:
+
+ static int netcfInterfaceIsActive(virInterfacePtr ifinfo)
+ {
+- struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = ifinfo->conn->interfacePrivateData;
+ struct netcf_if *iface = NULL;
+ unsigned int flags = 0;
+ virInterfaceDefPtr def = NULL;
+@@ -990,7 +992,7 @@ cleanup:
+ #ifdef HAVE_NETCF_TRANSACTIONS
+ static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int ret;
+
+ virCheckFlags(0, -1); /* currently flags must be 0 */
+@@ -1016,7 +1018,7 @@ static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
+
+ static int netcfInterfaceChangeCommit(virConnectPtr conn, unsigned int flags)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int ret;
+
+ virCheckFlags(0, -1); /* currently flags must be 0 */
+@@ -1042,7 +1044,7 @@ static int netcfInterfaceChangeCommit(virConnectPtr conn, unsigned int flags)
+
+ static int netcfInterfaceChangeRollback(virConnectPtr conn, unsigned int flags)
+ {
+- struct interface_driver *driver = conn->interfacePrivateData;
++ virNetcfDriverStatePtr driver = conn->interfacePrivateData;
+ int ret;
+
+ virCheckFlags(0, -1); /* currently flags must be 0 */
+--
+1.8.3.2
+
--- /dev/null
+From 69dd3f5be00b5232e45bbfb92ba50c97b084767a Mon Sep 17 00:00:00 2001
+Message-Id: <69dd3f5be00b5232e45bbfb92ba50c97b084767a.1382534061.git.jdenemar@redhat.com>
+From: Osier Yang <jyang@redhat.com>
+Date: Wed, 16 Oct 2013 23:12:57 +0800
+Subject: [PATCH] rpc: Correct the wrong payload size checking
+
+https://bugzilla.redhat.com/show_bug.cgi?id=950416
+
+<...>
+/* Size of message length field. Not counted in VIR_NET_MESSAGE_MAX
+ * and VIR_NET_MESSAGE_INITIAL.
+ */
+const VIR_NET_MESSAGE_LEN_MAX = 4;
+</...>
+
+However, msg->bufferLength includes the length word. The wrong checking
+was introduced by commit e914dcfd.
+
+* src/rpc/virnetmessage.c:
+ - Correct the checking in virNetMessageEncodePayloadRaw
+ - Use a new variable to track the new payload length in
+ virNetMessageEncodePayloadRaw
+(cherry picked from commit 0959785d3b4a4da3c24352942ca4d2152f4e0191)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/rpc/virnetmessage.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c
+index 8f4e4bc..d60366b 100644
+--- a/src/rpc/virnetmessage.c
++++ b/src/rpc/virnetmessage.c
+@@ -346,15 +346,16 @@ int virNetMessageEncodePayload(virNetMessagePtr msg,
+
+ /* Try to encode the payload. If the buffer is too small increase it. */
+ while (!(*filter)(&xdr, data)) {
+- if ((msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4 > VIR_NET_MESSAGE_MAX) {
++ unsigned int newlen = (msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4;
++
++ if (newlen > VIR_NET_MESSAGE_MAX) {
+ virReportError(VIR_ERR_RPC, "%s", _("Unable to encode message payload"));
+ goto error;
+ }
+
+ xdr_destroy(&xdr);
+
+- msg->bufferLength = (msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4 +
+- VIR_NET_MESSAGE_LEN_MAX;
++ msg->bufferLength = newlen + VIR_NET_MESSAGE_LEN_MAX;
+
+ if (VIR_REALLOC_N(msg->buffer, msg->bufferLength) < 0)
+ goto error;
+@@ -426,10 +427,15 @@ int virNetMessageEncodePayloadRaw(virNetMessagePtr msg,
+
+ /* If the message buffer is too small for the payload increase it accordingly. */
+ if ((msg->bufferLength - msg->bufferOffset) < len) {
+- if ((msg->bufferOffset + len) > VIR_NET_MESSAGE_MAX) {
++ if ((msg->bufferOffset + len) >
++ (VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_LEN_MAX)) {
+ virReportError(VIR_ERR_RPC,
+- _("Stream data too long to send (%zu bytes needed, %zu bytes available)"),
+- len, (VIR_NET_MESSAGE_MAX - msg->bufferOffset));
++ _("Stream data too long to send "
++ "(%zu bytes needed, %zu bytes available)"),
++ len,
++ VIR_NET_MESSAGE_MAX +
++ VIR_NET_MESSAGE_LEN_MAX -
++ msg->bufferOffset);
+ return -1;
+ }
+
+--
+1.8.4
+
--- /dev/null
+From 3d00a43e50674c1d2c4c512101f99d2a3526f22c Mon Sep 17 00:00:00 2001
+Message-Id: <3d00a43e50674c1d2c4c512101f99d2a3526f22c.1380703761.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 27 Sep 2013 13:06:06 +0200
+Subject: [PATCH] rpc: Increase bound limit for virDomainGetJobStats
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1012818
+
+Commit 6d7d0b1869ed293e3208d11f375cecea0129dfc5 (in 1.1.2) added bounds
+checking to virDomainGetJobStats. But even at that time the API was able
+to return 20 parameters while the limit was set to 16.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit f25a08747de3589605f7f288cec61e0c182fbb7f)
+---
+ src/remote/remote_protocol.x | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
+index 85ad9ba..a8450b1 100644
+--- a/src/remote/remote_protocol.x
++++ b/src/remote/remote_protocol.x
+@@ -230,7 +230,7 @@ const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
+ const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64;
+
+ /* Upper limit on number of job stats */
+-const REMOTE_DOMAIN_JOB_STATS_MAX = 16;
++const REMOTE_DOMAIN_JOB_STATS_MAX = 64;
+
+ /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
+ typedef opaque remote_uuid[VIR_UUID_BUFLEN];
+--
+1.8.3.2
+
--- /dev/null
+From ae96147f6368145fcea0c34b5897dd4762e7e843 Mon Sep 17 00:00:00 2001
+Message-Id: <ae96147f6368145fcea0c34b5897dd4762e7e843.1383922565.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 8 Nov 2013 12:33:15 +0100
+Subject: [PATCH] schema: Rename option 'hypervtristate' to 'featurestate'
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1008989
+
+Change the RelaxNG schema option name so that it can be reused for
+non-hyperv feature flags.
+
+(cherry picked from commit c4caa012c2b3e42ebe701ecbbe041fcee12e9d40)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ docs/schemas/domaincommon.rng | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index c7eaf00..9563893 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -4068,17 +4068,17 @@
+ <interleave>
+ <optional>
+ <element name="relaxed">
+- <ref name="hypervtristate"/>
++ <ref name="featurestate"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="vapic">
+- <ref name="hypervtristate"/>
++ <ref name="featurestate"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="spinlocks">
+- <ref name="hypervtristate"/>
++ <ref name="featurestate"/>
+ <optional>
+ <attribute name="retries">
+ <data type="unsignedInt"/>
+@@ -4090,7 +4090,7 @@
+ </element>
+ </define>
+
+- <define name="hypervtristate">
++ <define name="featurestate">
+ <attribute name="state">
+ <choice>
+ <value>on</value>
+--
+1.8.4.2
+
--- /dev/null
+From e6e8ccf983c15591a86805a8f9d63d7529a87639 Mon Sep 17 00:00:00 2001
+Message-Id: <e6e8ccf983c15591a86805a8f9d63d7529a87639.1379193140.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Thu, 12 Sep 2013 11:37:32 -0600
+Subject: [PATCH] security: provide supplemental groups even when parsing label
+ (CVE-2013-4291)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006513
+
+Commit 29fe5d7 (released in 1.1.1) introduced a latent problem
+for any caller of virSecurityManagerSetProcessLabel and where
+the domain already had a uid:gid label to be parsed. Such a
+setup would collect the list of supplementary groups during
+virSecurityManagerPreFork, but then ignores that information,
+and thus fails to call setgroups() to adjust the supplementary
+groups of the process.
+
+Upstream does not use virSecurityManagerSetProcessLabel for
+qemu (it uses virSecurityManagerSetChildProcessLabel instead),
+so this problem remained latent until backporting the initial
+commit into v0.10.2-maint (commit c061ff5, released in 0.10.2.7),
+where virSecurityManagerSetChildProcessLabel has not been
+backported. As a result of using a different code path in the
+backport, attempts to start a qemu domain that runs as qemu:qemu
+will end up with supplementary groups unchanged from the libvirtd
+parent process, rather than the desired supplementary groups of
+the qemu user. This can lead to failure to start a domain
+(typical Fedora setup assigns user 107 'qemu' to both group 107
+'qemu' and group 36 'kvm', so a disk image that is only readable
+under kvm group rights is locked out). Worse, it is a security
+hole (the qemu process will inherit supplemental group rights
+from the parent libvirtd process, which means it has access
+rights to files owned by group 0 even when such files should
+not normally be visible to user qemu).
+
+LXC does not use the DAC security driver, so it is not vulnerable
+at this time. Still, it is better to plug the latent hole on
+the master branch first, before cherry-picking it to the only
+vulnerable branch v0.10.2-maint.
+
+* src/security/security_dac.c (virSecurityDACGetIds): Always populate
+groups and ngroups, rather than only when no label is parsed.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 745aa55fbf3e076c4288d5ec3239f5a5d43508a6)
+---
+ src/security/security_dac.c | 16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+diff --git a/src/security/security_dac.c b/src/security/security_dac.c
+index 8cbb083..6876bd5 100644
+--- a/src/security/security_dac.c
++++ b/src/security/security_dac.c
+@@ -115,13 +115,13 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
+ return -1;
+ }
+
+- if ((ret = virSecurityDACParseIds(def, uidPtr, gidPtr)) <= 0) {
+- if (groups)
+- *groups = NULL;
+- if (ngroups)
+- *ngroups = 0;
++ if (groups)
++ *groups = priv ? priv->groups : NULL;
++ if (ngroups)
++ *ngroups = priv ? priv->ngroups : 0;
++
++ if ((ret = virSecurityDACParseIds(def, uidPtr, gidPtr)) <= 0)
+ return ret;
+- }
+
+ if (!priv) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -134,10 +134,6 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
+ *uidPtr = priv->user;
+ if (gidPtr)
+ *gidPtr = priv->group;
+- if (groups)
+- *groups = priv->groups;
+- if (ngroups)
+- *ngroups = priv->ngroups;
+
+ return 0;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 83edaa14dafc6fc409ad4c9e2b89351c3f519602 Mon Sep 17 00:00:00 2001
+Message-Id: <83edaa14dafc6fc409ad4c9e2b89351c3f519602.1378475168.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Tue, 20 Aug 2013 11:08:54 -0600
+Subject: [PATCH] selinux: distinguish failure to label from request to avoid
+ label
+
+https://bugzilla.redhat.com/show_bug.cgi?id=924153
+
+Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
+an attribute relabel='no' in order to try and minimize the
+impact of shutdown delays when an NFS server disappears. The idea
+was that if a disk is on NFS and can't be labeled in the first
+place, there is no need to attempt the (no-op) relabel on domain
+shutdown. Unfortunately, the way this was implemented was by
+modifying the domain XML so that the optimization would survive
+libvirtd restart, but in a way that is indistinguishable from an
+explicit user setting. Furthermore, once the setting is turned
+on, libvirt avoids attempts at labeling, even for operations like
+snapshot or blockcopy where the chain is being extended or pivoted
+onto non-NFS, where SELinux labeling is once again possible. As
+a result, it was impossible to do a blockcopy to pivot from an
+NFS image file onto a local file.
+
+The solution is to separate the semantics of a chain that must
+not be labeled (which the user can set even on persistent domains)
+vs. the optimization of not attempting a relabel on cleanup (a
+live-only annotation), and using only the user's explicit notation
+rather than the optimization as the decision on whether to skip
+a label attempt in the first place. When upgrading an older
+libvirtd to a newer, an NFS volume will still attempt the relabel;
+but as the avoidance of a relabel was only an optimization, this
+shouldn't cause any problems.
+
+In the ideal future, libvirt will eventually have XML describing
+EVERY file in the backing chain, with each file having a separate
+<seclabel> element. At that point, libvirt will be able to track
+more closely which files need a relabel attempt at shutdown. But
+until we reach that point, the single <seclabel> for the entire
+<disk> chain is treated as a hint - when a chain has only one
+file, then we know it is accurate; but if the chain has more than
+one file, we have to attempt relabel in spite of the attribute,
+in case part of the chain is local and SELinux mattered for that
+portion of the chain.
+
+* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
+member.
+* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
+Parse it, for live images only.
+(virSecurityDeviceLabelDefFormat): Output it.
+(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
+(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
+(virDomainDiskDefFormat): Pass flags on through.
+* src/security/security_selinux.c
+(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
+when possible.
+(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
+norelabel, if labeling fails.
+(virSecuritySELinuxSetFileconHelper): Fix indentation.
+* docs/formatdomain.html.in (seclabel): Document new xml.
+* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
+* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
+* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
+* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
+New test files.
+* tests/qemuxml2argvtest.c (mymain): Run the new tests.
+* tests/qemuxml2xmltest.c (mymain): Likewise.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 0f082e699eda0ad14965c0bc75789c4bfac2bda7)
+---
+ docs/formatdomain.html.in | 6 ++-
+ docs/schemas/domaincommon.rng | 27 +++++++------
+ src/conf/domain_conf.c | 47 ++++++++++++++++------
+ src/conf/domain_conf.h | 3 +-
+ src/security/security_selinux.c | 18 ++++++---
+ .../qemuxml2argv-seclabel-dynamic-labelskip.args | 5 +++
+ .../qemuxml2argv-seclabel-dynamic-labelskip.xml | 32 +++++++++++++++
+ .../qemuxml2argv-seclabel-static-labelskip.args | 5 +++
+ .../qemuxml2argv-seclabel-static-labelskip.xml | 33 +++++++++++++++
+ tests/qemuxml2argvtest.c | 2 +
+ .../qemuxml2xmlout-seclabel-dynamic-labelskip.xml | 31 ++++++++++++++
+ tests/qemuxml2xmltest.c | 8 ++--
+ 12 files changed, 182 insertions(+), 35 deletions(-)
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args
+ create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml
+ create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml
+
+diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
+index 3fd83c9..4308dbe 100644
+--- a/docs/formatdomain.html.in
++++ b/docs/formatdomain.html.in
+@@ -5129,7 +5129,11 @@ qemu-kvm -net nic,model=? /dev/null
+ a <code>seclabel</code> element is attached to a specific path
+ rather than the top-level domain assignment, only the
+ attribute <code>relabel</code> or the
+- sub-element <code>label</code> are supported.
++ sub-element <code>label</code> are supported. Additionally,
++ <span class="since">since 1.1.2</span>, an output-only
++ element <code>labelskip</code> will be present for active
++ domains on disks where labeling was skipped due to the image
++ being on a file system that lacks security labeling.
+ </p>
+
+ <h2><a name="examples">Example configs</a></h2>
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index ac807e6..dfcd61c 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -152,34 +152,35 @@
+ <define name="devSeclabel">
+ <element name="seclabel">
+ <!-- A per-device seclabel override is more limited, either
+- relabel=no or a <label> must be present. -->
++ relabel=no or a <label> must be present on input;
++ output also can include labelskip=yes. -->
++ <optional>
++ <attribute name='model'>
++ <text/>
++ </attribute>
++ </optional>
+ <choice>
+ <group>
+- <optional>
+- <attribute name='model'>
+- <text/>
+- </attribute>
+- </optional>
+ <attribute name='relabel'>
+ <value>no</value>
+ </attribute>
+ </group>
+ <group>
+- <optional>
+- <attribute name='model'>
+- <text/>
+- </attribute>
+- </optional>
++ <attribute name='labelskip'>
++ <value>yes</value>
++ </attribute>
++ </group>
++ <group>
+ <optional>
+ <attribute name='relabel'>
+ <value>yes</value>
+ </attribute>
+ </optional>
+- <zeroOrMore>
++ <oneOrMore>
+ <element name='label'>
+ <text/>
+ </element>
+- </zeroOrMore>
++ </oneOrMore>
+ </group>
+ </choice>
+ </element>
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 53daf73..d6b4ea7 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -4484,7 +4484,8 @@ static int
+ virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
+ size_t *nseclabels_rtn,
+ virSecurityLabelDefPtr *vmSeclabels,
+- int nvmSeclabels, xmlXPathContextPtr ctxt)
++ int nvmSeclabels, xmlXPathContextPtr ctxt,
++ unsigned int flags)
+ {
+ virSecurityDeviceLabelDefPtr *seclabels;
+ size_t nseclabels = 0;
+@@ -4492,7 +4493,7 @@ virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
+ size_t i, j;
+ xmlNodePtr *list = NULL;
+ virSecurityLabelDefPtr vmDef = NULL;
+- char *model, *relabel, *label;
++ char *model, *relabel, *label, *labelskip;
+
+ if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) < 0)
+ goto error;
+@@ -4547,6 +4548,13 @@ virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDefPtr **seclabels_rtn,
+ seclabels[i]->norelabel = false;
+ }
+
++ /* labelskip is only parsed on live images */
++ labelskip = virXMLPropString(list[i], "labelskip");
++ seclabels[i]->labelskip = false;
++ if (labelskip && !(flags & VIR_DOMAIN_XML_INACTIVE))
++ seclabels[i]->labelskip = STREQ(labelskip, "yes");
++ VIR_FREE(labelskip);
++
+ ctxt->node = list[i];
+ label = virXPathStringLimit("string(./label)",
+ VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
+@@ -5208,7 +5216,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
+ &def->nseclabels,
+ vmSeclabels,
+ nvmSeclabels,
+- ctxt) < 0)
++ ctxt,
++ flags) < 0)
+ goto error;
+ ctxt->node = saved_node;
+ }
+@@ -6884,7 +6893,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
+ &chr_def->nseclabels,
+ vmSeclabels,
+ nvmSeclabels,
+- ctxt) < 0) {
++ ctxt,
++ flags) < 0) {
+ ctxt->node = saved_node;
+ goto error;
+ }
+@@ -14028,14 +14038,23 @@ virSecurityLabelDefFormat(virBufferPtr buf, virSecurityLabelDefPtr def)
+
+ static void
+ virSecurityDeviceLabelDefFormat(virBufferPtr buf,
+- virSecurityDeviceLabelDefPtr def)
++ virSecurityDeviceLabelDefPtr def,
++ unsigned int flags)
+ {
++ /* For offline output, skip elements that allow labels but have no
++ * label specified (possible if labelskip was ignored on input). */
++ if ((flags & VIR_DOMAIN_XML_INACTIVE) && !def->label && !def->norelabel)
++ return;
++
+ virBufferAddLit(buf, "<seclabel");
+
+ if (def->model)
+ virBufferAsprintf(buf, " model='%s'", def->model);
+
+- virBufferAsprintf(buf, " relabel='%s'", def->norelabel ? "no" : "yes");
++ if (def->labelskip)
++ virBufferAddLit(buf, " labelskip='yes'");
++ else
++ virBufferAsprintf(buf, " relabel='%s'", def->norelabel ? "no" : "yes");
+
+ if (def->label) {
+ virBufferAddLit(buf, ">\n");
+@@ -14110,7 +14129,8 @@ virDomainDiskBlockIoDefFormat(virBufferPtr buf,
+
+ static int
+ virDomainDiskSourceDefFormat(virBufferPtr buf,
+- virDomainDiskDefPtr def)
++ virDomainDiskDefPtr def,
++ unsigned int flags)
+ {
+ int n;
+ const char *startupPolicy = virDomainStartupPolicyTypeToString(def->startupPolicy);
+@@ -14129,7 +14149,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 8);
+ for (n = 0; n < def->nseclabels; n++)
+- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
++ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
++ flags);
+ virBufferAdjustIndent(buf, -8);
+ virBufferAddLit(buf, " </source>\n");
+ } else {
+@@ -14146,7 +14167,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 8);
+ for (n = 0; n < def->nseclabels; n++)
+- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
++ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
++ flags);
+ virBufferAdjustIndent(buf, -8);
+ virBufferAddLit(buf, " </source>\n");
+ } else {
+@@ -14211,7 +14233,8 @@ virDomainDiskSourceDefFormat(virBufferPtr buf,
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 8);
+ for (n = 0; n < def->nseclabels; n++)
+- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
++ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n],
++ flags);
+ virBufferAdjustIndent(buf, -8);
+ virBufferAddLit(buf, " </source>\n");
+ } else {
+@@ -14347,7 +14370,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
+ virBufferAddLit(buf, " </auth>\n");
+ }
+
+- if (virDomainDiskSourceDefFormat(buf, def) < 0)
++ if (virDomainDiskSourceDefFormat(buf, def, flags) < 0)
+ return -1;
+ virDomainDiskGeometryDefFormat(buf, def);
+ virDomainDiskBlockIoDefFormat(buf, def);
+@@ -15199,7 +15222,7 @@ virDomainChrDefFormat(virBufferPtr buf,
+ if (def->seclabels && def->nseclabels > 0) {
+ virBufferAdjustIndent(buf, 2);
+ for (n = 0; n < def->nseclabels; n++)
+- virSecurityDeviceLabelDefFormat(buf, def->seclabels[n]);
++ virSecurityDeviceLabelDefFormat(buf, def->seclabels[n], flags);
+ virBufferAdjustIndent(buf, -2);
+ }
+
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 29ef0f8..b9e9600 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -343,7 +343,8 @@ typedef virSecurityDeviceLabelDef *virSecurityDeviceLabelDefPtr;
+ struct _virSecurityDeviceLabelDef {
+ char *model;
+ char *label; /* image label string */
+- bool norelabel;
++ bool norelabel; /* true to skip label attempts */
++ bool labelskip; /* live-only; true if skipping failed label attempt */
+ };
+
+
+diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
+index e3dce66a..38de060 100644
+--- a/src/security/security_selinux.c
++++ b/src/security/security_selinux.c
+@@ -917,10 +917,10 @@ virSecuritySELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
+ security_get_boolean_active("virt_use_nfs") != 1) {
+ msg = _("Setting security context '%s' on '%s' not supported. "
+ "Consider setting virt_use_nfs");
+- if (security_getenforce() == 1)
+- VIR_WARN(msg, tcon, path);
+- else
+- VIR_INFO(msg, tcon, path);
++ if (security_getenforce() == 1)
++ VIR_WARN(msg, tcon, path);
++ else
++ VIR_INFO(msg, tcon, path);
+ } else {
+ VIR_INFO("Setting security context '%s' on '%s' not supported",
+ tcon, path);
+@@ -1135,6 +1135,14 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
+ if (seclabel->norelabel || (disk_seclabel && disk_seclabel->norelabel))
+ return 0;
+
++ /* If labelskip is true and there are no backing files, then we
++ * know it is safe to skip the restore. FIXME - backing files should
++ * be tracked in domain XML, at which point labelskip should be a
++ * per-file attribute instead of a disk attribute. */
++ if (disk_seclabel && disk_seclabel->labelskip &&
++ !disk->backingChain)
++ return 0;
++
+ /* Don't restore labels on readoly/shared disks, because
+ * other VMs may still be accessing these
+ * Alternatively we could iterate over all running
+@@ -1219,7 +1227,7 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
+ disk_seclabel = virDomainDiskDefGenSecurityLabelDef(SECURITY_SELINUX_NAME);
+ if (!disk_seclabel)
+ return -1;
+- disk_seclabel->norelabel = true;
++ disk_seclabel->labelskip = true;
+ if (VIR_APPEND_ELEMENT(disk->seclabels, disk->nseclabels,
+ disk_seclabel) < 0) {
+ virSecurityDeviceLabelDefFree(disk_seclabel);
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args
+new file mode 100644
+index 0000000..892c6b5
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.args
+@@ -0,0 +1,5 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
++-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
++unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
++-hda /dev/HostVG/QEMUGuest1 \
++-net none -serial none -parallel none
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml
+new file mode 100644
+index 0000000..e3bc700
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-dynamic-labelskip.xml
+@@ -0,0 +1,32 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <disk type='block' device='disk'>
++ <source dev='/dev/HostVG/QEMUGuest1'>
++ <seclabel model='selinux' labelskip='yes'/>
++ </source>
++ <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'/>
++ <memballoon model='virtio'/>
++ </devices>
++ <seclabel type='dynamic' model='selinux' relabel='yes'>
++ <baselabel>system_u:system_r:svirt_custom_t:s0</baselabel>
++ </seclabel>
++</domain>
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args
+new file mode 100644
+index 0000000..892c6b5
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.args
+@@ -0,0 +1,5 @@
++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
++-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \
++unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
++-hda /dev/HostVG/QEMUGuest1 \
++-net none -serial none -parallel none
+diff --git a/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml
+new file mode 100644
+index 0000000..a743448
+--- /dev/null
++++ b/tests/qemuxml2argvdata/qemuxml2argv-seclabel-static-labelskip.xml
+@@ -0,0 +1,33 @@
++<domain type='qemu' id='1'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <disk type='block' device='disk'>
++ <source dev='/dev/HostVG/QEMUGuest1'>
++ <seclabel model='selinux' labelskip='yes'/>
++ </source>
++ <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'/>
++ <memballoon model='virtio'/>
++ </devices>
++ <seclabel type='static' model='selinux' relabel='yes'>
++ <label>system_u:system_r:svirt_custom_t:s0:c192,c392</label>
++ <imagelabel>system_u:system_r:svirt_custom_t:s0:c192,c392</imagelabel>
++ </seclabel>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 679124e..3a3c304 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -923,8 +923,10 @@ mymain(void)
+ DO_TEST("seclabel-dynamic", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-dynamic-baselabel", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-dynamic-override", QEMU_CAPS_NAME);
++ DO_TEST("seclabel-dynamic-labelskip", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-static", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-static-relabel", QEMU_CAPS_NAME);
++ DO_TEST("seclabel-static-labelskip", QEMU_CAPS_NAME);
+ DO_TEST("seclabel-none", QEMU_CAPS_NAME);
+
+ DO_TEST("pseries-basic",
+diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml
+new file mode 100644
+index 0000000..0764691
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-dynamic-labelskip.xml
+@@ -0,0 +1,31 @@
++<domain type='qemu'>
++ <name>QEMUGuest1</name>
++ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++ <memory unit='KiB'>219100</memory>
++ <currentMemory unit='KiB'>219100</currentMemory>
++ <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu>
++ <os>
++ <type arch='i686' machine='pc'>hvm</type>
++ <boot dev='hd'/>
++ </os>
++ <clock offset='utc'/>
++ <on_poweroff>destroy</on_poweroff>
++ <on_reboot>restart</on_reboot>
++ <on_crash>destroy</on_crash>
++ <devices>
++ <emulator>/usr/bin/qemu</emulator>
++ <disk type='block' device='disk'>
++ <source dev='/dev/HostVG/QEMUGuest1'>
++ </source>
++ <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'/>
++ <memballoon model='virtio'/>
++ </devices>
++ <seclabel type='dynamic' model='selinux' relabel='yes'>
++ <baselabel>system_u:system_r:svirt_custom_t:s0</baselabel>
++ </seclabel>
++</domain>
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index 5c6730d..6eebc68 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -30,6 +30,7 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live)
+ char *actual = NULL;
+ int ret = -1;
+ virDomainDefPtr def = NULL;
++ unsigned int flags = live ? 0 : VIR_DOMAIN_XML_INACTIVE;
+
+ if (virtTestLoadFile(inxml, &inXmlData) < 0)
+ goto fail;
+@@ -37,11 +38,10 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml, bool live)
+ goto fail;
+
+ if (!(def = virDomainDefParseString(inXmlData, driver.caps, driver.xmlopt,
+- QEMU_EXPECTED_VIRT_TYPES,
+- live ? 0 : VIR_DOMAIN_XML_INACTIVE)))
++ QEMU_EXPECTED_VIRT_TYPES, flags)))
+ goto fail;
+
+- if (!(actual = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE)))
++ if (!(actual = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE | flags)))
+ goto fail;
+
+ if (STRNEQ(outXmlData, actual)) {
+@@ -257,7 +257,9 @@ mymain(void)
+
+ DO_TEST_FULL("seclabel-dynamic-baselabel", false, WHEN_INACTIVE);
+ DO_TEST_FULL("seclabel-dynamic-override", false, WHEN_INACTIVE);
++ DO_TEST_FULL("seclabel-dynamic-labelskip", true, WHEN_INACTIVE);
+ DO_TEST("seclabel-static");
++ DO_TEST_FULL("seclabel-static-labelskip", false, WHEN_ACTIVE);
+ DO_TEST("seclabel-none");
+ DO_TEST("numad-static-vcpu-no-numatune");
+ DO_TEST("disk-scsi-lun-passthrough-sgio");
+--
+1.8.3.2
+
--- /dev/null
+From 6deaf5a18aa0c03952cdcaa5ea95f53aebcf995f Mon Sep 17 00:00:00 2001
+Message-Id: <6deaf5a18aa0c03952cdcaa5ea95f53aebcf995f.1378475168.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Tue, 20 Aug 2013 11:08:55 -0600
+Subject: [PATCH] selinux: enhance test to cover nfs label failure
+
+https://bugzilla.redhat.com/show_bug.cgi?id=924153
+
+Daniel Berrange (correctly) pointed out that we should do a better
+job of testing selinux labeling fallbacks on NFS disks that lack
+labeling support.
+
+* tests/securityselinuxhelper.c (includes): Makefile already
+guaranteed xattr support. Add additional headers.
+(init_syms): New function, borrowing from vircgroupmock.c.
+(setfilecon_raw, getfilecon_raw): Fake NFS failure.
+(statfs): Fake an NFS mount point.
+(security_getenforce, security_get_boolean_active): Don't let host
+environment affect test.
+* tests/securityselinuxlabeldata/nfs.data: New file.
+* tests/securityselinuxlabeldata/nfs.xml: New file.
+* tests/securityselinuxlabeltest.c (testSELinuxCreateDisks)
+(testSELinuxDeleteDisks): Setup and cleanup for fake NFS mount.
+(testSELinuxCheckLabels): Test handling of SELinux NFS denial.
+Fix memory leak.
+(testSELinuxLabeling): Avoid infinite loop on dirty tree.
+(mymain): Add new test.
+
+(cherry picked from commit 95577af442e503bb209808b04b6482c895c9f561)
+---
+ tests/securityselinuxhelper.c | 86 ++++++++++++++++++++++++++++++----
+ tests/securityselinuxlabeldata/nfs.txt | 1 +
+ tests/securityselinuxlabeldata/nfs.xml | 24 ++++++++++
+ tests/securityselinuxlabeltest.c | 17 +++++--
+ 4 files changed, 117 insertions(+), 11 deletions(-)
+ create mode 100644 tests/securityselinuxlabeldata/nfs.txt
+ create mode 100644 tests/securityselinuxlabeldata/nfs.xml
+
+diff --git a/tests/securityselinuxhelper.c b/tests/securityselinuxhelper.c
+index a82ca6d..89cba3a 100644
+--- a/tests/securityselinuxhelper.c
++++ b/tests/securityselinuxhelper.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2011-2012 Red Hat, Inc.
++ * Copyright (C) 2011-2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -19,22 +19,53 @@
+
+ #include <config.h>
+
++/* This file is only compiled on Linux, and only if xattr support was
++ * detected. */
++
++#include <dlfcn.h>
++#include <errno.h>
++#include <linux/magic.h>
+ #include <selinux/selinux.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <sys/vfs.h>
+ #include <unistd.h>
+-#include <errno.h>
+-#if WITH_ATTR
+-# include <attr/xattr.h>
+-#endif
++#include <attr/xattr.h>
+
+ #include "virstring.h"
+
++static int (*realstatfs)(const char *path, struct statfs *buf);
++static int (*realsecurity_get_boolean_active)(const char *name);
++
++static void init_syms(void)
++{
++ if (realstatfs)
++ return;
++
++#define LOAD_SYM(name) \
++ do { \
++ if (!(real ## name = dlsym(RTLD_NEXT, #name))) { \
++ fprintf(stderr, "Cannot find real '%s' symbol\n", #name); \
++ abort(); \
++ } \
++ } while (0)
++
++ LOAD_SYM(statfs);
++ LOAD_SYM(security_get_boolean_active);
++
++#undef LOAD_SYM
++}
++
++
+ /*
+ * The kernel policy will not allow us to arbitrarily change
+ * test process context. This helper is used as an LD_PRELOAD
+ * so that the libvirt code /thinks/ it is changing/reading
+- * the process context, where as in fact we're faking it all
++ * the process context, whereas in fact we're faking it all.
++ * Furthermore, we fake out that we are using an nfs subdirectory,
++ * where we control whether selinux is enforcing and whether
++ * the virt_use_nfs bool is set.
+ */
+
+ int getcon_raw(security_context_t *context)
+@@ -83,10 +114,13 @@ int setcon(security_context_t context)
+ }
+
+
+-#if WITH_ATTR
+ int setfilecon_raw(const char *path, security_context_t con)
+ {
+ const char *constr = con;
++ if (STRPREFIX(path, abs_builddir "/securityselinuxlabeldata/nfs/")) {
++ errno = EOPNOTSUPP;
++ return -1;
++ }
+ return setxattr(path, "user.libvirt.selinux",
+ constr, strlen(constr), 0);
+ }
+@@ -101,6 +135,10 @@ int getfilecon_raw(const char *path, security_context_t *con)
+ char *constr = NULL;
+ ssize_t len = getxattr(path, "user.libvirt.selinux",
+ NULL, 0);
++ if (STRPREFIX(path, abs_builddir "/securityselinuxlabeldata/nfs/")) {
++ errno = EOPNOTSUPP;
++ return -1;
++ }
+ if (len < 0)
+ return -1;
+ if (!(constr = malloc(len+1)))
+@@ -114,8 +152,40 @@ int getfilecon_raw(const char *path, security_context_t *con)
+ constr[len] = '\0';
+ return 0;
+ }
++
++
+ int getfilecon(const char *path, security_context_t *con)
+ {
+ return getfilecon_raw(path, con);
+ }
+-#endif
++
++
++int statfs(const char *path, struct statfs *buf)
++{
++ int ret;
++
++ init_syms();
++
++ ret = realstatfs(path, buf);
++ if (!ret && STREQ(path, abs_builddir "/securityselinuxlabeldata/nfs"))
++ buf->f_type = NFS_SUPER_MAGIC;
++ return ret;
++}
++
++
++int security_getenforce(void)
++{
++ /* For the purpose of our test, we are enforcing. */
++ return 1;
++}
++
++
++int security_get_boolean_active(const char *name)
++{
++ /* For the purpose of our test, nfs is not permitted. */
++ if (STREQ(name, "virt_use_nfs"))
++ return 0;
++
++ init_syms();
++ return realsecurity_get_boolean_active(name);
++}
+diff --git a/tests/securityselinuxlabeldata/nfs.txt b/tests/securityselinuxlabeldata/nfs.txt
+new file mode 100644
+index 0000000..4c1698e
+--- /dev/null
++++ b/tests/securityselinuxlabeldata/nfs.txt
+@@ -0,0 +1 @@
++/nfs/plain.raw;EOPNOTSUPP
+diff --git a/tests/securityselinuxlabeldata/nfs.xml b/tests/securityselinuxlabeldata/nfs.xml
+new file mode 100644
+index 0000000..46a1440
+--- /dev/null
++++ b/tests/securityselinuxlabeldata/nfs.xml
+@@ -0,0 +1,24 @@
++<domain type='kvm'>
++ <name>vm1</name>
++ <uuid>c7b3edbd-edaf-9455-926a-d65c16db1800</uuid>
++ <memory unit='KiB'>219200</memory>
++ <os>
++ <type arch='i686' machine='pc-1.0'>hvm</type>
++ <boot dev='cdrom'/>
++ </os>
++ <devices>
++ <disk type='file' device='disk'>
++ <driver name='qemu' type='raw'/>
++ <source file='/nfs/plain.raw'/>
++ <target dev='vda' bus='virtio'/>
++ </disk>
++ <input type='mouse' bus='ps2'/>
++ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
++ <listen type='address' address='0.0.0.0'/>
++ </graphics>
++ </devices>
++ <seclabel model="selinux" type="dynamic" relabel="yes">
++ <label>system_u:system_r:svirt_t:s0:c41,c264</label>
++ <imagelabel>system_u:object_r:svirt_image_t:s0:c41,c264</imagelabel>
++ </seclabel>
++</domain>
+diff --git a/tests/securityselinuxlabeltest.c b/tests/securityselinuxlabeltest.c
+index efe825a..fa99f99 100644
+--- a/tests/securityselinuxlabeltest.c
++++ b/tests/securityselinuxlabeltest.c
+@@ -209,7 +209,7 @@ testSELinuxCreateDisks(testSELinuxFile *files, size_t nfiles)
+ {
+ size_t i;
+
+- if (virFileMakePath(abs_builddir "/securityselinuxlabeldata") < 0)
++ if (virFileMakePath(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
+ return -1;
+
+ for (i = 0; i < nfiles; i++) {
+@@ -228,6 +228,10 @@ testSELinuxDeleteDisks(testSELinuxFile *files, size_t nfiles)
+ if (unlink(files[i].file) < 0)
+ return -1;
+ }
++ if (rmdir(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
++ return -1;
++ /* Ignore failure to remove non-empty directory with in-tree build */
++ rmdir(abs_builddir "/securityselinuxlabeldata");
+ return 0;
+ }
+
+@@ -238,9 +242,13 @@ testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
+ security_context_t ctx;
+
+ for (i = 0; i < nfiles; i++) {
++ ctx = NULL;
+ if (getfilecon(files[i].file, &ctx) < 0) {
+ if (errno == ENODATA) {
+- ctx = NULL;
++ /* nothing to do */
++ } else if (errno == EOPNOTSUPP) {
++ if (VIR_STRDUP(ctx, "EOPNOTSUPP") < 0)
++ return -1;
+ } else {
+ virReportSystemError(errno,
+ "Cannot read label on %s",
+@@ -252,8 +260,10 @@ testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "File %s context '%s' did not match epected '%s'",
+ files[i].file, ctx, files[i].context);
++ VIR_FREE(ctx);
+ return -1;
+ }
++ VIR_FREE(ctx);
+ }
+ return 0;
+ }
+@@ -287,7 +297,7 @@ testSELinuxLabeling(const void *opaque)
+
+ cleanup:
+ if (testSELinuxDeleteDisks(files, nfiles) < 0)
+- goto cleanup;
++ VIR_WARN("unable to fully clean up");
+
+ virDomainDefFree(def);
+ for (i = 0; i < nfiles; i++) {
+@@ -334,6 +344,7 @@ mymain(void)
+ DO_TEST_LABELING("disks");
+ DO_TEST_LABELING("kernel");
+ DO_TEST_LABELING("chardev");
++ DO_TEST_LABELING("nfs");
+
+ return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 7d9c9d6cc0664f2d92e771a5c088cc251a619759 Mon Sep 17 00:00:00 2001
+Message-Id: <7d9c9d6cc0664f2d92e771a5c088cc251a619759.1378475168.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 3 Sep 2013 17:15:51 +0200
+Subject: [PATCH] test_virtlockd.aug.in: Use the correct file
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1003685
+
+The test should refer to Virtlockd.lns, which is the name of
+the module + lens in virtlockd.aug.
+(cherry picked from commit 4471ecf66955f895ae3508b8d6fb7b5e768f735f)
+---
+ src/locking/test_virtlockd.aug.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/locking/test_virtlockd.aug.in b/src/locking/test_virtlockd.aug.in
+index dcd47c3..799818e 100644
+--- a/src/locking/test_virtlockd.aug.in
++++ b/src/locking/test_virtlockd.aug.in
+@@ -5,7 +5,7 @@ log_outputs=\"3:syslog:libvirtd\"
+ log_buffer_size = 64
+ "
+
+- test Libvirtd.lns get conf =
++ test Virtlockd.lns get conf =
+ { "log_level" = "3" }
+ { "log_filters" = "3:remote 4:event" }
+ { "log_outputs" = "3:syslog:libvirtd" }
+--
+1.8.3.2
+
--- /dev/null
+From 5eb44efbfb8d5d2bbfdca1d3fbaef8aa78afa1d2 Mon Sep 17 00:00:00 2001
+Message-Id: <5eb44efbfb8d5d2bbfdca1d3fbaef8aa78afa1d2.1377873640.git.jdenemar@redhat.com>
+From: Martin Kletzander <mkletzan@redhat.com>
+Date: Thu, 22 Aug 2013 15:39:04 +0200
+Subject: [PATCH] tests: Add URI precedence checking
+
+https://bugzilla.redhat.com/show_bug.cgi?id=999323
+
+Commit a0b6a36f is fixing what commit abfff210 broke, so to avoid having
+to deal with this issue again, herec comes "virsh-uriprecedence".
+
+(cherry picked from commit 398de14734c1a9a8053f23ffbbaf47bac1b3f716)
+---
+ tests/Makefile.am | 2 ++
+ tests/virsh-uriprecedence | 76 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 78 insertions(+)
+ create mode 100755 tests/virsh-uriprecedence
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index efd28e3..0c6e5ee 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -98,6 +98,7 @@ EXTRA_DIST = \
+ storagevolxml2xmlout \
+ sysinfodata \
+ test-lib.sh \
++ virsh-uriprecedence \
+ vmx2xmldata \
+ xencapsdata \
+ xmconfigdata \
+@@ -234,6 +235,7 @@ test_scripts += \
+ read-bufsiz \
+ read-non-seekable \
+ start \
++ virsh-uriprecedence \
+ vcpupin \
+ virsh-all \
+ virsh-optparse \
+diff --git a/tests/virsh-uriprecedence b/tests/virsh-uriprecedence
+new file mode 100755
+index 0000000..f4d84a4
+--- /dev/null
++++ b/tests/virsh-uriprecedence
+@@ -0,0 +1,76 @@
++#!/bin/sh
++
++: ${srcdir=.}
++. $srcdir/test-lib.sh
++
++# This test checks if virsh obeys the proper precedence of different
++# URI settings
++test_intro "virsh-uriprecedence"
++
++virsh_bin="$abs_top_builddir/tools/virsh"
++counter=1
++ret=0
++
++cleanup_() { rm -rf "$tmphome"; }
++
++# Create all mock files/directories to avoid permission problems
++tmphome="$PWD/tmp_home"
++export XDG_CONFIG_HOME="$tmphome/.config"
++export XDG_CACHE_HOME="$tmphome/.cache"
++export XDG_RUNTIME_HOME="XDG_CACHE_HOME"
++
++mkdir -p "$XDG_CONFIG_HOME/libvirt" "$XDG_CONFIG_HOME/virsh"
++mkdir -p "$XDG_CACHE_HOME/libvirt" "$XDG_CACHE_HOME/virsh"
++mkdir -p "$XDG_RUNTIME_HOME/libvirt" "$XDG_RUNTIME_HOME/virsh"
++
++# Main function checking for the proper uri being returned
++test_uri()
++{
++ result=0
++ if [ "$($virsh_bin uri)" != "$good_uri" ]; then
++ result=1
++ ret=1
++ fi
++ test_result "$counter" "$1" "$result"
++ counter="$((counter+1))"
++}
++
++# Precedence is the following (lowest priority first):
++#
++# 1) if run as root, 'uri_default' from /etc/libvirtd/libvirt.conf,
++# otherwise qemu:///session. There is no way to mock this file for
++# virsh/libvirt.so and the user may have set anything in there that
++# would spoil the test, so we don't test this
++#
++# 2) 'uri_default' from $XDG_CONFIG_HOME/libvirt/libvirt.conf
++#
++# 3) LIBVIRT_DEFAULT_URI
++#
++# 4) VIRSH_DEFAULT_CONNECT_URI
++#
++# 5) parameter -c (--connect)
++
++unset LIBVIRT_DEFAULT_URI
++unset VIRSH_DEFAULT_CONNECT_URI
++bad_uri="test:///default?bad_uri"
++good_uri="test:///default?good_uri"
++
++printf "uri_default=\"%s\"\n" "$good_uri" >"$XDG_CONFIG_HOME/libvirt/libvirt.conf"
++test_uri "User config file"
++
++printf "uri_default=\"%s\"\n" "$bad_uri" >"$XDG_CONFIG_HOME/libvirt/libvirt.conf"
++export LIBVIRT_DEFAULT_URI="$good_uri"
++test_uri "LIBVIRT_DEFAULT_URI"
++
++export LIBVIRT_DEFAULT_URI="$bad_uri"
++export VIRSH_DEFAULT_CONNECT_URI="$good_uri"
++test_uri "VIRSH_DEFAULT_CONNECT_URI"
++
++export VIRSH_DEFAULT_CONNECT_URI="$bad_uri"
++virsh_bin="$virsh_bin --connect $good_uri"
++test_uri "Parameter"
++
++# test_uri() increases $counter even for the last test, so we must
++# decrement it
++test_final "$((counter-1))" "$ret"
++(exit "$ret"); exit "$ret"
+--
+1.8.3.2
+
--- /dev/null
+From f7bff4830e9dadb1016eaa5bd9dfae7153f1304d Mon Sep 17 00:00:00 2001
+Message-Id: <f7bff4830e9dadb1016eaa5bd9dfae7153f1304d.1377873638.git.jdenemar@redhat.com>
+From: Martin Kletzander <mkletzan@redhat.com>
+Date: Tue, 13 Aug 2013 11:32:50 +0100
+Subject: [PATCH] tests: Fix parallel runs of TLS test suites
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+I noticed this yesterday and fixed it in a different way, but ended up
+with one more problem. It was probably the way I fixed it combined
+with one more filename changed.
+
+Anyway, why I'm saying this is that one more filename should be renamed
+in order to avoid a race (which I was unable to reproduce, though).
+
+I checked this is the last file those two tests have in common by going
+through the code and the re-checked by this "script":
+
+strace -o session.trace -e open ./virnettlssessiontest
+strace -o context.trace -e open ./virnettlscontexttest
+sort \
+ <(sed -n '/^open/s/open("\([^"]*\)",.*$/\1/p' context.trace | sort -u)\
+ <(sed -n '/^open/s/open("\([^"]*\)",.*$/\1/p' session.trace | sort -u)\
+ | uniq -d| grep '.pem$'
+
+So it should be enough to make these tests independent of each other.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 3be7a30426d215ed50938d3674c50097b33953bf)
+---
+ tests/virnettlscontexttest.c | 8 ++++----
+ tests/virnettlssessiontest.c | 6 +++---
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c
+index 53792ee..2c7d400 100644
+--- a/tests/virnettlscontexttest.c
++++ b/tests/virnettlscontexttest.c
+@@ -556,12 +556,12 @@ mymain(void)
+ cacertlevel2areq.crt,
+ };
+
+- testTLSWriteCertChain("cacertchain.pem",
++ testTLSWriteCertChain("cacertchain-ctx.pem",
+ certchain,
+ ARRAY_CARDINALITY(certchain));
+
+- DO_CTX_TEST(true, "cacertchain.pem", servercertlevel3areq.filename, false);
+- DO_CTX_TEST(false, "cacertchain.pem", clientcertlevel2breq.filename, false);
++ DO_CTX_TEST(true, "cacertchain-ctx.pem", servercertlevel3areq.filename, false);
++ DO_CTX_TEST(false, "cacertchain-ctx.pem", clientcertlevel2breq.filename, false);
+
+ testTLSDiscardCert(&cacertreq);
+ testTLSDiscardCert(&cacert1req);
+@@ -617,7 +617,7 @@ mymain(void)
+ testTLSDiscardCert(&cacertlevel2areq);
+ testTLSDiscardCert(&servercertlevel3areq);
+ testTLSDiscardCert(&clientcertlevel2breq);
+- unlink("cacertchain.pem");
++ unlink("cacertchain-ctx.pem");
+
+ testTLSCleanup(KEYFILE);
+
+diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c
+index 9b171ed..f5f7212 100644
+--- a/tests/virnettlssessiontest.c
++++ b/tests/virnettlssessiontest.c
+@@ -451,11 +451,11 @@ mymain(void)
+ cacertlevel2areq.crt,
+ };
+
+- testTLSWriteCertChain("cacertchain.pem",
++ testTLSWriteCertChain("cacertchain-sess.pem",
+ certchain,
+ ARRAY_CARDINALITY(certchain));
+
+- DO_SESS_TEST("cacertchain.pem", servercertlevel3areq.filename, clientcertlevel2breq.filename,
++ DO_SESS_TEST("cacertchain-sess.pem", servercertlevel3areq.filename, clientcertlevel2breq.filename,
+ false, false, "libvirt.org", NULL);
+
+ testTLSDiscardCert(&clientcertreq);
+@@ -474,7 +474,7 @@ mymain(void)
+ testTLSDiscardCert(&cacertlevel2areq);
+ testTLSDiscardCert(&servercertlevel3areq);
+ testTLSDiscardCert(&clientcertlevel2breq);
+- unlink("cacertchain.pem");
++ unlink("cacertchain-sess.pem");
+
+ testTLSCleanup(KEYFILE);
+
+--
+1.8.3.2
+
--- /dev/null
+From 580b26c2c30c28ef417009f08296ffa43bb76e0c Mon Sep 17 00:00:00 2001
+Message-Id: <580b26c2c30c28ef417009f08296ffa43bb76e0c.1381871412.git.jdenemar@redhat.com>
+From: Eric Blake <eblake@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:10 +0100
+Subject: [PATCH] tests: work with older dbus
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+On RHEL 5, with dbus 1.1.2, compilation failed with:
+
+virsystemdmock.c: In function 'dbus_connection_send_with_reply_and_block':
+virsystemdmock.c:68: warning: implicit declaration of function 'dbus_message_set_serial'
+
+Fix this by instead bypassing all attempts to use a dbus serial.
+
+* tests/virsystemdmock.c (dbus_message_set_reply_serial): Add new
+override.
+(dbus_connection_send_with_reply_and_block): No longer bother with
+the serial.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit edfae3dccf5eceeb86e1c4304dca8a8ed0f74e57)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/virsystemdmock.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/tests/virsystemdmock.c b/tests/virsystemdmock.c
+index b6c3695..ded52d2 100644
+--- a/tests/virsystemdmock.c
++++ b/tests/virsystemdmock.c
+@@ -58,6 +58,12 @@ dbus_bool_t dbus_connection_set_watch_functions(DBusConnection *connection ATTRI
+ return 1;
+ }
+
++dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message ATTRIBUTE_UNUSED,
++ dbus_uint32_t serial ATTRIBUTE_UNUSED)
++{
++ return 1;
++}
++
+ DBusMessage *dbus_connection_send_with_reply_and_block(DBusConnection *connection ATTRIBUTE_UNUSED,
+ DBusMessage *message,
+ int timeout_milliseconds ATTRIBUTE_UNUSED,
+@@ -65,8 +71,6 @@ DBusMessage *dbus_connection_send_with_reply_and_block(DBusConnection *connectio
+ {
+ DBusMessage *reply = NULL;
+
+- dbus_message_set_serial(message, 7);
+-
+ if (getenv("FAIL_BAD_SERVICE"))
+ reply = dbus_message_new_error(message,
+ "org.freedesktop.systemd.badthing",
+--
+1.8.3.2
+
--- /dev/null
+From 4e04f5df15242cceaba6c60992cfb2347afee457 Mon Sep 17 00:00:00 2001
+Message-Id: <4e04f5df15242cceaba6c60992cfb2347afee457.1377873638.git.jdenemar@redhat.com>
+From: Dan Walsh <dwalsh@redhat.com>
+Date: Tue, 13 Aug 2013 15:20:39 +0100
+Subject: [PATCH] util: add virGetUserDirectoryByUID
+
+For https://bugzilla.redhat.com/show_bug.cgi?id=988491
+
+This function is needed for virt-login-shell. Also modify virGirUserDirectory
+to use the new function, to simplify the code.
+
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit fbd7682706d52445fbc0f6fa1c4b7965256e733f)
+---
+ src/libvirt_private.syms | 1 +
+ src/util/virutil.c | 22 ++++++++++++++++++----
+ src/util/virutil.h | 1 +
+ 3 files changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 9cfb84c..faa67ad 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2047,6 +2047,7 @@ virGetUnprivSGIOSysfsPath;
+ virGetUserCacheDirectory;
+ virGetUserConfigDirectory;
+ virGetUserDirectory;
++virGetUserDirectoryByUID;
+ virGetUserID;
+ virGetUserName;
+ virGetUserRuntimeDirectory;
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index adcdb3c..3abcd53 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -647,6 +647,14 @@ cleanup:
+ return result;
+ }
+
++
++char *
++virGetUserDirectory(void)
++{
++ return virGetUserDirectoryByUID(geteuid());
++}
++
++
+ #ifdef HAVE_GETPWUID_R
+ /* Look up fields from the user database for the given user. On
+ * error, set errno, report the error, and return -1. */
+@@ -750,13 +758,16 @@ static char *virGetGroupEnt(gid_t gid)
+ return ret;
+ }
+
+-char *virGetUserDirectory(void)
++
++char *
++virGetUserDirectoryByUID(uid_t uid)
+ {
+ char *ret;
+- virGetUserEnt(geteuid(), NULL, NULL, &ret);
++ virGetUserEnt(uid, NULL, NULL, &ret);
+ return ret;
+ }
+
++
+ static char *virGetXDGDirectory(const char *xdgenvname, const char *xdgdefdir)
+ {
+ const char *path = getenv(xdgenvname);
+@@ -1092,8 +1103,11 @@ virGetWin32DirectoryRoot(char **path)
+
+
+ char *
+-virGetUserDirectory(void)
++virGetUserDirectoryByUID(uid_t uid ATTRIBUTE_UNUSED)
+ {
++ /* Since Windows lacks setuid binaries, and since we already fake
++ * geteuid(), we can safely assume that this is only called when
++ * querying about the current user */
+ const char *dir;
+ char *ret;
+
+@@ -1177,7 +1191,7 @@ virGetUserRuntimeDirectory(void)
+
+ # else /* !HAVE_GETPWUID_R && !WIN32 */
+ char *
+-virGetUserDirectory(void)
++virGetUserDirectoryByUID(uid_t uid ATTRIBUTE_UNUSED)
+ {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("virGetUserDirectory is not available"));
+diff --git a/src/util/virutil.h b/src/util/virutil.h
+index 526c610..4b06992 100644
+--- a/src/util/virutil.h
++++ b/src/util/virutil.h
+@@ -111,6 +111,7 @@ static inline int getgid (void) { return 0; }
+ char *virGetHostname(void);
+
+ char *virGetUserDirectory(void);
++char *virGetUserDirectoryByUID(uid_t uid);
+ char *virGetUserConfigDirectory(void);
+ char *virGetUserCacheDirectory(void);
+ char *virGetUserRuntimeDirectory(void);
+--
+1.8.3.2
+
--- /dev/null
+From 3a1d215c947592bdf9db3cb65480add04119bb98 Mon Sep 17 00:00:00 2001
+Message-Id: <3a1d215c947592bdf9db3cb65480add04119bb98.1383922565.git.jdenemar@redhat.com>
+From: Laine Stump <laine@laine.org>
+Date: Fri, 8 Nov 2013 05:42:32 -0700
+Subject: [PATCH] util: use size_t instead of unsigned int for
+ num_virtual_functions
+
+This is a prerequisite to the fix for the fix to:
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1025397
+
+num_virtual_functions needs to be size_t in order to use the
+VIR_APPEND_ELEMENT macro.
+
+(cherry picked from commit 89e2a6c88c2d26cf3a9a70adc8fdac970a471b64)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/node_device_conf.h | 2 +-
+ src/network/bridge_driver.c | 2 +-
+ src/util/virnetdev.c | 4 ++--
+ src/util/virnetdev.h | 2 +-
+ src/util/virpci.c | 8 ++++----
+ src/util/virpci.h | 2 +-
+ 6 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
+index 1fa61b5..60cf8c3 100644
+--- a/src/conf/node_device_conf.h
++++ b/src/conf/node_device_conf.h
+@@ -110,7 +110,7 @@ struct _virNodeDevCapsDef {
+ char *vendor_name;
+ virPCIDeviceAddressPtr physical_function;
+ virPCIDeviceAddressPtr *virtual_functions;
+- unsigned int num_virtual_functions;
++ size_t num_virtual_functions;
+ unsigned int flags;
+ virPCIDeviceAddressPtr *iommuGroupDevices;
+ size_t nIommuGroupDevices;
+diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
+index c900478..6e31840 100644
+--- a/src/network/bridge_driver.c
++++ b/src/network/bridge_driver.c
+@@ -3736,7 +3736,7 @@ int networkRegister(void) {
+ */
+ static int
+ networkCreateInterfacePool(virNetworkDefPtr netdef) {
+- unsigned int num_virt_fns = 0;
++ size_t num_virt_fns = 0;
+ char **vfname = NULL;
+ virPCIDeviceAddressPtr *virt_fns;
+ int ret = -1;
+diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
+index 30df7a6..566a207 100644
+--- a/src/util/virnetdev.c
++++ b/src/util/virnetdev.c
+@@ -1080,7 +1080,7 @@ int
+ virNetDevGetVirtualFunctions(const char *pfname,
+ char ***vfname,
+ virPCIDeviceAddressPtr **virt_fns,
+- unsigned int *n_vfname)
++ size_t *n_vfname)
+ {
+ int ret = -1;
+ size_t i;
+@@ -1267,7 +1267,7 @@ int
+ virNetDevGetVirtualFunctions(const char *pfname ATTRIBUTE_UNUSED,
+ char ***vfname ATTRIBUTE_UNUSED,
+ virPCIDeviceAddressPtr **virt_fns ATTRIBUTE_UNUSED,
+- unsigned int *n_vfname ATTRIBUTE_UNUSED)
++ size_t *n_vfname ATTRIBUTE_UNUSED)
+ {
+ virReportSystemError(ENOSYS, "%s",
+ _("Unable to get virtual functions on this platform"));
+diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
+index 44a37ca..9fd6628 100644
+--- a/src/util/virnetdev.h
++++ b/src/util/virnetdev.h
+@@ -124,7 +124,7 @@ int virNetDevGetPhysicalFunction(const char *ifname, char **pfname)
+ int virNetDevGetVirtualFunctions(const char *pfname,
+ char ***vfname,
+ virPCIDeviceAddressPtr **virt_fns,
+- unsigned int *n_vfname)
++ size_t *n_vfname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+
+diff --git a/src/util/virpci.c b/src/util/virpci.c
+index be95d03..87ea81b 100644
+--- a/src/util/virpci.c
++++ b/src/util/virpci.c
+@@ -2385,7 +2385,7 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path,
+ int
+ virPCIGetVirtualFunctions(const char *sysfs_path,
+ virPCIDeviceAddressPtr **virtual_functions,
+- unsigned int *num_virtual_functions)
++ size_t *num_virtual_functions)
+ {
+ int ret = -1;
+ size_t i;
+@@ -2418,7 +2418,7 @@ virPCIGetVirtualFunctions(const char *sysfs_path,
+ goto error;
+ }
+
+- VIR_DEBUG("Number of virtual functions: %d",
++ VIR_DEBUG("Number of virtual functions: %zu",
+ *num_virtual_functions);
+
+ if (virPCIGetDeviceAddressFromSysfsLink(device_link,
+@@ -2489,7 +2489,7 @@ virPCIGetVirtualFunctionIndex(const char *pf_sysfs_device_link,
+ {
+ int ret = -1;
+ size_t i;
+- unsigned int num_virt_fns = 0;
++ size_t num_virt_fns = 0;
+ virPCIDeviceAddressPtr vf_bdf = NULL;
+ virPCIDeviceAddressPtr *virt_fns = NULL;
+
+@@ -2634,7 +2634,7 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path ATTRIBUTE_UNUSED,
+ int
+ virPCIGetVirtualFunctions(const char *sysfs_path ATTRIBUTE_UNUSED,
+ virPCIDeviceAddressPtr **virtual_functions ATTRIBUTE_UNUSED,
+- unsigned int *num_virtual_functions ATTRIBUTE_UNUSED)
++ size_t *num_virtual_functions ATTRIBUTE_UNUSED)
+ {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
+ return -1;
+diff --git a/src/util/virpci.h b/src/util/virpci.h
+index 0aa6fee..0479f0b 100644
+--- a/src/util/virpci.h
++++ b/src/util/virpci.h
+@@ -138,7 +138,7 @@ int virPCIGetPhysicalFunction(const char *sysfs_path,
+
+ int virPCIGetVirtualFunctions(const char *sysfs_path,
+ virPCIDeviceAddressPtr **virtual_functions,
+- unsigned int *num_virtual_functions);
++ size_t *num_virtual_functions);
+
+ int virPCIIsVirtualFunction(const char *vf_sysfs_device_link);
+
+--
+1.8.4.2
+
--- /dev/null
+From 405530fa1be17ff5b8dcff6785b67c63eebf49f7 Mon Sep 17 00:00:00 2001
+Message-Id: <405530fa1be17ff5b8dcff6785b67c63eebf49f7.1379193141.git.jdenemar@redhat.com>
+From: "Liuji (Jeremy)" <jeremy.liu@huawei.com>
+Date: Wed, 11 Sep 2013 09:58:51 +0200
+Subject: [PATCH] virDomainDefParseXML: set the argument of virBitmapFree to
+ NULL after calling virBitmapFree
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006722
+
+After freeing the bitmap pointer, it must set the pointer to NULL.
+This will avoid any other use of the freed memory of the bitmap pointer.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006710
+
+Signed-off-by: Liuji (Jeremy) <jeremy.liu@huawei.com>
+(cherry picked from commit ef5d51d491356f1f4287aa3a8b908b183b6dd9aa)
+---
+ src/conf/domain_conf.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index d6b4ea7..566940c 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -11251,8 +11251,10 @@ virDomainDefParseXML(xmlDocPtr xml,
+ }
+
+ /* Ignore 'nodeset' if 'placement' is 'auto' finally */
+- if (placement_mode == VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_AUTO)
++ if (placement_mode == VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_AUTO) {
+ virBitmapFree(def->numatune.memory.nodemask);
++ def->numatune.memory.nodemask = NULL;
++ }
+
+ /* Copy 'placement' of <numatune> to <vcpu> if its 'placement'
+ * is not specified and 'placement' of <numatune> is specified.
+--
+1.8.3.2
+
--- /dev/null
+From afbd35a816254adcd4a5660a2e9089ee986f9457 Mon Sep 17 00:00:00 2001
+Message-Id: <afbd35a816254adcd4a5660a2e9089ee986f9457.1379193140.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 12 Sep 2013 11:37:33 -0600
+Subject: [PATCH] virFileNBDDeviceAssociate: Avoid use of uninitialized
+ variable
+
+CVE-2013-4297: https://bugzilla.redhat.com/show_bug.cgi?id=1006513
+
+The @qemunbd variable can be used uninitialized.
+
+(cherry picked from commit 2dba0323ff0cec31bdcea9dd3b2428af297401f2)
+---
+ src/util/virfile.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 2b07ac9..7af0843 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -732,7 +732,7 @@ int virFileNBDDeviceAssociate(const char *file,
+ char **dev)
+ {
+ char *nbddev;
+- char *qemunbd;
++ char *qemunbd = NULL;
+ virCommandPtr cmd = NULL;
+ int ret = -1;
+ const char *fmtstr = NULL;
+--
+1.8.3.2
+
--- /dev/null
+From 07cefaf0d0ab324d95e4e0cc1f75004dec487365 Mon Sep 17 00:00:00 2001
+Message-Id: <07cefaf0d0ab324d95e4e0cc1f75004dec487365.1381871411.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 2 Oct 2013 11:04:07 +0200
+Subject: [PATCH] virNetDevBandwidthEqual: Make it more robust
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1014503
+
+So far the virNetDevBandwidthEqual() expected both ->in and ->out items
+to be allocated for both @a and @b compared. This is not necessary true
+for all our code. For instance, running 'update-device' twice over a NIC
+with the very same XML results in SIGSEGV-ing in this function.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit ee02fbc8e4a24c1347761ceff2ddb2c108e9611c)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virnetdevbandwidth.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c
+index 42b0a50..17f4fa3 100644
+--- a/src/util/virnetdevbandwidth.c
++++ b/src/util/virnetdevbandwidth.c
+@@ -335,16 +335,30 @@ virNetDevBandwidthEqual(virNetDevBandwidthPtr a,
+ return false;
+
+ /* in */
+- if (a->in->average != b->in->average ||
+- a->in->peak != b->in->peak ||
+- a->in->burst != b->in->burst)
++ if (a->in) {
++ if (!b->in)
++ return false;
++
++ if (a->in->average != b->in->average ||
++ a->in->peak != b->in->peak ||
++ a->in->burst != b->in->burst)
++ return false;
++ } else if (b->in) {
+ return false;
++ }
+
+ /*out*/
+- if (a->out->average != b->out->average ||
+- a->out->peak != b->out->peak ||
+- a->out->burst != b->out->burst)
++ if (a->out) {
++ if (!b->out)
++ return false;
++
++ if (a->out->average != b->out->average ||
++ a->out->peak != b->out->peak ||
++ a->out->burst != b->out->burst)
++ return false;
++ } else if (b->out) {
+ return false;
++ }
+
+ return true;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From cfa44d1e04f4f32cdfd4098ec8a234fb784b4c9b Mon Sep 17 00:00:00 2001
+Message-Id: <cfa44d1e04f4f32cdfd4098ec8a234fb784b4c9b.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 16 Aug 2013 15:30:58 +0200
+Subject: [PATCH] virbitmap: Refactor virBitmapParse to avoid access beyond
+ bounds of array
+
+https://bugzilla.redhat.com/show_bug.cgi?id=997906 [7.0]
+
+The virBitmapParse function was calling virBitmapIsSet() function that
+requires the caller to check the bounds of the bitmap without checking
+them. This resulted into crashes when parsing a bitmap string that was
+exceeding the bounds used as argument.
+
+This patch refactors the function to use virBitmapSetBit without
+checking if the bit is set (this function does the checks internally)
+and then counts the bits in the bitmap afterwards (instead of keeping
+track while parsing the string).
+
+This patch also changes the "parse_error" label to a more common
+"error".
+
+The refactor should also get rid of the need to call sa_assert on the
+returned variable as the callpath should allow coverity to infer the
+possible return values.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=997367 [6.5]
+
+Thanks to Alex Jia for tracking down the issue. This issue is introduced
+by commit 0fc8909.
+
+(cherry picked from commit 47b9127e883677a0d60d767030a147450e919a25)
+---
+ src/util/virbitmap.c | 38 +++++++++++++++-----------------------
+ 1 file changed, 15 insertions(+), 23 deletions(-)
+
+diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
+index 7e1cd02..47c678e 100644
+--- a/src/util/virbitmap.c
++++ b/src/util/virbitmap.c
+@@ -297,7 +297,6 @@ virBitmapParse(const char *str,
+ virBitmapPtr *bitmap,
+ size_t bitmapSize)
+ {
+- int ret = 0;
+ bool neg = false;
+ const char *cur;
+ char *tmp;
+@@ -330,12 +329,12 @@ virBitmapParse(const char *str,
+ }
+
+ if (!c_isdigit(*cur))
+- goto parse_error;
++ goto error;
+
+ if (virStrToLong_i(cur, &tmp, 10, &start) < 0)
+- goto parse_error;
++ goto error;
+ if (start < 0)
+- goto parse_error;
++ goto error;
+
+ cur = tmp;
+
+@@ -343,35 +342,29 @@ virBitmapParse(const char *str,
+
+ if (*cur == ',' || *cur == 0 || *cur == terminator) {
+ if (neg) {
+- if (virBitmapIsSet(*bitmap, start)) {
+- ignore_value(virBitmapClearBit(*bitmap, start));
+- ret--;
+- }
++ if (virBitmapClearBit(*bitmap, start) < 0)
++ goto error;
+ } else {
+- if (!virBitmapIsSet(*bitmap, start)) {
+- ignore_value(virBitmapSetBit(*bitmap, start));
+- ret++;
+- }
++ if (virBitmapSetBit(*bitmap, start) < 0)
++ goto error;
+ }
+ } else if (*cur == '-') {
+ if (neg)
+- goto parse_error;
++ goto error;
+
+ cur++;
+ virSkipSpaces(&cur);
+
+ if (virStrToLong_i(cur, &tmp, 10, &last) < 0)
+- goto parse_error;
++ goto error;
+ if (last < start)
+- goto parse_error;
++ goto error;
+
+ cur = tmp;
+
+ for (i = start; i <= last; i++) {
+- if (!virBitmapIsSet(*bitmap, i)) {
+- ignore_value(virBitmapSetBit(*bitmap, i));
+- ret++;
+- }
++ if (virBitmapSetBit(*bitmap, i) < 0)
++ goto error;
+ }
+
+ virSkipSpaces(&cur);
+@@ -384,14 +377,13 @@ virBitmapParse(const char *str,
+ } else if (*cur == 0 || *cur == terminator) {
+ break;
+ } else {
+- goto parse_error;
++ goto error;
+ }
+ }
+
+- sa_assert(ret >= 0);
+- return ret;
++ return virBitmapCountBits(*bitmap);
+
+-parse_error:
++error:
+ virBitmapFree(*bitmap);
+ *bitmap = NULL;
+ return -1;
+--
+1.8.3.2
+
--- /dev/null
+From 4e7a676e72a6c29440fba9ef7942a0e615cd8707 Mon Sep 17 00:00:00 2001
+Message-Id: <4e7a676e72a6c29440fba9ef7942a0e615cd8707.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 16 Aug 2013 15:31:00 +0200
+Subject: [PATCH] virbitmaptest: Add test for out of bounds condition
+
+https://bugzilla.redhat.com/show_bug.cgi?id=997906
+
+Previous patch fixed an issue where, when parsing a bitmap from the
+string, the bounds of the bitmap weren't checked. That flaw resulted into
+crashes. This test tests that case to avoid it in the future.
+
+(cherry picked from commit 7efd5fd1b0225436cbbae1181ab41c2d3eca43f9)
+---
+ tests/virbitmaptest.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
+index 8cfd8b5..c56d6fa 100644
+--- a/tests/virbitmaptest.c
++++ b/tests/virbitmaptest.c
+@@ -464,6 +464,38 @@ cleanup:
+ return ret;
+ }
+
++
++/* test out of bounds conditions on virBitmapParse */
++static int
++test9(const void *opaque ATTRIBUTE_UNUSED)
++{
++ int ret = -1;
++ virBitmapPtr bitmap;
++
++ if (virBitmapParse("100000000", 0, &bitmap, 20) != -1)
++ goto cleanup;
++
++ if (bitmap)
++ goto cleanup;
++
++ if (virBitmapParse("1-1000000000", 0, &bitmap, 20) != -1)
++ goto cleanup;
++
++ if (bitmap)
++ goto cleanup;
++
++ if (virBitmapParse("1-10^10000000000", 0, &bitmap, 20) != -1)
++ goto cleanup;
++
++ if (bitmap)
++ goto cleanup;
++
++ ret = 0;
++cleanup:
++ return ret;
++
++}
++
+ static int
+ mymain(void)
+ {
+@@ -485,6 +517,8 @@ mymain(void)
+ ret = -1;
+ if (virtTestRun("test8", 1, test8, NULL) < 0)
+ ret = -1;
++ if (virtTestRun("test9", 1, test9, NULL) < 0)
++ ret = -1;
+
+ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From f3ee83ac90bbea17541cd11bd917e6016eb338b6 Mon Sep 17 00:00:00 2001
+Message-Id: <f3ee83ac90bbea17541cd11bd917e6016eb338b6.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 16 Aug 2013 15:30:59 +0200
+Subject: [PATCH] virbitmaptest: Fix function header formatting
+
+https://bugzilla.redhat.com/show_bug.cgi?id=997906
+
+(cherry picked from commit 536d38128e749fa5b149b9e168224280c3ad348c)
+---
+ tests/virbitmaptest.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
+index 9c7329e..8cfd8b5 100644
+--- a/tests/virbitmaptest.c
++++ b/tests/virbitmaptest.c
+@@ -1,4 +1,6 @@
+ /*
++ * virbitmaptest.c: Test the bitmap code
++ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2012 Fujitsu.
+ *
+@@ -24,7 +26,8 @@
+
+ #include "virbitmap.h"
+
+-static int test1(const void *data ATTRIBUTE_UNUSED)
++static int
++test1(const void *data ATTRIBUTE_UNUSED)
+ {
+ virBitmapPtr bitmap;
+ int size;
+@@ -78,7 +81,8 @@ testBit(virBitmapPtr bitmap,
+ return -1;
+ }
+
+-static int test2(const void *data ATTRIBUTE_UNUSED)
++static int
++test2(const void *data ATTRIBUTE_UNUSED)
+ {
+ const char *bitsString1 = "1-32,50,88-99,1021-1023";
+ char *bitsString2 = NULL;
+@@ -140,7 +144,8 @@ error:
+ return ret;
+ }
+
+-static int test3(const void *data ATTRIBUTE_UNUSED)
++static int
++test3(const void *data ATTRIBUTE_UNUSED)
+ {
+ virBitmapPtr bitmap = NULL;
+ int ret = -1;
+@@ -167,7 +172,8 @@ error:
+ }
+
+ /* test for virBitmapNextSetBit, virBitmapNextClearBit */
+-static int test4(const void *data ATTRIBUTE_UNUSED)
++static int
++test4(const void *data ATTRIBUTE_UNUSED)
+ {
+ const char *bitsString = "0, 2-4, 6-10, 12, 14-18, 20, 22, 25";
+ int size = 40;
+@@ -261,7 +267,8 @@ error:
+ }
+
+ /* test for virBitmapNewData/ToData */
+-static int test5(const void *v ATTRIBUTE_UNUSED)
++static int
++test5(const void *v ATTRIBUTE_UNUSED)
+ {
+ char data[] = {0x01, 0x02, 0x00, 0x00, 0x04};
+ unsigned char *data2 = NULL;
+@@ -309,7 +316,8 @@ error:
+
+
+ /* test for virBitmapFormat */
+-static int test6(const void *v ATTRIBUTE_UNUSED)
++static int
++test6(const void *v ATTRIBUTE_UNUSED)
+ {
+ virBitmapPtr bitmap = NULL;
+ char *str = NULL;
+@@ -390,7 +398,8 @@ error:
+ return ret;
+ }
+
+-static int test7(const void *v ATTRIBUTE_UNUSED)
++static int
++test7(const void *v ATTRIBUTE_UNUSED)
+ {
+ virBitmapPtr bitmap;
+ size_t i;
+@@ -429,7 +438,8 @@ error:
+ return -1;
+ }
+
+-static int test8(const void *v ATTRIBUTE_UNUSED)
++static int
++test8(const void *v ATTRIBUTE_UNUSED)
+ {
+ virBitmapPtr bitmap = NULL;
+ char data[108] = {0x00,};
+--
+1.8.3.2
+
--- /dev/null
+From 2781384efc02836d14b5f7169ba2c4025fd08144 Mon Sep 17 00:00:00 2001
+Message-Id: <2781384efc02836d14b5f7169ba2c4025fd08144.1381871412.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:11 +0100
+Subject: [PATCH] virdbus: Add virDBusHasSystemBus()
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+Some systems may not use DBus in their system. Add a method to check if
+the system bus is available that doesn't print error messages so that
+code can later check for this condition and use an alternative approach.
+
+(cherry picked from commit 2398dd3d3ea2e060318abd3d9346ad65df910803)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 1 +
+ src/util/virdbus.c | 36 +++++++++++++++++++++++++++++++++---
+ src/util/virdbus.h | 1 +
+ 3 files changed, 35 insertions(+), 3 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index e6c23e4..47e989c 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1294,6 +1294,7 @@ virConfWriteMem;
+ virDBusCallMethod;
+ virDBusGetSessionBus;
+ virDBusGetSystemBus;
++virDBusHasSystemBus;
+ virDBusMessageDecode;
+ virDBusMessageEncode;
+ virDBusMessageRead;
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index e88dc26..62c31be 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -73,7 +73,8 @@ static void virDBusSystemBusInit(void)
+ systembus = virDBusBusInit(DBUS_BUS_SYSTEM, &systemdbuserr);
+ }
+
+-DBusConnection *virDBusGetSystemBus(void)
++static DBusConnection *
++virDBusGetSystemBusInternal(void)
+ {
+ if (virOnce(&systemonce, virDBusSystemBusInit) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+@@ -81,14 +82,34 @@ DBusConnection *virDBusGetSystemBus(void)
+ return NULL;
+ }
+
+- if (!systembus) {
++ return systembus;
++}
++
++
++DBusConnection *
++virDBusGetSystemBus(void)
++{
++ DBusConnection *bus;
++
++ if (!(bus = virDBusGetSystemBusInternal())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to get DBus system bus connection: %s"),
+ systemdbuserr.message ? systemdbuserr.message : "watch setup failed");
+ return NULL;
+ }
+
+- return systembus;
++ return bus;
++}
++
++
++bool
++virDBusHasSystemBus(void)
++{
++ if (virDBusGetSystemBusInternal())
++ return true;
++
++ VIR_DEBUG("System DBus not available: %s", NULLSTR(systemdbuserr.message));
++ return false;
+ }
+
+
+@@ -1195,6 +1216,15 @@ DBusConnection *virDBusGetSystemBus(void)
+ return NULL;
+ }
+
++
++bool
++virDBusHasSystemBus(void)
++{
++ VIR_DEBUG("DBus support not compiled into this binary");
++ return false;
++}
++
++
+ DBusConnection *virDBusGetSessionBus(void)
+ {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+diff --git a/src/util/virdbus.h b/src/util/virdbus.h
+index 39de479..a5aab56 100644
+--- a/src/util/virdbus.h
++++ b/src/util/virdbus.h
+@@ -32,6 +32,7 @@
+ # include "internal.h"
+
+ DBusConnection *virDBusGetSystemBus(void);
++bool virDBusHasSystemBus(void);
+ DBusConnection *virDBusGetSessionBus(void);
+
+ int virDBusCallMethod(DBusConnection *conn,
+--
+1.8.3.2
+
--- /dev/null
+From 1bf9fb12d2d9cca51a06f099918b35e24c29ef8e Mon Sep 17 00:00:00 2001
+Message-Id: <1bf9fb12d2d9cca51a06f099918b35e24c29ef8e.1377873639.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Fri, 9 Aug 2013 07:06:34 -0400
+Subject: [PATCH] virnettlscontext: Resolve Coverity warnings (UNINIT)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=994158
+
+Coverity complained about the usage of the uninitialized cacerts in the
+event(s) that "access(certFile, R_OK)" and/or "access(cacertFile, R_OK)"
+fail the for loop used to fill in the certs will have indeterminate data
+as well as the possibility that both failures would result in the
+gnutls_x509_crt_deinit() call having a similar fate.
+
+Initializing cacerts only would resolve the issue; however, it still
+would leave the indeterminate action, so rather add a parameter to
+the virNetTLSContextLoadCACertListFromFile() to pass the max size rather
+then overloading the returned count parameter. If the the call is never
+made, then we won't go through the for loops referencing the empty
+cacerts
+
+(cherry picked from commit f905cc998449c89339d0e2894a71d9a9e45293e5)
+---
+ src/rpc/virnettlscontext.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
+index 2beee8f..7cee27c 100644
+--- a/src/rpc/virnettlscontext.c
++++ b/src/rpc/virnettlscontext.c
+@@ -545,12 +545,12 @@ cleanup:
+
+ static int virNetTLSContextLoadCACertListFromFile(const char *certFile,
+ gnutls_x509_crt_t *certs,
++ unsigned int certMax,
+ size_t *ncerts)
+ {
+ gnutls_datum_t data;
+ char *buf = NULL;
+ int ret = -1;
+- unsigned int certMax = *ncerts;
+
+ *ncerts = 0;
+ VIR_DEBUG("certFile %s", certFile);
+@@ -584,15 +584,17 @@ static int virNetTLSContextSanityCheckCredentials(bool isServer,
+ {
+ gnutls_x509_crt_t cert = NULL;
+ gnutls_x509_crt_t cacerts[MAX_CERTS];
+- size_t ncacerts = MAX_CERTS;
++ size_t ncacerts = 0;
+ size_t i;
+ int ret = -1;
+
++ memset(cacerts, 0, sizeof(cacerts));
+ if ((access(certFile, R_OK) == 0) &&
+ !(cert = virNetTLSContextLoadCertFromFile(certFile, isServer)))
+ goto cleanup;
+ if ((access(cacertFile, R_OK) == 0) &&
+- virNetTLSContextLoadCACertListFromFile(cacertFile, cacerts, &ncacerts) < 0)
++ virNetTLSContextLoadCACertListFromFile(cacertFile, cacerts,
++ MAX_CERTS, &ncacerts) < 0)
+ goto cleanup;
+
+ if (cert &&
+--
+1.8.3.2
+
--- /dev/null
+From b1878a91f75a26f6c851106df6d83086fe213963 Mon Sep 17 00:00:00 2001
+Message-Id: <b1878a91f75a26f6c851106df6d83086fe213963.1383922565.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 4 Nov 2013 17:36:00 +0100
+Subject: [PATCH] virpci: Don't error on unbinded devices
+
+RHEL-7: https://bugzilla.redhat.com/show_bug.cgi?id=1019387
+UPSTREAM: https://bugzilla.redhat.com/show_bug.cgi?id=1018897
+
+If a PCI deivce is not binded to any driver (e.g. there's yet no PCI
+driver in the linux kernel) but still users want to passthru the device
+we fail the whole operation as we fail to resolve the 'driver' link
+under the PCI device sysfs tree. Obviously, this is not a fatal error
+and it shouldn't be error at all.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit df4283a55bf3516b333352e2052dbe3317936953)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virpci.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/src/util/virpci.c b/src/util/virpci.c
+index be50b4f..be95d03 100644
+--- a/src/util/virpci.c
++++ b/src/util/virpci.c
+@@ -1095,11 +1095,8 @@ virPCIDeviceBindToStub(virPCIDevicePtr dev,
+ const char *newDriverName = NULL;
+
+ if (virPCIDriverDir(&stubDriverPath, stubDriverName) < 0 ||
+- virPCIFile(&driverLink, dev->name, "driver") < 0 ||
+- virPCIDeviceGetDriverPathAndName(dev, &oldDriverPath,
+- &oldDriverName) < 0) {
++ virPCIFile(&driverLink, dev->name, "driver") < 0)
+ goto cleanup;
+- }
+
+ if (virFileExists(driverLink)) {
+ if (virFileLinkPointsTo(driverLink, stubDriverPath)) {
+--
+1.8.4.2
+
--- /dev/null
+From 48d8b3b8088178e6b77e40379facbfd23f3154e8 Mon Sep 17 00:00:00 2001
+Message-Id: <48d8b3b8088178e6b77e40379facbfd23f3154e8.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Wed, 21 Aug 2013 12:43:31 +0200
+Subject: [PATCH] virsh: Don't leak list of volumes when undefining domain with
+ storage
+
+https://bugzilla.redhat.com/show_bug.cgi?id=999057 [7.0]
+
+Use the new semantics of vshStringToArray to avoid leaking the array of
+volumes to be deleted. The array would be leaked in case the first
+volume was found in the domain definition. Also refactor the code a bit
+to sanitize naming of variables hoding arrays and dimensions of the
+arrays.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=996050 [6.6]
+(cherry picked from commit 04898f60d2b509c4d106bf7e1ee269acc240b93d)
+---
+ tools/virsh-domain.c | 134 +++++++++++++++++++++++++--------------------------
+ 1 file changed, 65 insertions(+), 69 deletions(-)
+
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index e2e4409..f35a3c5 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -2928,24 +2928,23 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+ int rc = -1;
+ int running;
+ /* list of volumes to remove along with this domain */
+- vshUndefineVolume *vlist = NULL;
+- int nvols = 0;
+- const char *volumes = NULL;
+- char **volume_tokens = NULL;
+- char *volume_tok = NULL;
+- int nvolume_tokens = 0;
+- char *def = NULL;
++ const char *vol_string = NULL; /* string containing volumes to delete */
++ char **vol_list = NULL; /* tokenized vol_string */
++ int nvol_list = 0;
++ vshUndefineVolume *vols = NULL; /* info about the volumes to delete*/
++ size_t nvols = 0;
++ char *def = NULL; /* domain def */
++ xmlDocPtr doc = NULL;
++ xmlXPathContextPtr ctxt = NULL;
++ xmlNodePtr *vol_nodes = NULL; /* XML nodes of volumes of the guest */
++ int nvol_nodes;
+ char *source = NULL;
+ char *target = NULL;
+ size_t i;
+ size_t j;
+- xmlDocPtr doc = NULL;
+- xmlXPathContextPtr ctxt = NULL;
+- xmlNodePtr *vol_nodes = NULL;
+- int nvolumes = 0;
+- bool vol_not_found = false;
+
+- ignore_value(vshCommandOptString(cmd, "storage", &volumes));
++
++ ignore_value(vshCommandOptString(cmd, "storage", &vol_string));
+
+ if (managed_save) {
+ flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE;
+@@ -3013,14 +3012,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+ }
+
+ /* Stash domain description for later use */
+- if (volumes || remove_all_storage) {
++ if (vol_string || remove_all_storage) {
+ if (running) {
+- vshError(ctl, _("Storage volume deletion is supported only on stopped domains"));
++ vshError(ctl,
++ _("Storage volume deletion is supported only on "
++ "stopped domains"));
+ goto cleanup;
+ }
+
+- if (volumes && remove_all_storage) {
+- vshError(ctl, _("Specified both --storage and --remove-all-storage"));
++ if (vol_string && remove_all_storage) {
++ vshError(ctl,
++ _("Specified both --storage and --remove-all-storage"));
+ goto cleanup;
+ }
+
+@@ -3034,20 +3036,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+ goto error;
+
+ /* tokenize the string from user and save it's parts into an array */
+- if (volumes) {
+- if ((nvolume_tokens = vshStringToArray(volumes, &volume_tokens)) < 0)
+- goto cleanup;
+- }
+-
+- if ((nvolumes = virXPathNodeSet("./devices/disk", ctxt,
+- &vol_nodes)) < 0)
++ if (vol_string &&
++ (nvol_list = vshStringToArray(vol_string, &vol_list)) < 0)
+ goto error;
+
+- if (nvolumes > 0)
+- vlist = vshCalloc(ctl, nvolumes, sizeof(*vlist));
++ if ((nvol_nodes = virXPathNodeSet("./devices/disk", ctxt,
++ &vol_nodes)) < 0)
++ goto error;
+
+- for (i = 0; i < nvolumes; i++) {
++ for (i = 0; i < nvol_nodes; i++) {
+ ctxt->node = vol_nodes[i];
++ vshUndefineVolume vol;
+ VIR_FREE(source);
+ VIR_FREE(target);
+
+@@ -3059,56 +3058,53 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+ "./source/@file|"
+ "./source/@dir|"
+ "./source/@name|"
+- "./source/@dev)", ctxt))) {
+- if (last_error && last_error->code != VIR_ERR_OK)
+- goto error;
+- else
+- continue;
+- }
++ "./source/@dev)", ctxt)))
++ continue;
+
+ /* lookup if volume was selected by user */
+- if (volumes) {
+- volume_tok = NULL;
+- for (j = 0; j < nvolume_tokens; j++) {
+- if (volume_tokens[j] &&
+- (STREQ(volume_tokens[j], target) ||
+- STREQ(volume_tokens[j], source))) {
+- volume_tok = volume_tokens[j];
+- volume_tokens[j] = NULL;
++ if (vol_list) {
++ bool found = false;
++ for (j = 0; j < nvol_list; j++) {
++ if (STREQ_NULLABLE(vol_list[j], target) ||
++ STREQ_NULLABLE(vol_list[j], source)) {
++ VIR_FREE(vol_list[j]);
++ found = true;
+ break;
+ }
+ }
+- if (!volume_tok)
++ if (!found)
+ continue;
+ }
+
+- if (!(vlist[nvols].vol = virStorageVolLookupByPath(ctl->conn,
+- source))) {
++ if (!(vol.vol = virStorageVolLookupByPath(ctl->conn, source))) {
+ vshPrint(ctl,
+ _("Storage volume '%s'(%s) is not managed by libvirt. "
+ "Remove it manually.\n"), target, source);
+ vshResetLibvirtError();
+ continue;
+ }
+- vlist[nvols].source = source;
+- vlist[nvols].target = target;
++
++ vol.source = source;
++ vol.target = target;
+ source = NULL;
+ target = NULL;
+- nvols++;
++ if (VIR_APPEND_ELEMENT(vols, nvols, vol) < 0)
++ goto cleanup;
+ }
+
+ /* print volumes specified by user that were not found in domain definition */
+- if (volumes) {
+- for (j = 0; j < nvolume_tokens; j++) {
+- if (volume_tokens[j]) {
+- vshError(ctl, _("Volume '%s' was not found in domain's "
+- "definition.\n"),
+- volume_tokens[j]);
+- vol_not_found = true;
++ if (vol_list) {
++ bool found = false;
++ for (i = 0; i < nvol_list; i++) {
++ if (vol_list[i]) {
++ vshError(ctl,
++ _("Volume '%s' was not found in domain's "
++ "definition.\n"), vol_list[i]);
++ found = true;
+ }
+ }
+
+- if (vol_not_found)
++ if (found)
+ goto cleanup;
+ }
+ }
+@@ -3169,9 +3165,9 @@ out:
+ for (i = 0; i < nvols; i++) {
+ if (wipe_storage) {
+ vshPrint(ctl, _("Wiping volume '%s'(%s) ... "),
+- vlist[i].target, vlist[i].source);
++ vols[i].target, vols[i].source);
+ fflush(stdout);
+- if (virStorageVolWipe(vlist[i].vol, 0) < 0) {
++ if (virStorageVolWipe(vols[i].vol, 0) < 0) {
+ vshError(ctl, _("Failed! Volume not removed."));
+ ret = false;
+ continue;
+@@ -3181,13 +3177,13 @@ out:
+ }
+
+ /* delete the volume */
+- if (virStorageVolDelete(vlist[i].vol, 0) < 0) {
++ if (virStorageVolDelete(vols[i].vol, 0) < 0) {
+ vshError(ctl, _("Failed to remove storage volume '%s'(%s)"),
+- vlist[i].target, vlist[i].source);
++ vols[i].target, vols[i].source);
+ ret = false;
+ } else {
+ vshPrint(ctl, _("Volume '%s'(%s) removed.\n"),
+- vlist[i].target, vlist[i].source);
++ vols[i].target, vols[i].source);
+ }
+ }
+ }
+@@ -3196,17 +3192,17 @@ cleanup:
+ VIR_FREE(source);
+ VIR_FREE(target);
+ for (i = 0; i < nvols; i++) {
+- VIR_FREE(vlist[i].source);
+- VIR_FREE(vlist[i].target);
+- if (vlist[i].vol)
+- virStorageVolFree(vlist[i].vol);
++ VIR_FREE(vols[i].source);
++ VIR_FREE(vols[i].target);
++ if (vols[i].vol)
++ virStorageVolFree(vols[i].vol);
+ }
+- VIR_FREE(vlist);
++ VIR_FREE(vols);
++
++ for (i = 0; i < nvol_list; i++)
++ VIR_FREE(vol_list[i]);
++ VIR_FREE(vol_list);
+
+- if (volume_tokens) {
+- VIR_FREE(*volume_tokens);
+- VIR_FREE(volume_tokens);
+- }
+ VIR_FREE(def);
+ VIR_FREE(vol_nodes);
+ xmlFreeDoc(doc);
+--
+1.8.3.2
+
--- /dev/null
+From f307877d3c0c1bac66d4039dc6b50c67b73d23dd Mon Sep 17 00:00:00 2001
+Message-Id: <f307877d3c0c1bac66d4039dc6b50c67b73d23dd.1377873641.git.jdenemar@redhat.com>
+From: Martin Kletzander <mkletzan@redhat.com>
+Date: Wed, 28 Aug 2013 11:18:01 +0200
+Subject: [PATCH] virsh: Fix debugging
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001628
+
+Commit a0b6a36f "fixed" what abfff210 broke (URI precedence), but
+there was still one more thing missing to fix. When using virsh
+parameters to setup debugging, those weren't honored, because at the
+time debugging was initializing, arguments weren't parsed yet. To
+make ewerything work as expected, we need to initialize the debugging
+twice, once before debugging (so we can debug option parsing properly)
+and then again after these options are parsed.
+
+As a side effect, this patch also fixes a leak when virsh is ran with
+multiple '-l' parameters.
+
+Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit ac43da705f0e7c23dffd87c0705ff01711b88ac0)
+---
+ tools/virsh.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/tools/virsh.c b/tools/virsh.c
+index 2ea44a6..34f5c4a 100644
+--- a/tools/virsh.c
++++ b/tools/virsh.c
+@@ -2321,10 +2321,9 @@ vshInitDebug(vshControl *ctl)
+ debugEnv = getenv("VIRSH_LOG_FILE");
+ if (debugEnv && *debugEnv) {
+ ctl->logfile = vshStrdup(ctl, debugEnv);
++ vshOpenLogFile(ctl);
+ }
+ }
+-
+- vshOpenLogFile(ctl);
+ }
+
+ /*
+@@ -2333,6 +2332,10 @@ vshInitDebug(vshControl *ctl)
+ static bool
+ vshInit(vshControl *ctl)
+ {
++ /* Since we have the commandline arguments parsed, we need to
++ * re-initialize all the debugging to make it work properly */
++ vshInitDebug(ctl);
++
+ if (ctl->conn)
+ return false;
+
+@@ -3040,7 +3043,9 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
+ ctl->readonly = true;
+ break;
+ case 'l':
++ vshCloseLogFile(ctl);
+ ctl->logfile = vshStrdup(ctl, optarg);
++ vshOpenLogFile(ctl);
+ break;
+ case 'e':
+ len = strlen(optarg);
+--
+1.8.3.2
+
--- /dev/null
+From e387f0a8337a7a9acb0aec433f1f90a1c4cdeb80 Mon Sep 17 00:00:00 2001
+Message-Id: <e387f0a8337a7a9acb0aec433f1f90a1c4cdeb80.1377873641.git.jdenemar@redhat.com>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 22 Aug 2013 16:56:23 -0400
+Subject: [PATCH] virsh: Print cephx and iscsi usage
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1000155
+
+When using virsh secret-list - if the secret types are cephx or iscsi,
+then allow fetch/print of the usage information. Prior to the change
+the following would print:
+
+UUID Usage
+-----------------------------------------------------------
+1b40a534-8301-45d5-b1aa-11894ebb1735 Unused
+a5ba3efe-6adf-4a6a-b243-f010a043e314 Unused
+
+Afterwards:
+
+UUID Usage
+-----------------------------------------------------------
+1b40a534-8301-45d5-b1aa-11894ebb1735 ceph ceph_example
+a5ba3efe-6adf-4a6a-b243-f010a043e314 iscsi libvirtiscsi
+
+(cherry picked from commit db1382f322841a7f8c877151644f49c147664fec)
+---
+ tools/virsh-secret.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c
+index c4763e3..e849a79 100644
+--- a/tools/virsh-secret.c
++++ b/tools/virsh-secret.c
+@@ -38,6 +38,7 @@
+ #include "virfile.h"
+ #include "virutil.h"
+ #include "virxml.h"
++#include "conf/secret_conf.h"
+
+ static virSecretPtr
+ vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name)
+@@ -536,15 +537,10 @@ cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+
+ for (i = 0; i < list->nsecrets; i++) {
+ virSecretPtr sec = list->secrets[i];
+- const char *usageType = NULL;
+-
+- switch (virSecretGetUsageType(sec)) {
+- case VIR_SECRET_USAGE_TYPE_VOLUME:
+- usageType = _("Volume");
+- break;
+- }
+-
++ int usageType = virSecretGetUsageType(sec);
++ const char *usageStr = virSecretUsageTypeTypeToString(usageType);
+ char uuid[VIR_UUID_STRING_BUFLEN];
++
+ if (virSecretGetUUIDString(list->secrets[i], uuid) < 0) {
+ vshError(ctl, "%s", _("Failed to get uuid of secret"));
+ goto cleanup;
+@@ -552,7 +548,7 @@ cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+
+ if (usageType) {
+ vshPrint(ctl, "%-36s %s %s\n",
+- uuid, usageType,
++ uuid, usageStr,
+ virSecretGetUsageID(sec));
+ } else {
+ vshPrint(ctl, "%-36s %s\n",
+--
+1.8.3.2
+
--- /dev/null
+From 6fe13c7752108ab069441129901249a792aa62f4 Mon Sep 17 00:00:00 2001
+Message-Id: <6fe13c7752108ab069441129901249a792aa62f4.1377873639.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 16 Aug 2013 10:44:51 +0200
+Subject: [PATCH] virsh-domain: Fix memleak in cmdCPUBaseline
+
+https://bugzilla.redhat.com/show_bug.cgi?id=997798 [7.0]
+https://bugzilla.redhat.com/show_bug.cgi?id=997765 [6.6]
+
+==1349431== 8 bytes in 1 blocks are definitely lost in loss record 11 of 760
+==1349431== at 0x4C2A554: calloc (vg_replace_malloc.c:593)
+==1349431== by 0x4E9AA3E: virAllocN (in /usr/lib64/libvirt.so.0.1001.1)
+==1349431== by 0x4EF28C4: virXPathNodeSet (in /usr/lib64/libvirt.so.0.1001.1)
+==1349431== by 0x130B83: cmdCPUBaseline (in /usr/bin/virsh)
+==1349431== by 0x12C608: vshCommandRun (in /usr/bin/virsh)
+==1349431== by 0x12889A: main (in /usr/bin/virsh)
+
+(cherry picked from commit f4ec8616410cea2b7dbe4c535c81cf70162a2939)
+---
+ tools/virsh-domain.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index 31db8fe..2134e57 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -6228,6 +6228,7 @@ cleanup:
+ }
+ VIR_FREE(list);
+ VIR_FREE(buffer);
++ VIR_FREE(node_list);
+
+ return ret;
+
+--
+1.8.3.2
+
--- /dev/null
+From c19ba72c3346f46ba9cd59e573d87aa854869798 Mon Sep 17 00:00:00 2001
+Message-Id: <c19ba72c3346f46ba9cd59e573d87aa854869798.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Wed, 21 Aug 2013 12:43:29 +0200
+Subject: [PATCH] virsh-domain: Fix memleak in cmdUndefine with storage
+
+https://bugzilla.redhat.com/show_bug.cgi?id=999057 [7.0]
+
+When undefining a domain with storage when the volume isn't managed by
+libvirt the name and path strings weren't freed properly.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=996050 [6.6]
+(cherry picked from commit 5075248ac9e60dd73da3487f83be9aa188200688)
+---
+ tools/virsh-domain.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index 2134e57..e2e4409 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -3048,6 +3048,8 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+
+ for (i = 0; i < nvolumes; i++) {
+ ctxt->node = vol_nodes[i];
++ VIR_FREE(source);
++ VIR_FREE(target);
+
+ /* get volume source and target paths */
+ if (!(target = virXPathString("string(./target/@dev)", ctxt)))
+@@ -3090,6 +3092,8 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
+ }
+ vlist[nvols].source = source;
+ vlist[nvols].target = target;
++ source = NULL;
++ target = NULL;
+ nvols++;
+ }
+
+@@ -3189,6 +3193,8 @@ out:
+ }
+
+ cleanup:
++ VIR_FREE(source);
++ VIR_FREE(target);
+ for (i = 0; i < nvols; i++) {
+ VIR_FREE(vlist[i].source);
+ VIR_FREE(vlist[i].target);
+--
+1.8.3.2
+
--- /dev/null
+From 7898ba7927e2aae5c3c6e59c6a7c0fc1672a6e02 Mon Sep 17 00:00:00 2001
+Message-Id: <7898ba7927e2aae5c3c6e59c6a7c0fc1672a6e02.1377873638.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 13 Aug 2013 14:46:14 +0200
+Subject: [PATCH] virsh-domain: Flip logic in cmdSetvcpus
+
+To avoid having to assign a failure code to the returned variable switch
+this function to negative logic. This will fix issue with invalid number
+of cpus returning success return code.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=996552 [7.0]
+https://bugzilla.redhat.com/show_bug.cgi?id=996466 [6.6]
+(cherry picked from commit 3abb6ec077f7fdc9ac9969b5c33f2c2d270903f3)
+---
+ tools/virsh-domain.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index 8cafce4..31db8fe 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -5961,7 +5961,7 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
+ {
+ virDomainPtr dom;
+ int count = 0;
+- bool ret = true;
++ bool ret = false;
+ bool maximum = vshCommandOptBool(cmd, "maximum");
+ bool config = vshCommandOptBool(cmd, "config");
+ bool live = vshCommandOptBool(cmd, "live");
+@@ -5992,9 +5992,8 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
+ }
+
+ if (flags == -1) {
+- if (virDomainSetVcpus(dom, count) != 0) {
+- ret = false;
+- }
++ if (virDomainSetVcpus(dom, count) != 0)
++ goto cleanup;
+ } else {
+ /* If the --maximum flag was given, we need to ensure only the
+ --config flag is in effect as well */
+@@ -6011,18 +6010,18 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
+
+ /* Warn the user about the invalid flag combination */
+ vshError(ctl, _("--maximum must be used with --config only"));
+- ret = false;
+ goto cleanup;
+ }
+ }
+
+ /* Apply the virtual cpu changes */
+- if (virDomainSetVcpusFlags(dom, count, flags) < 0) {
+- ret = false;
+- }
++ if (virDomainSetVcpusFlags(dom, count, flags) < 0)
++ goto cleanup;
+ }
+
+- cleanup:
++ ret = true;
++
++cleanup:
+ virDomainFree(dom);
+ return ret;
+ }
+--
+1.8.3.2
+
--- /dev/null
+From 8cb402b248c072f5a9e440e33fae60bd77d06a69 Mon Sep 17 00:00:00 2001
+Message-Id: <8cb402b248c072f5a9e440e33fae60bd77d06a69.1379193140.git.jdenemar@redhat.com>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 11 Sep 2013 15:49:48 +0200
+Subject: [PATCH] virsh domjobinfo: Do not return 1 if job is NONE
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1006864
+
+Commit 38ab1225 changed the default value of ret from true to false but
+forgot to set ret = true when job is NONE. Thus, virsh domjobinfo
+returned 1 when there was no job running for a domain but it used to
+(and should) return 0 in this case.
+
+(cherry picked from commit f084caae7c5db8ae03e7fafce164c73f65681843)
+---
+ tools/virsh-domain.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
+index f35a3c5..bf5f425 100644
+--- a/tools/virsh-domain.c
++++ b/tools/virsh-domain.c
+@@ -4995,6 +4995,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd)
+ case VIR_DOMAIN_JOB_NONE:
+ default:
+ vshPrint(ctl, "%-12s\n", _("None"));
++ ret = true;
+ goto cleanup;
+ }
+
+--
+1.8.3.2
+
--- /dev/null
+From 8a44f62f8d1858ebab7f2bbb890d5f3eb2d2b316 Mon Sep 17 00:00:00 2001
+Message-Id: <8a44f62f8d1858ebab7f2bbb890d5f3eb2d2b316.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 28 Aug 2013 10:24:13 +0200
+Subject: [PATCH] virsh: free messages after logging them to a file
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001957
+
+The messages were only freed on error.
+
+==12== 1,100 bytes in 1 blocks are definitely lost in loss record 698 of 729
+==12== by 0x4E98C22: virBufferAsprintf (virbuffer.c:294)
+==12== by 0x12C950: vshOutputLogFile (virsh.c:2440)
+==12== by 0x12880B: vshError (virsh.c:2254)
+==12== by 0x131957: vshCommandOptDomainBy (virsh-domain.c:109)
+==12== by 0x14253E: cmdStart (virsh-domain.c:3333)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001536
+(cherry picked from commit 66d124b45472addc10d286ca291aa5411fcb381f)
+---
+ tools/virsh.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virsh.c b/tools/virsh.c
+index 34f5c4a..d1ae183 100644
+--- a/tools/virsh.c
++++ b/tools/virsh.c
+@@ -2479,6 +2479,7 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
+ if (safewrite(ctl->log_fd, str, len) < 0)
+ goto error;
+
++ VIR_FREE(str);
+ return;
+
+ error:
+--
+1.8.3.2
+
--- /dev/null
+From a2d2939673d2e77d1297ae054795fd337dd0a95f Mon Sep 17 00:00:00 2001
+Message-Id: <a2d2939673d2e77d1297ae054795fd337dd0a95f.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 28 Aug 2013 10:24:09 +0200
+Subject: [PATCH] virsh: free the caps list properly if one of them is invalid
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001957
+
+VIR_FREE(caps) is not enough to free an array allocated
+by vshStringToArray.
+
+==17== 4 bytes in 1 blocks are definitely lost in loss record 4 of 728
+==17== by 0x4EFFC44: virStrdup (virstring.c:554)
+==17== by 0x128B10: _vshStrdup (virsh.c:125)
+==17== by 0x129164: vshStringToArray (virsh.c:218)
+==17== by 0x157BB3: cmdNodeListDevices (virsh-nodedev.c:409)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001536
+(cherry picked from commit 14d5328681448267dfc0812948fa2c6ec4dfa7d4)
+---
+ tools/virsh-nodedev.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
+index 5522405..92ef40c 100644
+--- a/tools/virsh-nodedev.c
++++ b/tools/virsh-nodedev.c
+@@ -413,8 +413,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ for (i = 0; i < ncaps; i++) {
+ if ((cap_type = virNodeDevCapTypeFromString(caps[i])) < 0) {
+ vshError(ctl, "%s", _("Invalid capability type"));
+- VIR_FREE(caps);
+- return false;
++ ret = false;
++ goto cleanup;
+ }
+
+ switch (cap_type) {
+--
+1.8.3.2
+
--- /dev/null
+From f972546d4131686a85f5d124e9feec49b77419c1 Mon Sep 17 00:00:00 2001
+Message-Id: <f972546d4131686a85f5d124e9feec49b77419c1.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 28 Aug 2013 10:24:10 +0200
+Subject: [PATCH] virsh: free the formatting string when listing pool details
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001957
+
+==23== 41 bytes in 1 blocks are definitely lost in loss record 626 of 727
+==23== by 0x4F0099F: virAsprintfInternal (virstring.c:358)
+==23== by 0x15D2C9: cmdPoolList (virsh-pool.c:1268)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001536
+(cherry picked from commit 785ff34bf884a721544ea531c000e8a140e485fa)
+---
+ tools/virsh-pool.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
+index b8fc8d7..e31e76c 100644
+--- a/tools/virsh-pool.c
++++ b/tools/virsh-pool.c
+@@ -1264,7 +1264,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ /* Create the output template. Each column is sized according to
+ * the longest string.
+ */
+- char *outputStr;
++ char *outputStr = NULL;
+ ret = virAsprintf(&outputStr,
+ "%%-%lus %%-%lus %%-%lus %%-%lus %%%lus %%%lus %%%lus\n",
+ (unsigned long) nameStrLength,
+@@ -1319,6 +1319,7 @@ asprintf_failure:
+ functionReturn = false;
+
+ cleanup:
++ VIR_FREE(outputStr);
+ if (list && list->npools) {
+ for (i = 0; i < list->npools; i++) {
+ VIR_FREE(poolInfoTexts[i].state);
+--
+1.8.3.2
+
--- /dev/null
+From 8a150535474e22c35508b075212b91478ba06de0 Mon Sep 17 00:00:00 2001
+Message-Id: <8a150535474e22c35508b075212b91478ba06de0.1377873641.git.jdenemar@redhat.com>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Wed, 28 Aug 2013 10:24:12 +0200
+Subject: [PATCH] virsh: free the list from ListAll APIs even for 0 items
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001957
+
+virsh secret-list leak when no secrets are defined:
+
+==27== 8 bytes in 1 blocks are definitely lost in loss record 6 of 726
+==27== by 0x4E941DD: virAllocN (viralloc.c:183)
+==27== by 0x5037F1A: remoteConnectListAllSecrets (remote_driver.c:3076)
+==27== by 0x5004EC6: virConnectListAllSecrets (libvirt.c:16298)
+==27== by 0x15F813: vshSecretListCollect (virsh-secret.c:397)
+==27== by 0x15F0E1: cmdSecretList (virsh-secret.c:532)
+
+And so do some other *-list commands.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001536
+(cherry picked from commit f733eac058b373822708d3ec889dd80e281fa7e1)
+---
+ tools/virsh-interface.c | 2 +-
+ tools/virsh-network.c | 2 +-
+ tools/virsh-nodedev.c | 2 +-
+ tools/virsh-nwfilter.c | 2 +-
+ tools/virsh-secret.c | 2 +-
+ 5 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c
+index 0f78551..3720c8c 100644
+--- a/tools/virsh-interface.c
++++ b/tools/virsh-interface.c
+@@ -174,7 +174,7 @@ vshInterfaceListFree(vshInterfaceListPtr list)
+ {
+ size_t i;
+
+- if (list && list->nifaces) {
++ if (list && list->ifaces) {
+ for (i = 0; i < list->nifaces; i++) {
+ if (list->ifaces[i])
+ virInterfaceFree(list->ifaces[i]);
+diff --git a/tools/virsh-network.c b/tools/virsh-network.c
+index 06bf483..8ddd5ca 100644
+--- a/tools/virsh-network.c
++++ b/tools/virsh-network.c
+@@ -423,7 +423,7 @@ vshNetworkListFree(vshNetworkListPtr list)
+ {
+ size_t i;
+
+- if (list && list->nnets) {
++ if (list && list->nets) {
+ for (i = 0; i < list->nnets; i++) {
+ if (list->nets[i])
+ virNetworkFree(list->nets[i]);
+diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
+index 92ef40c..3a2d12b 100644
+--- a/tools/virsh-nodedev.c
++++ b/tools/virsh-nodedev.c
+@@ -207,7 +207,7 @@ vshNodeDeviceListFree(vshNodeDeviceListPtr list)
+ {
+ size_t i;
+
+- if (list && list->ndevices) {
++ if (list && list->devices) {
+ for (i = 0; i < list->ndevices; i++) {
+ if (list->devices[i])
+ virNodeDeviceFree(list->devices[i]);
+diff --git a/tools/virsh-nwfilter.c b/tools/virsh-nwfilter.c
+index fbf211a..e5fcb8f 100644
+--- a/tools/virsh-nwfilter.c
++++ b/tools/virsh-nwfilter.c
+@@ -242,7 +242,7 @@ vshNWFilterListFree(vshNWFilterListPtr list)
+ {
+ size_t i;
+
+- if (list && list->nfilters) {
++ if (list && list->filters) {
+ for (i = 0; i < list->nfilters; i++) {
+ if (list->filters[i])
+ virNWFilterFree(list->filters[i]);
+diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c
+index 9d34c1a..c4763e3 100644
+--- a/tools/virsh-secret.c
++++ b/tools/virsh-secret.c
+@@ -369,7 +369,7 @@ vshSecretListFree(vshSecretListPtr list)
+ {
+ size_t i;
+
+- if (list && list->nsecrets) {
++ if (list && list->secrets) {
+ for (i = 0; i < list->nsecrets; i++) {
+ if (list->secrets[i])
+ virSecretFree(list->secrets[i]);
+--
+1.8.3.2
+
--- /dev/null
+From be34cccbd2e9ca0e756c8e40c34d01474e138c31 Mon Sep 17 00:00:00 2001
+Message-Id: <be34cccbd2e9ca0e756c8e40c34d01474e138c31.1377873640.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Wed, 21 Aug 2013 12:43:30 +0200
+Subject: [PATCH] virsh: modify vshStringToArray to duplicate the elements too
+
+https://bugzilla.redhat.com/show_bug.cgi?id=999057
+
+At a slightly larger memory expense allow stealing of items from the
+string array returned from vshStringToArray and turn the result into a
+string list compatible with virStringSplit. This will allow to use the
+common dealloc function.
+
+This patch also fixes a few forgotten checks of return from
+vshStringToArray and one memory leak.
+
+(cherry picked from commit d64af6ce3cce0d353238086c4e1ec0fd59217cf0)
+---
+ tools/virsh-nodedev.c | 18 +++++-------------
+ tools/virsh-pool.c | 10 ++++------
+ tools/virsh-snapshot.c | 10 ++--------
+ tools/virsh.c | 15 ++++++++-------
+ tools/virsh.h | 1 +
+ 5 files changed, 20 insertions(+), 34 deletions(-)
+
+diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
+index 3255079..5522405 100644
+--- a/tools/virsh-nodedev.c
++++ b/tools/virsh-nodedev.c
+@@ -161,10 +161,7 @@ cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd)
+
+ ret = true;
+ cleanup:
+- if (arr) {
+- VIR_FREE(*arr);
+- VIR_FREE(arr);
+- }
++ virStringFreeList(arr);
+ virNodeDeviceFree(dev);
+ return ret;
+ }
+@@ -409,7 +406,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ vshError(ctl, "%s", _("Options --tree and --cap are incompatible"));
+ return false;
+ }
+- ncaps = vshStringToArray(cap_str, &caps);
++ if ((ncaps = vshStringToArray(cap_str, &caps)) < 0)
++ return false;
+ }
+
+ for (i = 0; i < ncaps; i++) {
+@@ -503,10 +501,7 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ }
+
+ cleanup:
+- if (caps) {
+- VIR_FREE(*caps);
+- VIR_FREE(caps);
+- }
++ virStringFreeList(caps);
+ vshNodeDeviceListFree(list);
+ return ret;
+ }
+@@ -574,10 +569,7 @@ cmdNodeDeviceDumpXML(vshControl *ctl, const vshCmd *cmd)
+
+ ret = true;
+ cleanup:
+- if (arr) {
+- VIR_FREE(*arr);
+- VIR_FREE(arr);
+- }
++ virStringFreeList(arr);
+ VIR_FREE(xml);
+ virNodeDeviceFree(device);
+ return ret;
+diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
+index 1622be2..b8fc8d7 100644
+--- a/tools/virsh-pool.c
++++ b/tools/virsh-pool.c
+@@ -995,12 +995,13 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ char **poolTypes = NULL;
+ int npoolTypes = 0;
+
+- npoolTypes = vshStringToArray(type, &poolTypes);
++ if ((npoolTypes = vshStringToArray(type, &poolTypes)) < 0)
++ return false;
+
+ for (i = 0; i < npoolTypes; i++) {
+ if ((poolType = virStoragePoolTypeFromString(poolTypes[i])) < 0) {
+ vshError(ctl, "%s", _("Invalid pool type"));
+- VIR_FREE(poolTypes);
++ virStringFreeList(poolTypes);
+ return false;
+ }
+
+@@ -1036,10 +1037,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ break;
+ }
+ }
+- if (poolTypes) {
+- VIR_FREE(*poolTypes);
+- VIR_FREE(poolTypes);
+- }
++ virStringFreeList(poolTypes);
+ }
+
+ if (!(list = vshStoragePoolListCollect(ctl, flags)))
+diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
+index db9715b..e37a5b3 100644
+--- a/tools/virsh-snapshot.c
++++ b/tools/virsh-snapshot.c
+@@ -261,10 +261,7 @@ vshParseSnapshotMemspec(vshControl *ctl, virBufferPtr buf, const char *str)
+ cleanup:
+ if (ret < 0)
+ vshError(ctl, _("unable to parse memspec: %s"), str);
+- if (array) {
+- VIR_FREE(*array);
+- VIR_FREE(array);
+- }
++ virStringFreeList(array);
+ return ret;
+ }
+
+@@ -313,10 +310,7 @@ vshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const char *str)
+ cleanup:
+ if (ret < 0)
+ vshError(ctl, _("unable to parse diskspec: %s"), str);
+- if (array) {
+- VIR_FREE(*array);
+- VIR_FREE(array);
+- }
++ virStringFreeList(array);
+ return ret;
+ }
+
+diff --git a/tools/virsh.c b/tools/virsh.c
+index f65dc79..15f529e 100644
+--- a/tools/virsh.c
++++ b/tools/virsh.c
+@@ -163,10 +163,9 @@ vshPrettyCapacity(unsigned long long val, const char **unit)
+ }
+
+ /*
+- * Convert the strings separated by ',' into array. The caller
+- * must free the first array element and the returned array after
+- * use (all other array elements belong to the memory allocated
+- * for the first array element).
++ * Convert the strings separated by ',' into array. The returned
++ * array is a NULL terminated string list. The caller has to free
++ * the array using virStringFreeList or a similar method.
+ *
+ * Returns the length of the filled array on success, or -1
+ * on error.
+@@ -196,7 +195,8 @@ vshStringToArray(const char *str,
+ str_tok++;
+ }
+
+- if (VIR_ALLOC_N(arr, nstr_tokens) < 0) {
++ /* reserve the NULL element at the end */
++ if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) {
+ VIR_FREE(str_copied);
+ return -1;
+ }
+@@ -212,12 +212,13 @@ vshStringToArray(const char *str,
+ continue;
+ }
+ *tmp++ = '\0';
+- arr[nstr_tokens++] = str_tok;
++ arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
+ str_tok = tmp;
+ }
+- arr[nstr_tokens++] = str_tok;
++ arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
+
+ *array = arr;
++ VIR_FREE(str_copied);
+ return nstr_tokens;
+ }
+
+diff --git a/tools/virsh.h b/tools/virsh.h
+index a407428..466ca2d 100644
+--- a/tools/virsh.h
++++ b/tools/virsh.h
+@@ -37,6 +37,7 @@
+ # include "virerror.h"
+ # include "virthread.h"
+ # include "virnetdevbandwidth.h"
++# include "virstring.h"
+
+ # define VSH_MAX_XML_FILE (10*1024*1024)
+
+--
+1.8.3.2
+
--- /dev/null
+From 77e8976b4c8127438dc0351dbaad8f762ec899cb Mon Sep 17 00:00:00 2001
+Message-Id: <77e8976b4c8127438dc0351dbaad8f762ec899cb.1377873641.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 28 Aug 2013 10:24:11 +0200
+Subject: [PATCH] virsh-pool.c: Don't jump over variable declaration
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1001957
+
+Since 785ff34bf8 we are using the outputStr variable in cleanup label.
+However, there is a possibility to jump to the label before the variable
+has been declared:
+
+virsh-pool.c: In function 'cmdPoolList':
+virsh-pool.c:1121:25: error: jump skips variable initialization [-Werror=jump-misses-init]
+ goto asprintf_failure;
+ ^
+virsh-pool.c:1308:1: note: label 'asprintf_failure' defined here
+ asprintf_failure:
+ ^
+virsh-pool.c:1267:11: note: 'outputStr' declared here
+ char *outputStr = NULL;
+(cherry picked from commit 2ab0948d0c7034dbb3ee00e41cb497c03d0d2c66)
+---
+ tools/virsh-pool.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
+index e31e76c..e52d676 100644
+--- a/tools/virsh-pool.c
++++ b/tools/virsh-pool.c
+@@ -964,6 +964,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ const char *type = NULL;
+ bool details = vshCommandOptBool(cmd, "details");
+ bool inactive, all;
++ char *outputStr = NULL;
+
+ inactive = vshCommandOptBool(cmd, "inactive");
+ all = vshCommandOptBool(cmd, "all");
+@@ -1264,7 +1265,6 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+ /* Create the output template. Each column is sized according to
+ * the longest string.
+ */
+- char *outputStr = NULL;
+ ret = virAsprintf(&outputStr,
+ "%%-%lus %%-%lus %%-%lus %%-%lus %%%lus %%%lus %%%lus\n",
+ (unsigned long) nameStrLength,
+--
+1.8.3.2
+
--- /dev/null
+From 6d4ec90d10bff86d33343551fc99be3fa15189a5 Mon Sep 17 00:00:00 2001
+Message-Id: <6d4ec90d10bff86d33343551fc99be3fa15189a5.1382534061.git.jdenemar@redhat.com>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 11 Oct 2013 11:24:34 +0200
+Subject: [PATCH] virsocket: Introduce virSocketAddrIsWildcard
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1015215
+
+This function takes exactly one argument: an address to check.
+It returns true, if the address is an IPv4 or IPv6 address in numeric
+format, false otherwise (e.g. for "examplehost").
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 1f9546e365e8beab1a4b681cc34105e0ac74be70)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libvirt_private.syms | 1 +
+ src/util/virsocketaddr.c | 72 +++++++++++++++++++++++++++++++++++++-----------
+ src/util/virsocketaddr.h | 2 ++
+ tests/sockettest.c | 29 +++++++++++++++++++
+ 4 files changed, 88 insertions(+), 16 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 9a00dfe..f96f126 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1874,6 +1874,7 @@ virSocketAddrGetIpPrefix;
+ virSocketAddrGetPort;
+ virSocketAddrGetRange;
+ virSocketAddrIsNetmask;
++virSocketAddrIsNumeric;
+ virSocketAddrIsPrivate;
+ virSocketAddrIsWildcard;
+ virSocketAddrMask;
+diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
+index 3e01baf..6df9205 100644
+--- a/src/util/virsocketaddr.c
++++ b/src/util/virsocketaddr.c
+@@ -71,6 +71,35 @@ static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr, virSocketAddrIPv6Ptr
+ return 0;
+ }
+
++static int
++virSocketAddrParseInternal(struct addrinfo **res,
++ const char *val,
++ int family,
++ bool reportError)
++{
++ struct addrinfo hints;
++ int err;
++
++ if (val == NULL) {
++ virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address"));
++ return -1;
++ }
++
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = family;
++ hints.ai_flags = AI_NUMERICHOST;
++ if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) {
++ if (reportError)
++ virReportError(VIR_ERR_SYSTEM_ERROR,
++ _("Cannot parse socket address '%s': %s"),
++ val, gai_strerror(err));
++
++ return -1;
++ }
++
++ return 0;
++}
++
+ /**
+ * virSocketAddrParse:
+ * @val: a numeric network address IPv4 or IPv6
+@@ -84,24 +113,10 @@ static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr, virSocketAddrIPv6Ptr
+ */
+ int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) {
+ int len;
+- struct addrinfo hints;
+- struct addrinfo *res = NULL;
+- int err;
++ struct addrinfo *res;
+
+- if (val == NULL) {
+- virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address"));
++ if (virSocketAddrParseInternal(&res, val, family, true) < 0)
+ return -1;
+- }
+-
+- memset(&hints, 0, sizeof(hints));
+- hints.ai_family = family;
+- hints.ai_flags = AI_NUMERICHOST;
+- if ((err = getaddrinfo(val, NULL, &hints, &res)) != 0) {
+- virReportError(VIR_ERR_SYSTEM_ERROR,
+- _("Cannot parse socket address '%s': %s"),
+- val, gai_strerror(err));
+- return -1;
+- }
+
+ if (res == NULL) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+@@ -824,3 +839,28 @@ virSocketAddrGetIpPrefix(const virSocketAddrPtr address,
+ */
+ return 0;
+ }
++
++/**
++ * virSocketAddrIsNumeric:
++ * @address: address to check
++ *
++ * Check if passed address is an IP address in numeric format. For
++ * instance, for 0.0.0.0 true is returned, for 'examplehost"
++ * false is returned.
++ *
++ * Returns: true if @address is an IP address,
++ * false otherwise
++ */
++bool
++virSocketAddrIsNumeric(const char *address)
++{
++ struct addrinfo *res;
++ unsigned short family;
++
++ if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, false) < 0)
++ return false;
++
++ family = res->ai_addr->sa_family;
++ freeaddrinfo(res);
++ return family == AF_INET || family == AF_INET6;
++}
+diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h
+index b28fe6c..d844914 100644
+--- a/src/util/virsocketaddr.h
++++ b/src/util/virsocketaddr.h
+@@ -124,4 +124,6 @@ bool virSocketAddrEqual(const virSocketAddrPtr s1,
+ bool virSocketAddrIsPrivate(const virSocketAddrPtr addr);
+
+ bool virSocketAddrIsWildcard(const virSocketAddrPtr addr);
++
++bool virSocketAddrIsNumeric(const char *address);
+ #endif /* __VIR_SOCKETADDR_H__ */
+diff --git a/tests/sockettest.c b/tests/sockettest.c
+index 092de88..5dcf636 100644
+--- a/tests/sockettest.c
++++ b/tests/sockettest.c
+@@ -180,6 +180,21 @@ static int testWildcardHelper(const void *opaque)
+ return testWildcard(data->addr, data->pass);
+ }
+
++struct testIsNumericData {
++ const char *addr;
++ bool pass;
++};
++
++static int
++testIsNumericHelper(const void *opaque)
++{
++ const struct testIsNumericData *data = opaque;
++
++ if (virSocketAddrIsNumeric(data->addr))
++ return data->pass ? 0 : -1;
++ return data->pass ? -1 : 0;
++}
++
+ static int
+ mymain(void)
+ {
+@@ -253,6 +268,14 @@ mymain(void)
+ ret = -1; \
+ } while (0)
+
++#define DO_TEST_IS_NUMERIC(addr, pass) \
++ do { \
++ struct testIsNumericData data = { addr, pass}; \
++ if (virtTestRun("Test isNumeric " addr, 1, \
++ testIsNumericHelper, &data) < 0) \
++ ret = -1; \
++ } while (0)
++
+
+ DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_UNSPEC, true);
+ DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_INET, true);
+@@ -314,6 +337,12 @@ mymain(void)
+ DO_TEST_WILDCARD("1", false);
+ DO_TEST_WILDCARD("0.1", false);
+
++ DO_TEST_IS_NUMERIC("0.0.0.0", true);
++ DO_TEST_IS_NUMERIC("::", true);
++ DO_TEST_IS_NUMERIC("1", true);
++ DO_TEST_IS_NUMERIC("::ffff", true);
++ DO_TEST_IS_NUMERIC("examplehost", false);
++
+ return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+--
+1.8.4
+
--- /dev/null
+From fb07bc1b5ac1e2cf3f0695de658e64ee79e84d54 Mon Sep 17 00:00:00 2001
+Message-Id: <fb07bc1b5ac1e2cf3f0695de658e64ee79e84d54.1381871412.git.jdenemar@redhat.com>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Mon, 14 Oct 2013 16:45:12 +0100
+Subject: [PATCH] virsystemd: Don't fail to start VM if DBus isn't available or
+ compiled in
+
+For
+
+ https://bugzilla.redhat.com/show_bug.cgi?id=1018730
+
+On hosts that don't have the DBus service running or installed the new
+systemd cgroups code failed with hard error instead of falling back to
+"manual" cgroup creation.
+
+Use the new helper to check for the system bus and use the fallback code
+in case it isn't available.
+
+(cherry picked from commit ee3db56fe9d47f547c07e7e0f6475e7f7a0eea7f)
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virsystemd.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
+index d0063a1..13370b5 100644
+--- a/src/util/virsystemd.c
++++ b/src/util/virsystemd.c
+@@ -145,8 +145,10 @@ int virSystemdCreateMachine(const char *name,
+ char *username = NULL;
+ char *slicename = NULL;
+
+- if (!(conn = virDBusGetSystemBus()))
+- return -1;
++ if (!virDBusHasSystemBus())
++ return -2;
++
++ conn = virDBusGetSystemBus();
+
+ if (privileged) {
+ if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0)
+--
+1.8.3.2
+
--- /dev/null
+# -*- rpm-spec -*-
+
+# If neither fedora nor rhel was defined, try to guess them from %{dist}
+%if !0%{?rhel} && !0%{?fedora}
+%{expand:%(echo "%{?dist}" | \
+ sed -ne 's/^\.el\([0-9]\+\).*/%%define rhel \1/p')}
+%{expand:%(echo "%{?dist}" | \
+ sed -ne 's/^\.fc\?\([0-9]\+\).*/%%define fedora \1/p')}
+%endif
+
+# Default to skipping autoreconf. Distros can change just this one line
+# (or provide a command-line override) if they backport any patches that
+# touch configure.ac or Makefile.am.
+# Always run autoreconf
+%{!?enable_autotools:%define enable_autotools 1}
+
+# A client only build will create a libvirt.so only containing
+# the generic RPC driver, and test driver and no libvirtd
+# Default to a full server + client build
+%define client_only 0
+
+# Now turn off server build in certain cases
+
+# RHEL-5 builds are client-only for s390, ppc
+%if 0%{?rhel} == 5
+ %ifnarch %{ix86} x86_64 ia64
+ %define client_only 1
+ %endif
+%endif
+
+# Disable all server side drivers if client only build requested
+%if %{client_only}
+ %define server_drivers 0
+%else
+ %define server_drivers 1
+%endif
+
+# Always build with dlopen'd modules
+%define with_driver_modules 1
+
+# Now set the defaults for all the important features, independent
+# of any particular OS
+
+# First the daemon itself
+%define with_libvirtd 0%{!?_without_libvirtd:%{server_drivers}}
+%define with_avahi 0%{!?_without_avahi:%{server_drivers}}
+
+# Then the hypervisor drivers that run in libvirtd
+%define with_xen 0%{!?_without_xen:%{server_drivers}}
+%define with_qemu 0%{!?_without_qemu:%{server_drivers}}
+%define with_lxc 0%{!?_without_lxc:%{server_drivers}}
+%define with_uml 0%{!?_without_uml:%{server_drivers}}
+%define with_libxl 0%{!?_without_libxl:%{server_drivers}}
+
+%define with_qemu_tcg %{with_qemu}
+# Change if we ever provide qemu-kvm binaries on non-x86 hosts
+%if 0%{?fedora} >= 18
+ %if 0%{?fedora} >= 20
+ %define qemu_kvm_arches %{ix86} x86_64 ppc64 s390x %{arm}
+ %else
+ %define qemu_kvm_arches %{ix86} x86_64 ppc64 s390x
+ %endif
+%else
+ %define qemu_kvm_arches %{ix86} x86_64
+%endif
+
+%ifarch %{qemu_kvm_arches}
+ %define with_qemu_kvm %{with_qemu}
+%else
+ %define with_qemu_kvm 0
+%endif
+
+# Then the hypervisor drivers that run outside libvirtd, in libvirt.so
+%define with_openvz 0%{!?_without_openvz:1}
+%define with_vbox 0%{!?_without_vbox:1}
+%define with_vmware 0%{!?_without_vmware:1}
+%define with_phyp 0%{!?_without_phyp:1}
+%define with_esx 0%{!?_without_esx:1}
+%define with_hyperv 0%{!?_without_hyperv:1}
+%define with_xenapi 0%{!?_without_xenapi:1}
+%define with_parallels 0%{!?_without_parallels:1}
+
+# Then the secondary host drivers, which run inside libvirtd
+%define with_interface 0%{!?_without_interface:%{server_drivers}}
+%define with_network 0%{!?_without_network:%{server_drivers}}
+%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
+%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
+%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
+%define with_storage_disk 0%{!?_without_storage_disk:%{server_drivers}}
+%define with_storage_mpath 0%{!?_without_storage_mpath:%{server_drivers}}
+%if 0%{?fedora} >= 16
+ %define with_storage_rbd 0%{!?_without_storage_rbd:%{server_drivers}}
+%else
+ %define with_storage_rbd 0
+%endif
+%if 0%{?fedora} >= 17
+ %define with_storage_sheepdog 0%{!?_without_storage_sheepdog:%{server_drivers}}
+%else
+ %define with_storage_sheepdog 0
+%endif
+%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
+%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
+
+# A few optional bits off by default, we enable later
+%define with_polkit 0%{!?_without_polkit:0}
+%define with_capng 0%{!?_without_capng:0}
+%define with_fuse 0%{!?_without_fuse:0}
+%define with_netcf 0%{!?_without_netcf:0}
+%define with_udev 0%{!?_without_udev:0}
+%define with_hal 0%{!?_without_hal:0}
+%define with_yajl 0%{!?_without_yajl:0}
+%define with_nwfilter 0%{!?_without_nwfilter:0}
+%define with_libpcap 0%{!?_without_libpcap:0}
+%define with_macvtap 0%{!?_without_macvtap:0}
+%define with_libnl 0%{!?_without_libnl:0}
+%define with_audit 0%{!?_without_audit:0}
+%define with_dtrace 0%{!?_without_dtrace:0}
+%define with_cgconfig 0%{!?_without_cgconfig:0}
+%define with_sanlock 0%{!?_without_sanlock:0}
+%define with_systemd 0%{!?_without_systemd:0}
+%define with_numad 0%{!?_without_numad:0}
+%define with_firewalld 0%{!?_without_firewalld:0}
+%define with_libssh2 0%{!?_without_libssh2:0}
+
+# Non-server/HV driver defaults which are always enabled
+%define with_python 0%{!?_without_python:1}
+%define with_sasl 0%{!?_without_sasl:1}
+
+
+# Finally set the OS / architecture specific special cases
+
+# Xen is available only on i386 x86_64 ia64
+%ifnarch %{ix86} x86_64 ia64
+ %define with_xen 0
+ %define with_libxl 0
+%endif
+
+# vbox is available only on i386 x86_64
+%ifnarch %{ix86} x86_64
+ %define with_vbox 0
+%endif
+
+# Numactl is not available on s390[x] and ARM
+%ifarch s390 s390x %{arm}
+ %define with_numactl 0
+%endif
+
+# RHEL doesn't ship OpenVZ, VBox, UML, PowerHypervisor,
+# VMWare, libxenserver (xenapi), libxenlight (Xen 4.1 and newer),
+# or HyperV.
+%if 0%{?rhel}
+ %define with_openvz 0
+ %define with_vbox 0
+ %define with_uml 0
+ %define with_phyp 0
+ %define with_vmware 0
+ %define with_xenapi 0
+ %define with_libxl 0
+ %define with_hyperv 0
+ %define with_parallels 0
+%endif
+
+# Fedora 17 / RHEL-7 are first where we use systemd. Although earlier
+# Fedora has systemd, libvirt still used sysvinit there.
+%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+ %define with_systemd 1
+%endif
+
+# Fedora 18 / RHEL-7 are first where firewalld support is enabled
+%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+ %define with_firewalld 1
+%endif
+
+# RHEL-5 has restricted QEMU to x86_64 only and is too old for LXC
+%if 0%{?rhel} == 5
+ %define with_qemu_tcg 0
+ %ifnarch x86_64
+ %define with_qemu 0
+ %define with_qemu_kvm 0
+ %endif
+ %define with_lxc 0
+%endif
+
+# RHEL-6 has restricted QEMU to x86_64 only, stopped including Xen
+# on all archs. Other archs all have LXC available though
+%if 0%{?rhel} >= 6
+ %define with_qemu_tcg 0
+ %ifnarch x86_64
+ %define with_qemu 0
+ %define with_qemu_kvm 0
+ %endif
+ %define with_xen 0
+%endif
+
+# Fedora doesn't have any QEMU on ppc64 until FC16 - only ppc
+%if 0%{?fedora} && 0%{?fedora} < 16
+ %ifarch ppc64
+ %define with_qemu 0
+ %endif
+%endif
+
+# Fedora doesn't have new enough Xen for libxl until F18
+%if 0%{?fedora} && 0%{?fedora} < 18
+ %define with_libxl 0
+%endif
+
+# PolicyKit was introduced in Fedora 8 / RHEL-6 or newer
+%if 0%{?fedora} >= 8 || 0%{?rhel} >= 6
+ %define with_polkit 0%{!?_without_polkit:1}
+%endif
+
+# libcapng is used to manage capabilities in Fedora 12 / RHEL-6 or newer
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+ %define with_capng 0%{!?_without_capng:1}
+%endif
+
+# fuse is used to provide virtualized /proc for LXC
+%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+ %define with_fuse 0%{!?_without_fuse:1}
+%endif
+
+# netcf is used to manage network interfaces in Fedora 12 / RHEL-6 or newer
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+ %define with_netcf 0%{!?_without_netcf:%{server_drivers}}
+%endif
+
+# udev is used to manage host devices in Fedora 12 / RHEL-6 or newer
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+ %define with_udev 0%{!?_without_udev:%{server_drivers}}
+%else
+ %define with_hal 0%{!?_without_hal:%{server_drivers}}
+%endif
+
+# interface requires netcf
+%if ! 0%{?with_netcf}
+ %define with_interface 0
+%endif
+
+# Enable yajl library for JSON mode with QEMU
+%if 0%{?fedora} >= 13 || 0%{?rhel} >= 6
+ %define with_yajl 0%{!?_without_yajl:%{server_drivers}}
+%endif
+
+# Enable sanlock library for lock management with QEMU
+# Sanlock is available only on i686 x86_64 for RHEL
+%if 0%{?fedora} >= 16
+ %define with_sanlock 0%{!?_without_sanlock:%{server_drivers}}
+%endif
+%if 0%{?rhel} == 6
+ %ifarch %{ix86} x86_64
+ %define with_sanlock 0%{!?_without_sanlock:%{server_drivers}}
+ %endif
+%endif
+%if 0%{?rhel} >= 7
+ %ifarch x86_64
+ %define with_sanlock 0%{!?_without_sanlock:%{server_drivers}}
+ %endif
+%endif
+
+# Enable libssh2 transport for new enough distros
+%if 0%{?fedora} >= 17
+ %define with_libssh2 0%{!?_without_libssh2:1}
+%endif
+
+# Disable some drivers when building without libvirt daemon.
+# The logic is the same as in configure.ac
+%if ! %{with_libvirtd}
+ %define with_interface 0
+ %define with_network 0
+ %define with_qemu 0
+ %define with_lxc 0
+ %define with_uml 0
+ %define with_hal 0
+ %define with_udev 0
+ %define with_storage_fs 0
+ %define with_storage_lvm 0
+ %define with_storage_iscsi 0
+ %define with_storage_mpath 0
+ %define with_storage_rbd 0
+ %define with_storage_sheepdog 0
+ %define with_storage_disk 0
+%endif
+
+%if %{with_qemu} || %{with_lxc} || %{with_uml}
+ %define with_nwfilter 0%{!?_without_nwfilter:%{server_drivers}}
+# Enable libpcap library
+ %define with_libpcap 0%{!?_without_libpcap:%{server_drivers}}
+ %define with_macvtap 0%{!?_without_macvtap:%{server_drivers}}
+
+# numad is used to manage the CPU and memory placement dynamically,
+# it's not available on s390[x] and ARM.
+ %if 0%{?fedora} >= 17 || 0%{?rhel} >= 6
+ %ifnarch s390 s390x %{arm}
+ %define with_numad 0%{!?_without_numad:%{server_drivers}}
+ %endif
+ %endif
+%endif
+
+%if %{with_macvtap}
+ %define with_libnl 1
+%endif
+
+%if 0%{?fedora} >= 11 || 0%{?rhel} >= 5
+ %define with_audit 0%{!?_without_audit:1}
+%endif
+
+%if 0%{?fedora} >= 13 || 0%{?rhel} >= 6
+ %define with_dtrace 1
+%endif
+
+# Pull in cgroups config system
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+ %if %{with_qemu} || %{with_lxc}
+ %define with_cgconfig 0%{!?_without_cgconfig:1}
+ %endif
+%endif
+
+%if %{with_udev} || %{with_hal}
+ %define with_nodedev 1
+%else
+ %define with_nodedev 0
+%endif
+
+%if %{with_storage_fs} || %{with_storage_mpath} || %{with_storage_iscsi} || %{with_storage_lvm} || %{with_storage_disk}
+ %define with_storage 1
+%else
+ %define with_storage 0
+%endif
+
+
+# Force QEMU to run as non-root
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+ %define qemu_user qemu
+ %define qemu_group qemu
+%else
+ %define qemu_user root
+ %define qemu_group root
+%endif
+
+
+# The RHEL-5 Xen package has some feature backports. This
+# flag is set to enable use of those special bits on RHEL-5
+%if 0%{?rhel} == 5
+ %define with_rhel5 1
+%else
+ %define with_rhel5 0
+%endif
+
+%if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+ %define with_systemd_macros 1
+%else
+ %define with_systemd_macros 0
+%endif
+
+
+# RHEL releases provide stable tool chains and so it is safe to turn
+# compiler warning into errors without being worried about frequent
+# changes in reported warnings
+%if 0%{?rhel}
+ %define enable_werror --enable-werror
+%endif
+
+
+Summary: Library providing a simple virtualization API
+Name: libvirt
+Version: 1.1.1
+Release: 12%{?dist}%{?extra_release}
+License: LGPLv2+
+Group: Development/Libraries
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
+URL: http://libvirt.org/
+
+%if %(echo %{version} | grep -o \\. | wc -l) == 3
+ %define mainturl stable_updates/
+%endif
+Source: http://libvirt.org/sources/%{?mainturl}libvirt-%{version}.tar.gz
+
+Patch1: libvirt-Delete-obsolete-unused-python-test-files.patch
+Patch2: libvirt-Add-APIs-for-formatting-systemd-slice-scope-names.patch
+Patch3: libvirt-Add-support-for-systemd-cgroup-mount.patch
+Patch4: libvirt-Cope-with-races-while-killing-processes.patch
+Patch5: libvirt-Enable-support-for-systemd-machined-in-cgroups-creation.patch
+Patch6: libvirt-Ensure-LXC-QEMU-APIs-set-the-filename-for-errors.patch
+Patch7: libvirt-Avoid-crash-if-NULL-is-passed-for-filename-funcname-in-logging.patch
+Patch8: libvirt-RPC-Don-t-accept-client-if-it-would-overcommit-max_clients.patch
+Patch9: libvirt-Introduce-max_queued_clients.patch
+Patch10: libvirt-conf-add-default-USB-controller-in-qemu-post-parse-callback.patch
+Patch11: libvirt-qemu-rename-some-functions-in-qemu_command.c.patch
+Patch12: libvirt-qemu-eliminate-almost-duplicate-code-in-qemu_command.c.patch
+Patch13: libvirt-qemu-enable-auto-allocate-of-all-PCI-addresses.patch
+Patch14: libvirt-qemu-add-pcie-root-controller.patch
+Patch15: libvirt-qemu-add-dmi-to-pci-bridge-controller.patch
+Patch16: libvirt-qemu-fix-handling-of-default-implicit-devices-for-q35.patch
+Patch17: libvirt-qemu-properly-set-use-device-alias-for-pci-controllers.patch
+Patch18: libvirt-qemu-enable-using-implicit-sata-controller-in-q35-machines.patch
+Patch19: libvirt-qemu-improve-error-reporting-during-PCI-address-validation.patch
+Patch20: libvirt-qemu-refactor-qemuDomainCheckDiskPresence-for-only-disk-presence-check.patch
+Patch21: libvirt-qemu-add-helper-functions-for-diskchain-checking.patch
+Patch22: libvirt-qemu-check-presence-of-each-disk-and-its-backing-file-as-well.patch
+Patch23: libvirt-conf-add-startupPolicy-attribute-for-harddisk.patch
+Patch24: libvirt-qemu-support-to-drop-disk-with-optional-startupPolicy.patch
+Patch25: libvirt-Split-TLS-test-into-two-separate-tests.patch
+Patch26: libvirt-Avoid-re-generating-certs-every-time.patch
+Patch27: libvirt-Change-data-passed-into-TLS-test-cases.patch
+Patch28: libvirt-Fix-validation-of-CA-certificate-chains.patch
+Patch29: libvirt-Fix-parallel-runs-of-TLS-test-suites.patch
+Patch30: libvirt-tests-Fix-parallel-runs-of-TLS-test-suites.patch
+Patch31: libvirt-Add-a-man-page-for-virtlockd-daemon.patch
+Patch32: libvirt-Add-an-example-config-file-for-virtlockd.patch
+Patch33: libvirt-Properly-handle-h-V-for-help-version-aliases-in-virtlockd-libvirtd.patch
+Patch34: libvirt-Make-check-for-dev-loop-device-names-stricter-to-avoid-dev-loop-control.patch
+Patch35: libvirt-Ensure-securityfs-is-mounted-readonly-in-container.patch
+Patch36: libvirt-Add-info-about-access-control-checks-into-API-reference.patch
+Patch37: libvirt-Record-the-where-the-auto-generated-data-comes-from.patch
+Patch38: libvirt-Add-documentation-for-access-control-system.patch
+Patch39: libvirt-virsh-domain-Flip-logic-in-cmdSetvcpus.patch
+Patch40: libvirt-Honour-root-prefix-in-lxcContainerMountFSBlockAuto.patch
+Patch41: libvirt-util-add-virGetUserDirectoryByUID.patch
+Patch42: libvirt-Introduce-a-virt-login-shell-binary.patch
+Patch43: libvirt-build-fix-compilation-of-virt-login-shell.c.patch
+Patch44: libvirt-Fix-double-free-and-broken-logic-in-virt-login-shell.patch
+Patch45: libvirt-Address-missed-feedback-from-review-of-virt-login-shell.patch
+Patch46: libvirt-Ensure-that-dev-exists-in-the-container-root-filesystem.patch
+Patch47: libvirt-remote-Fix-a-segfault-in-remoteDomainCreateWithFlags.patch
+Patch48: libvirt-build-avoid-lgcrypt-with-newer-gnutls.patch
+Patch49: libvirt-virnettlscontext-Resolve-Coverity-warnings-UNINIT.patch
+Patch50: libvirt-build-fix-missing-max_queued_clients-in-augeas-test-file-for-libvirtd.conf.patch
+Patch51: libvirt-virsh-domain-Fix-memleak-in-cmdCPUBaseline.patch
+Patch52: libvirt-Fix-typo-in-domain-name-in-polkit-acl-example.patch
+Patch53: libvirt-Update-polkit-examples-to-use-lookup-method.patch
+Patch54: libvirt-Add-bounds-checking-on-virDomainMigrate-Params-RPC-calls-CVE-2013-4292.patch
+Patch55: libvirt-Add-bounds-checking-on-virDomainGetJobStats-RPC-call.patch
+Patch56: libvirt-Add-bounds-checking-on-virDomain-SnapshotListAllChildren-ListAllSnapshots-RPC-calls.patch
+Patch57: libvirt-Add-bounds-checking-on-virConnectListAllDomains-RPC-call.patch
+Patch58: libvirt-Add-bounds-checking-on-virConnectListAllStoragePools-RPC-call.patch
+Patch59: libvirt-Add-bounds-checking-on-virStoragePoolListAllVolumes-RPC-call.patch
+Patch60: libvirt-Add-bounds-checking-on-virConnectListAllNetworks-RPC-call.patch
+Patch61: libvirt-Add-bounds-checking-on-virConnectListAllInterfaces-RPC-call.patch
+Patch62: libvirt-Add-bounds-checking-on-virConnectListAllNodeDevices-RPC-call.patch
+Patch63: libvirt-Add-bounds-checking-on-virConnectListAllNWFilters-RPC-call.patch
+Patch64: libvirt-Add-bounds-checking-on-virConnectListAllSecrets-RPC-call.patch
+Patch65: libvirt-Prohibit-unbounded-arrays-in-XDR-protocols.patch
+Patch66: libvirt-virbitmap-Refactor-virBitmapParse-to-avoid-access-beyond-bounds-of-array.patch
+Patch67: libvirt-virbitmaptest-Fix-function-header-formatting.patch
+Patch68: libvirt-virbitmaptest-Add-test-for-out-of-bounds-condition.patch
+Patch69: libvirt-virsh-domain-Fix-memleak-in-cmdUndefine-with-storage.patch
+Patch70: libvirt-virsh-modify-vshStringToArray-to-duplicate-the-elements-too.patch
+Patch71: libvirt-virsh-Don-t-leak-list-of-volumes-when-undefining-domain-with-storage.patch
+Patch72: libvirt-Fix-URI-connect-precedence.patch
+Patch73: libvirt-tests-Add-URI-precedence-checking.patch
+Patch74: libvirt-Don-t-free-NULL-network-in-cmdNetworkUpdate.patch
+Patch75: libvirt-virsh-Fix-debugging.patch
+Patch76: libvirt-qemu-Remove-hostdev-entry-when-freeing-the-depending-network-entry.patch
+Patch77: libvirt-Set-security-label-on-FD-for-virDomainOpenGraphics.patch
+Patch78: libvirt-virsh-free-the-caps-list-properly-if-one-of-them-is-invalid.patch
+Patch79: libvirt-virsh-free-the-formatting-string-when-listing-pool-details.patch
+Patch80: libvirt-virsh-pool.c-Don-t-jump-over-variable-declaration.patch
+Patch81: libvirt-virsh-free-the-list-from-ListAll-APIs-even-for-0-items.patch
+Patch82: libvirt-virsh-free-messages-after-logging-them-to-a-file.patch
+Patch83: libvirt-Reverse-logic-allowing-partial-DHCP-host-XML.patch
+Patch84: libvirt-virsh-Print-cephx-and-iscsi-usage.patch
+Patch85: libvirt-qemu_conf-Fix-broken-logic-for-adding-passthrough-iscsi-lun.patch
+Patch86: libvirt-Report-secret-usage-error-message-similarly.patch
+Patch87: libvirt-docs-Update-the-formatdomain-disk-examples.patch
+Patch88: libvirt-docs-Update-formatsecrets-to-include-more-examples-of-each-type.patch
+Patch89: libvirt-docs-Update-iSCSI-storage-pool-example.patch
+Patch90: libvirt-docs-Reformat-disk-attribute-description-in-formatdomain.patch
+Patch91: libvirt-qemuBuildNicDevStr-Add-mq-on-for-multiqueue-networking.patch
+Patch92: libvirt-migration-do-not-restore-labels-on-failed-migration.patch
+Patch93: libvirt-qemu-Drop-qemuDomainMemoryLimit.patch
+Patch94: libvirt-docs-Discourage-users-to-set-hard_limit.patch
+Patch95: libvirt-docs-Clean-09adfdc62de2b-up.patch
+Patch96: libvirt-qemuSetupMemoryCgroup-Handle-hard_limit-properly.patch
+Patch97: libvirt-qemuBuildCommandLine-Fall-back-to-mem-balloon-if-there-s-no-hard_limit.patch
+Patch98: libvirt-qemuDomainAttachHostPciDevice-Fall-back-to-mem-balloon-if-there-s-no-hard_limit.patch
+Patch99: libvirt-Don-t-crash-in-qemuBuildDeviceAddressStr.patch
+Patch100: libvirt-Fix-leaks-in-python-bindings.patch
+Patch101: libvirt-Process-virtlockd.conf-instead-of-libvirtd.conf.patch
+Patch102: libvirt-test_virtlockd.aug.in-Use-the-correct-file.patch
+Patch103: libvirt-qemu-Make-domain-renaming-work-during-migration.patch
+Patch104: libvirt-qemu-Handle-huge-number-of-queues-correctly.patch
+Patch105: libvirt-conf-Remove-the-actual-hostdev-when-removing-a-network.patch
+Patch106: libvirt-conf-Don-t-deref-NULL-actual-network-in-virDomainNetGetActualHostdev.patch
+Patch107: libvirt-python-Fix-a-PyList-usage-mistake.patch
+Patch108: libvirt-Add-nat-element-to-forward-network-schemas.patch
+Patch109: libvirt-Always-specify-qcow2-compat-level-on-qemu-img-command-line.patch
+Patch110: libvirt-selinux-distinguish-failure-to-label-from-request-to-avoid-label.patch
+Patch111: libvirt-selinux-enhance-test-to-cover-nfs-label-failure.patch
+Patch112: libvirt-Pass-AM_LDFLAGS-to-driver-modules-too.patch
+Patch113: libvirt-virsh-domjobinfo-Do-not-return-1-if-job-is-NONE.patch
+Patch114: libvirt-Fix-polkit-permission-names-for-storage-pools-vols-node-devices.patch
+Patch115: libvirt-Fix-naming-of-permission-for-detecting-storage-pools.patch
+Patch116: libvirt-security-provide-supplemental-groups-even-when-parsing-label-CVE-2013-4291.patch
+Patch117: libvirt-virFileNBDDeviceAssociate-Avoid-use-of-uninitialized-variable.patch
+Patch118: libvirt-rename-struct-interface_driver-to-virNetcfDriverState.patch
+Patch119: libvirt-netcf-driver-use-a-single-netcf-handle-for-all-connections.patch
+Patch120: libvirt-virDomainDefParseXML-set-the-argument-of-virBitmapFree-to-NULL-after-calling-virBitmapFree.patch
+Patch121: libvirt-Add-test-for-the-nodemask-double-free-crash.patch
+Patch122: libvirt-qemu-Fix-checking-of-guest-ABI-compatibility-when-reverting-snapshots.patch
+Patch123: libvirt-Also-store-user-group-ID-values-in-virIdentity.patch
+Patch124: libvirt-Ensure-system-identity-includes-process-start-time.patch
+Patch125: libvirt-Add-support-for-using-3-arg-pkcheck-syntax-for-process.patch
+Patch126: libvirt-Free-slicename-in-virSystemdCreateMachine.patch
+Patch127: libvirt-qemu-Fix-checking-of-ABI-stability-when-restoring-external-checkpoints.patch
+Patch128: libvirt-qemu-Use-migratable-XML-definition-when-doing-external-checkpoints.patch
+Patch129: libvirt-qemu-Fix-memleak-after-commit-59898a88ce8431bd3ea249b8789edc2ef9985827.patch
+Patch130: libvirt-qemu-Avoid-dangling-job-in-qemuDomainSetBlockIoTune.patch
+Patch131: libvirt-Fix-crash-in-remoteDispatchDomainMemoryStats.patch
+Patch132: libvirt-LXC-Don-t-mount-securityfs-when-user-namespace-enabled.patch
+Patch133: libvirt-Move-array-of-mounts-out-of-lxcContainerMountBasicFS.patch
+Patch134: libvirt-Ensure-root-filesystem-is-recursively-mounted-readonly.patch
+Patch135: libvirt-qemu-Fix-seamless-SPICE-migration.patch
+Patch136: libvirt-qemu-use-ide-as-device-name-for-implicit-SATA-controller-on-Q35.patch
+Patch137: libvirt-qemu-only-parse-basename-when-determining-emulator-properties.patch
+Patch138: libvirt-qemu-recognize-machine-accel-kvm-when-parsing-native.patch
+Patch139: libvirt-qemu-don-t-leave-shutdown-inhibited-on-attach-failure.patch
+Patch140: libvirt-qemu-don-t-leak-vm-on-failure.patch
+Patch141: libvirt-Fix-typo-in-identity-code-which-is-pre-requisite-for-CVE-2013-4311.patch
+Patch142: libvirt-conf-Don-t-crash-on-invalid-chardev-source-definition-of-RNGs-and-other.patch
+Patch143: libvirt-rpc-Increase-bound-limit-for-virDomainGetJobStats.patch
+Patch144: libvirt-qemu-Free-all-driver-data-in-qemuStateCleanup.patch
+Patch145: libvirt-qemu-Don-t-leak-reference-to-virQEMUDriverConfigPtr.patch
+Patch146: libvirt-qemu-eliminate-redundant-if-clauses-in-qemuCollectPCIAddress.patch
+Patch147: libvirt-qemu-allow-some-PCI-devices-to-be-attached-to-PCIe-slots.patch
+Patch148: libvirt-qemu-replace-multiple-strcmps-with-a-switch-on-an-enum.patch
+Patch149: libvirt-qemu-support-ich9-intel-hda-audio-device.patch
+Patch150: libvirt-qemu-turn-if-into-switch-in-qemuDomainValidateDevicePCISlotsQ35.patch
+Patch151: libvirt-qemu-prefer-to-put-a-Q35-machine-s-dmi-to-pci-bridge-at-00-1E.0.patch
+Patch152: libvirt-virNetDevBandwidthEqual-Make-it-more-robust.patch
+Patch153: libvirt-qemu_hotplug-Allow-QoS-update-in-qemuDomainChangeNet.patch
+Patch154: libvirt-qemu-check-actual-netdev-type-rather-than-config-netdev-type-during-init.patch
+Patch155: libvirt-Fix-crash-in-libvirtd-when-events-are-registered-ACLs-active-CVE-2013-4399.patch
+Patch156: libvirt-Remove-virConnectPtr-arg-from-virNWFilterDefParse.patch
+Patch157: libvirt-Don-t-pass-virConnectPtr-in-nwfilter-struct-domUpdateCBStruct.patch
+Patch158: libvirt-Remove-use-of-virConnectPtr-from-all-remaining-nwfilter-code.patch
+Patch159: libvirt-Don-t-set-netdev-offline-in-container-cleanup.patch
+Patch160: libvirt-Avoid-reporting-an-error-if-veth-device-is-already-deleted.patch
+Patch161: libvirt-Avoid-deleting-NULL-veth-device-name.patch
+Patch162: libvirt-Retry-veth-device-creation-on-failure.patch
+Patch163: libvirt-Use-vnet-as-prefix-for-veth-devices.patch
+Patch164: libvirt-Free-cmd-in-virNetDevVethDelete.patch
+Patch165: libvirt-Free-cmd-in-virNetDevVethCreate.patch
+Patch166: libvirt-LXC-Fix-handling-of-RAM-filesystem-size-units.patch
+Patch167: libvirt-build-Add-lxc-testcase-to-dist-list.patch
+Patch168: libvirt-tests-work-with-older-dbus.patch
+Patch169: libvirt-virdbus-Add-virDBusHasSystemBus.patch
+Patch170: libvirt-virsystemd-Don-t-fail-to-start-VM-if-DBus-isn-t-available-or-compiled-in.patch
+Patch171: libvirt-DBus-introduce-virDBusIsServiceEnabled.patch
+Patch172: libvirt-Change-way-we-fake-dbus-method-calls.patch
+Patch173: libvirt-Fix-virsystemdtest-for-previous-commit.patch
+Patch174: libvirt-LXC-workaround-machined-uncleaned-data-with-containers-running-systemd.patch
+Patch175: libvirt-Allow-use-of-a-private-dbus-bus-connection.patch
+Patch176: libvirt-Add-a-method-for-closing-the-dbus-system-bus-connection.patch
+Patch177: libvirt-Make-LXC-controller-use-a-private-dbus-connection-close-it.patch
+Patch178: libvirt-Fix-flaw-in-detecting-log-format.patch
+Patch179: libvirt-Fix-exit-status-of-lxc-controller.patch
+Patch180: libvirt-Improve-error-reporting-with-LXC-controller.patch
+Patch181: libvirt-nwfilter-Don-t-fail-to-start-if-DBus-isn-t-available.patch
+Patch182: libvirt-Don-t-ignore-all-dbus-connection-errors.patch
+Patch183: libvirt-LXC-Check-the-existence-of-dir-before-resolving-symlinks.patch
+Patch184: libvirt-Ensure-lxcContainerMain-reports-errors-on-stderr.patch
+Patch185: libvirt-Ensure-lxcContainerResolveSymlinks-reports-errors.patch
+Patch186: libvirt-Improve-log-filtering-in-virLXCProcessReadLogOutputData.patch
+Patch187: libvirt-Initialize-threading-error-layer-in-LXC-controller.patch
+Patch188: libvirt-qemu_migration-Avoid-crashing-if-domain-dies-too-quickly.patch
+Patch189: libvirt-Convert-uuid-to-a-string-before-printing-it.patch
+Patch190: libvirt-qemu_process-Make-qemuProcessReadLog-more-versatile-and-reusable.patch
+Patch191: libvirt-qemu-monitor-Add-infrastructure-to-access-VM-logs-for-better-err-msgs.patch
+Patch192: libvirt-qemu-monitor-Produce-better-errors-on-monitor-hangup.patch
+Patch193: libvirt-qemu-Wire-up-better-early-error-reporting.patch
+Patch194: libvirt-qemu-process-Silence-coverity-warning-when-rewinding-log-file.patch
+Patch195: libvirt-qemu-hostdev-Refactor-PCI-passhrough-handling.patch
+Patch196: libvirt-qemu-hostdev-Fix-function-spacing-and-header-formatting.patch
+Patch197: libvirt-qemu-hostdev-Add-checks-if-PCI-passthrough-is-available-in-the-host.patch
+Patch198: libvirt-qemu-Prefer-VFIO-for-PCI-device-passthrough.patch
+Patch199: libvirt-qemu-Init-pcidevs-in-qemuPrepareHostdevPCIDevices.patch
+Patch200: libvirt-Fix-max-stream-packet-size-for-old-clients.patch
+Patch201: libvirt-Adjust-legacy-max-payload-size-to-account-for-header-information.patch
+Patch202: libvirt-rpc-Correct-the-wrong-payload-size-checking.patch
+Patch203: libvirt-qemu-simplify-calling-qemuDomainHostdevNetConfigRestore.patch
+Patch204: libvirt-qemu-move-qemuDomainRemoveNetDevice-to-avoid-forward-reference.patch
+Patch205: libvirt-qemu-fix-removal-of-interface-type-hostdev.patch
+Patch206: libvirt-remote-fix-regression-in-event-deregistration.patch
+Patch207: libvirt-qemu-managedsave-Add-support-for-compressing-managed-save-images.patch
+Patch208: libvirt-qemu-snapshot-Add-support-for-compressing-external-snapshot-memory.patch
+Patch209: libvirt-Migration-Introduce-VIR_MIGRATE_PARAM_LISTEN_ADDRESS.patch
+Patch210: libvirt-virsocket-Introduce-virSocketAddrIsWildcard.patch
+Patch211: libvirt-qemu-Implement-support-for-VIR_MIGRATE_PARAM_LISTEN_ADDRESS.patch
+Patch212: libvirt-qemu_conf-Introduce-migration_address.patch
+Patch213: libvirt-qemu-Include-listenAddress-in-debug-prints.patch
+Patch214: libvirt-docs-Expand-description-of-host-model-CPU-mode.patch
+Patch215: libvirt-qemu-Avoid-assigning-unavailable-migration-ports.patch
+Patch216: libvirt-qemu-Make-migration-port-range-configurable.patch
+Patch217: libvirt-qemu-Fix-augeas-support-for-migration-ports.patch
+Patch218: libvirt-Fix-perms-for-virConnectDomainXML-To-From-Native.patch
+Patch219: libvirt-Add-helpers-for-getting-env-vars-in-a-setuid-environment.patch
+Patch220: libvirt-Only-allow-stderr-log-output-when-running-setuid.patch
+Patch221: libvirt-Close-all-non-stdio-FDs-in-virt-login-shell.patch
+Patch222: libvirt-Don-t-link-virt-login-shell-against-libvirt.so.patch
+Patch223: libvirt-build-fix-linking-virt-login-shell.patch
+Patch224: libvirt-build-fix-build-of-virt-login-shell-on-systems-with-older-gnutls.patch
+Patch225: libvirt-Set-a-sane-PATH-for-virt-login-shell.patch
+Patch226: libvirt-Make-virCommand-env-handling-robust-in-setuid-env.patch
+Patch227: libvirt-Remove-all-direct-use-of-getenv.patch
+Patch228: libvirt-Block-all-use-of-getenv-with-syntax-check.patch
+Patch229: libvirt-Only-allow-the-UNIX-transport-in-remote-driver-when-setuid.patch
+Patch230: libvirt-Don-t-allow-remote-driver-daemon-autostart-when-running-setuid.patch
+Patch231: libvirt-Add-stub-getegid-impl-for-platforms-lacking-it.patch
+Patch232: libvirt-Remove-nearly-all-use-of-getuid-getgid.patch
+Patch233: libvirt-Block-all-use-of-libvirt.so-in-setuid-programs.patch
+Patch234: libvirt-virpci-Don-t-error-on-unbinded-devices.patch
+Patch235: libvirt-network-fix-connections-count-in-case-of-allocate-failure.patch
+Patch236: libvirt-qemu-clean-up-migration-ports-when-migration-cancelled.patch
+Patch237: libvirt-qemuMigrationBeginPhase-Check-for-drive-mirror-for-NBD.patch
+Patch238: libvirt-Allow-root-directory-in-filesystem-source-dir-schema.patch
+Patch239: libvirt-Use-a-port-from-the-migration-range-for-NBD-as-well.patch
+Patch240: libvirt-qemu-Avoid-double-free-of-VM.patch
+Patch241: libvirt-util-use-size_t-instead-of-unsigned-int-for-num_virtual_functions.patch
+Patch242: libvirt-pci-properly-handle-out-of-order-SRIOV-virtual-functions.patch
+Patch243: libvirt-conf-Do-better-job-when-comparing-features-ABI-compatibility.patch
+Patch244: libvirt-schema-Rename-option-hypervtristate-to-featurestate.patch
+Patch245: libvirt-conf-Mark-user-provided-strings-in-error-messages-when-parsing-XML.patch
+Patch246: libvirt-cpu-Add-support-for-loading-and-storing-CPU-data.patch
+Patch247: libvirt-cpu-x86-Rename-struct-cpuX86cpuid-as-virCPUx86CPUID.patch
+Patch248: libvirt-cpu-x86-Rename-struct-cpuX86Data-as-virCPUx86Data.patch
+Patch249: libvirt-cpu-x86-Rename-x86DataFree-as-virCPUx86DataFree.patch
+Patch250: libvirt-Ensure-arch-is-always-set-in-cpuArchNodeData.patch
+Patch251: libvirt-cpu-x86-Rename-x86MakeCPUData-as-virCPUx86MakeData.patch
+Patch252: libvirt-cpu-x86-Rename-x86DataAddCpuid-as-virCPUx86DataAddCPUID.patch
+Patch253: libvirt-cpu-x86-Rename-data_iterator-and-DATA_ITERATOR_INIT.patch
+Patch254: libvirt-cpu-x86-Fix-return-types-of-x86cpuidMatch-and-x86cpuidMatchMasked.patch
+Patch255: libvirt-cpu-x86-Use-whitespace-to-clarify-context-and-use-consistent-labels.patch
+Patch256: libvirt-cpu-x86-Clean-up-error-messages-in-x86VendorLoad.patch
+Patch257: libvirt-cpu-Export-few-x86-specific-APIs.patch
+Patch258: libvirt-cpu-x86-Parse-the-CPU-feature-map-only-once.patch
+Patch259: libvirt-cpu_x86-Refactor-storage-of-CPUID-data-to-add-support-for-KVM-features.patch
+Patch260: libvirt-qemu-Add-monitor-APIs-to-fetch-CPUID-data-from-QEMU.patch
+Patch261: libvirt-cpu-x86-Add-internal-CPUID-features-support-and-KVM-feature-bits.patch
+Patch262: libvirt-conf-Refactor-storing-and-usage-of-feature-flags.patch
+Patch263: libvirt-qemu-Add-support-for-paravirtual-spinlocks-in-the-guest.patch
+Patch264: libvirt-qemu-process-Validate-specific-CPUID-flags-of-a-guest.patch
+
+
+%if %{with_libvirtd}
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_network}
+Requires: libvirt-daemon-config-network = %{version}-%{release}
+ %endif
+ %if %{with_nwfilter}
+Requires: libvirt-daemon-config-nwfilter = %{version}-%{release}
+ %endif
+ %if %{with_driver_modules}
+ %if %{with_libxl}
+Requires: libvirt-daemon-driver-libxl = %{version}-%{release}
+ %endif
+ %if %{with_lxc}
+Requires: libvirt-daemon-driver-lxc = %{version}-%{release}
+ %endif
+ %if %{with_qemu}
+Requires: libvirt-daemon-driver-qemu = %{version}-%{release}
+ %endif
+ %if %{with_uml}
+Requires: libvirt-daemon-driver-uml = %{version}-%{release}
+ %endif
+ %if %{with_xen}
+Requires: libvirt-daemon-driver-xen = %{version}-%{release}
+ %endif
+ %if %{with_vbox}
+Requires: libvirt-daemon-driver-vbox = %{version}-%{release}
+ %endif
+
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+ %endif
+%endif
+Requires: libvirt-client = %{version}-%{release}
+
+# All build-time requirements. Run-time requirements are
+# listed against each sub-RPM
+%if 0%{?enable_autotools}
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: gettext-devel
+BuildRequires: libtool
+BuildRequires: /usr/bin/pod2man
+%endif
+BuildRequires: python-devel
+%if %{with_systemd}
+BuildRequires: systemd-units
+%endif
+%if %{with_xen} || %{with_libxl}
+BuildRequires: xen-devel
+%endif
+BuildRequires: libxml2-devel
+BuildRequires: xhtml1-dtds
+BuildRequires: libxslt
+BuildRequires: readline-devel
+BuildRequires: ncurses-devel
+BuildRequires: gettext
+BuildRequires: libtasn1-devel
+%if (0%{?rhel} && 0%{?rhel} < 7) || (0%{?fedora} && 0%{?fedora} < 19)
+BuildRequires: libgcrypt-devel
+%endif
+BuildRequires: gnutls-devel
+BuildRequires: libattr-devel
+%if %{with_libvirtd}
+# For pool-build probing for existing pools
+BuildRequires: libblkid-devel >= 2.17
+%endif
+%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+# for augparse, optionally used in testing
+BuildRequires: augeas
+%endif
+%if %{with_hal}
+BuildRequires: hal-devel
+%endif
+%if %{with_udev}
+ %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+BuildRequires: systemd-devel >= 185
+ %else
+BuildRequires: libudev-devel >= 145
+ %endif
+BuildRequires: libpciaccess-devel >= 0.10.9
+%endif
+%if %{with_yajl}
+BuildRequires: yajl-devel
+%endif
+%if %{with_sanlock}
+# make sure libvirt is built with new enough sanlock on
+# distros that have it; required for on_lockfailure
+ %if 0%{?fedora} >= 17 || 0%{?rhel} >= 6
+BuildRequires: sanlock-devel >= 2.4
+ %else
+BuildRequires: sanlock-devel >= 1.8
+ %endif
+%endif
+%if %{with_libpcap}
+BuildRequires: libpcap-devel
+%endif
+%if %{with_libnl}
+ %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+BuildRequires: libnl3-devel
+ %else
+BuildRequires: libnl-devel
+ %endif
+%endif
+%if %{with_avahi}
+BuildRequires: avahi-devel
+%endif
+%if %{with_selinux}
+BuildRequires: libselinux-devel
+%endif
+%if %{with_network}
+BuildRequires: dnsmasq >= 2.41
+BuildRequires: iptables
+BuildRequires: iptables-ipv6
+BuildRequires: radvd
+%endif
+%if %{with_nwfilter}
+BuildRequires: ebtables
+%endif
+BuildRequires: module-init-tools
+%if %{with_sasl}
+BuildRequires: cyrus-sasl-devel
+%endif
+%if %{with_polkit}
+ %if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+# For CVE-2013-4311
+BuildRequires: polkit-devel >= 0.112
+ %else
+BuildRequires: PolicyKit-devel >= 0.6
+ %endif
+%endif
+%if %{with_storage_fs}
+# For mount/umount in FS driver
+BuildRequires: util-linux
+%endif
+%if %{with_qemu}
+# From QEMU RPMs
+BuildRequires: /usr/bin/qemu-img
+%else
+ %if %{with_xen}
+# From Xen RPMs
+BuildRequires: /usr/sbin/qcow-create
+ %endif
+%endif
+%if %{with_storage_lvm}
+# For LVM drivers
+BuildRequires: lvm2
+%endif
+%if %{with_storage_iscsi}
+# For ISCSI driver
+BuildRequires: iscsi-initiator-utils
+%endif
+%if %{with_storage_disk}
+# For disk driver
+BuildRequires: parted-devel
+ %if 0%{?rhel} == 5
+# Broken RHEL-5 parted RPM is missing a dep
+BuildRequires: e2fsprogs-devel
+ %endif
+%endif
+%if %{with_storage_mpath}
+# For Multipath support
+ %if 0%{?rhel} == 5
+# Broken RHEL-5 packaging has header files in main RPM :-(
+BuildRequires: device-mapper
+ %else
+BuildRequires: device-mapper-devel
+ %endif
+ %if %{with_storage_rbd}
+BuildRequires: ceph-devel
+ %endif
+%endif
+%if %{with_numactl}
+# For QEMU/LXC numa info
+BuildRequires: numactl-devel
+%endif
+%if %{with_capng}
+BuildRequires: libcap-ng-devel >= 0.5.0
+%endif
+%if %{with_fuse}
+BuildRequires: fuse-devel >= 2.8.6
+%endif
+%if %{with_phyp} || %{with_libssh2}
+BuildRequires: libssh2-devel >= 1.3.0
+%endif
+
+%if %{with_netcf}
+ %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+BuildRequires: netcf-devel >= 0.2.2
+ %else
+ %if 0%{?fedora} >= 16 || 0%{?rhel} >= 6
+BuildRequires: netcf-devel >= 0.1.8
+ %else
+BuildRequires: netcf-devel >= 0.1.4
+ %endif
+ %endif
+%endif
+%if %{with_esx}
+ %if 0%{?fedora} >= 9 || 0%{?rhel} >= 6
+BuildRequires: libcurl-devel
+ %else
+BuildRequires: curl-devel
+ %endif
+%endif
+%if %{with_hyperv}
+BuildRequires: libwsman-devel >= 2.2.3
+%endif
+%if %{with_audit}
+BuildRequires: audit-libs-devel
+%endif
+%if %{with_dtrace}
+# we need /usr/sbin/dtrace
+BuildRequires: systemtap-sdt-devel
+%endif
+
+%if %{with_storage_fs}
+# For mount/umount in FS driver
+BuildRequires: util-linux
+# For showmount in FS driver (netfs discovery)
+BuildRequires: nfs-utils
+%endif
+
+%if %{with_firewalld}
+# Communication with the firewall daemon uses DBus
+BuildRequires: dbus-devel
+%endif
+
+# Fedora build root suckage
+BuildRequires: gawk
+
+# For storage wiping with different algorithms
+BuildRequires: scrub
+
+%if %{with_numad}
+BuildRequires: numad
+%endif
+
+Provides: bundled(gnulib)
+
+%description
+Libvirt is a C toolkit to interact with the virtualization capabilities
+of recent versions of Linux (and other OSes). The main package includes
+the libvirtd server exporting the virtualization support.
+
+%package docs
+Summary: API reference and website documentation
+Group: Development/Libraries
+
+%description docs
+Includes the API reference for the libvirt C library, and a complete
+copy of the libvirt.org website documentation.
+
+%if %{with_libvirtd}
+%package daemon
+Summary: Server side daemon and supporting files for libvirt library
+Group: Development/Libraries
+
+# All runtime requirements for the libvirt package (runtime requrements
+# for subpackages are listed later in those subpackages)
+
+# The client side, i.e. shared libs and virsh are in a subpackage
+Requires: %{name}-client = %{version}-%{release}
+
+# for modprobe of pci devices
+Requires: module-init-tools
+# for /sbin/ip & /sbin/tc
+Requires: iproute
+ %if %{with_avahi}
+ %if 0%{?rhel} == 5
+Requires: avahi
+ %else
+Requires: avahi-libs
+ %endif
+ %endif
+ %if %{with_polkit}
+ %if 0%{?fedora} >= 12 || 0%{?rhel} >=6
+# For CVE-2013-4311
+Requires: polkit >= 0.112
+ %else
+Requires: PolicyKit >= 0.6
+ %endif
+ %endif
+ %if %{with_cgconfig}
+Requires: libcgroup
+ %endif
+ %ifarch %{ix86} x86_64 ia64
+# For virConnectGetSysinfo
+Requires: dmidecode
+ %endif
+# For service management
+ %if %{with_systemd}
+Requires(post): systemd-units
+Requires(post): systemd-sysv
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+ %endif
+ %if %{with_numad}
+Requires: numad
+ %endif
+# libvirtd depends on 'messagebus' service
+Requires: dbus
+# For uid creation during pre
+Requires(pre): shadow-utils
+
+%description daemon
+Server side daemon required to manage the virtualization capabilities
+of recent versions of Linux. Requires a hypervisor specific sub-RPM
+for specific drivers.
+
+ %if %{with_network}
+%package daemon-config-network
+Summary: Default configuration files for the libvirtd daemon
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-config-network
+Default configuration files for setting up NAT based networking
+ %endif
+
+ %if %{with_nwfilter}
+%package daemon-config-nwfilter
+Summary: Network filter configuration files for the libvirtd daemon
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-config-nwfilter
+Network filter configuration files for cleaning guest traffic
+ %endif
+
+ %if %{with_driver_modules}
+ %if %{with_network}
+%package daemon-driver-network
+Summary: Network driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+Requires: dnsmasq >= 2.41
+Requires: radvd
+Requires: iptables
+Requires: iptables-ipv6
+
+%description daemon-driver-network
+The network driver plugin for the libvirtd daemon, providing
+an implementation of the virtual network APIs using the Linux
+bridge capabilities.
+ %endif
+
+
+ %if %{with_nwfilter}
+%package daemon-driver-nwfilter
+Summary: Nwfilter driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+Requires: iptables
+Requires: iptables-ipv6
+Requires: ebtables
+
+%description daemon-driver-nwfilter
+The nwfilter driver plugin for the libvirtd daemon, providing
+an implementation of the firewall APIs using the ebtables,
+iptables and ip6tables capabilities
+ %endif
+
+
+ %if %{with_nodedev}
+%package daemon-driver-nodedev
+Summary: Nodedev driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+# needed for device enumeration
+ %if %{with_hal}
+Requires: hal
+ %endif
+ %if %{with_udev}
+ %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
+Requires: systemd >= 185
+ %else
+Requires: udev >= 145
+ %endif
+ %endif
+
+%description daemon-driver-nodedev
+The nodedev driver plugin for the libvirtd daemon, providing
+an implementation of the node device APIs using the udev
+capabilities.
+ %endif
+
+
+ %if %{with_interface}
+%package daemon-driver-interface
+Summary: Interface driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_netcf} && (0%{?fedora} >= 18 || 0%{?rhel} >= 7)
+Requires: netcf-libs >= 0.2.2
+ %endif
+
+%description daemon-driver-interface
+The interface driver plugin for the libvirtd daemon, providing
+an implementation of the network interface APIs using the
+netcf library
+ %endif
+
+
+%package daemon-driver-secret
+Summary: Secret driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-driver-secret
+The secret driver plugin for the libvirtd daemon, providing
+an implementation of the secret key APIs.
+
+
+ %if %{with_storage}
+%package daemon-driver-storage
+Summary: Storage driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_storage_fs}
+Requires: nfs-utils
+# For mkfs
+Requires: util-linux
+# For glusterfs
+ %if 0%{?fedora} >= 11
+Requires: glusterfs-client >= 2.0.1
+ %endif
+ %endif
+ %if %{with_storage_lvm}
+# For LVM drivers
+Requires: lvm2
+ %endif
+ %if %{with_storage_iscsi}
+# For ISCSI driver
+Requires: iscsi-initiator-utils
+ %endif
+ %if %{with_storage_disk}
+# For disk driver
+Requires: parted
+Requires: device-mapper
+ %endif
+ %if %{with_storage_mpath}
+# For multipath support
+Requires: device-mapper
+ %endif
+ %if %{with_storage_sheepdog}
+# For Sheepdog support
+Requires: sheepdog
+ %endif
+ %if %{with_qemu}
+# From QEMU RPMs
+Requires: /usr/bin/qemu-img
+ %else
+ %if %{with_xen}
+# From Xen RPMs
+Requires: /usr/sbin/qcow-create
+ %endif
+ %endif
+
+%description daemon-driver-storage
+The storage driver plugin for the libvirtd daemon, providing
+an implementation of the storage APIs using LVM, iSCSI,
+parted and more.
+ %endif
+
+
+ %if %{with_qemu}
+%package daemon-driver-qemu
+Summary: Qemu driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+# There really is a hard cross-driver dependency here
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: /usr/bin/qemu-img
+# For image compression
+Requires: gzip
+Requires: bzip2
+Requires: lzop
+Requires: xz
+
+%description daemon-driver-qemu
+The qemu driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+QEMU
+ %endif
+
+
+ %if %{with_lxc}
+%package daemon-driver-lxc
+Summary: LXC driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+# There really is a hard cross-driver dependency here
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+
+%description daemon-driver-lxc
+The LXC driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+the Linux kernel
+ %endif
+
+
+ %if %{with_uml}
+%package daemon-driver-uml
+Summary: Uml driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-driver-uml
+The UML driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+User Mode Linux
+ %endif
+
+
+ %if %{with_xen}
+%package daemon-driver-xen
+Summary: Xen driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-driver-xen
+The Xen driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+Xen
+ %endif
+
+
+ %if %{with_vbox}
+%package daemon-driver-vbox
+Summary: VirtualBox driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-driver-vbox
+The vbox driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+VirtualBox
+ %endif
+
+
+ %if %{with_libxl}
+%package daemon-driver-libxl
+Summary: Libxl driver plugin for the libvirtd daemon
+Group: Development/Libraries
+Requires: libvirt-daemon = %{version}-%{release}
+
+%description daemon-driver-libxl
+The Libxl driver plugin for the libvirtd daemon, providing
+an implementation of the hypervisor driver APIs using
+Libxl
+ %endif
+ %endif # %{with_driver_modules}
+
+
+
+ %if %{with_qemu_tcg}
+%package daemon-qemu
+Summary: Server side daemon & driver required to run QEMU guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+Requires: libvirt-daemon-driver-qemu = %{version}-%{release}
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+Requires: qemu
+
+%description daemon-qemu
+Server side daemon and driver required to manage the virtualization
+capabilities of the QEMU TCG emulators
+ %endif
+
+
+ %if %{with_qemu_kvm}
+%package daemon-kvm
+Summary: Server side daemon & driver required to run KVM guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+Requires: libvirt-daemon-driver-qemu = %{version}-%{release}
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+Requires: qemu-kvm
+
+%description daemon-kvm
+Server side daemon and driver required to manage the virtualization
+capabilities of the KVM hypervisor
+ %endif
+
+
+ %if %{with_lxc}
+%package daemon-lxc
+Summary: Server side daemon & driver required to run LXC guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+Requires: libvirt-daemon-driver-lxc = %{version}-%{release}
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+
+%description daemon-lxc
+Server side daemon and driver required to manage the virtualization
+capabilities of LXC
+ %endif
+
+
+ %if %{with_uml}
+%package daemon-uml
+Summary: Server side daemon & driver required to run UML guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+Requires: libvirt-daemon-driver-uml = %{version}-%{release}
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+# There are no UML kernel RPMs in Fedora/RHEL to depend on.
+
+%description daemon-uml
+Server side daemon and driver required to manage the virtualization
+capabilities of UML
+ %endif
+
+
+ %if %{with_xen} || %{with_libxl}
+%package daemon-xen
+Summary: Server side daemon & driver required to run XEN guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+ %if %{with_xen}
+Requires: libvirt-daemon-driver-xen = %{version}-%{release}
+ %endif
+ %if %{with_libxl}
+Requires: libvirt-daemon-driver-libxl = %{version}-%{release}
+ %endif
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+Requires: xen
+
+%description daemon-xen
+Server side daemon and driver required to manage the virtualization
+capabilities of XEN
+ %endif
+
+ %if %{with_vbox}
+%package daemon-vbox
+Summary: Server side daemon & driver required to run VirtualBox guests
+Group: Development/Libraries
+
+Requires: libvirt-daemon = %{version}-%{release}
+ %if %{with_driver_modules}
+Requires: libvirt-daemon-driver-vbox = %{version}-%{release}
+Requires: libvirt-daemon-driver-interface = %{version}-%{release}
+Requires: libvirt-daemon-driver-network = %{version}-%{release}
+Requires: libvirt-daemon-driver-nodedev = %{version}-%{release}
+Requires: libvirt-daemon-driver-nwfilter = %{version}-%{release}
+Requires: libvirt-daemon-driver-secret = %{version}-%{release}
+Requires: libvirt-daemon-driver-storage = %{version}-%{release}
+ %endif
+
+%description daemon-vbox
+Server side daemon and driver required to manage the virtualization
+capabilities of VirtualBox
+ %endif
+%endif # %{with_libvirtd}
+
+%package client
+Summary: Client side library and utilities of the libvirt library
+Group: Development/Libraries
+Requires: readline
+Requires: ncurses
+# So remote clients can access libvirt over SSH tunnel
+# (client invokes 'nc' against the UNIX socket on the server)
+Requires: nc
+# Needed by /usr/libexec/libvirt-guests.sh script.
+Requires: gettext
+# Needed by virt-pki-validate script.
+Requires: gnutls-utils
+# Needed for probing the power management features of the host.
+Requires: pm-utils
+%if %{with_sasl}
+Requires: cyrus-sasl
+# Not technically required, but makes 'out-of-box' config
+# work correctly & doesn't have onerous dependencies
+Requires: cyrus-sasl-md5
+%endif
+
+%description client
+Shared libraries and client binaries needed to access to the
+virtualization capabilities of recent versions of Linux (and other OSes).
+
+%if %{with_lxc}
+%package login-shell
+Summary: Login shell for connecting users to an LXC container
+Group: Development/Libraries
+Requires: %{name}-client = %{version}-%{release}
+
+%description login-shell
+Provides the set-uid virt-login-shell binary that is used to
+connect a user to an LXC container when they login, by switching
+namespaces.
+%endif
+
+%package devel
+Summary: Libraries, includes, etc. to compile with the libvirt library
+Group: Development/Libraries
+Requires: %{name}-client = %{version}-%{release}
+Requires: %{name}-docs = %{version}-%{release}
+Requires: pkgconfig
+
+%description devel
+Include header files & development libraries for the libvirt C library.
+
+%if %{with_sanlock}
+%package lock-sanlock
+Summary: Sanlock lock manager plugin for QEMU driver
+Group: Development/Libraries
+ %if 0%{?fedora} >= 17 || 0%{?rhel} >= 6
+Requires: sanlock >= 2.4
+ %else
+Requires: sanlock >= 1.8
+ %endif
+#for virt-sanlock-cleanup require augeas
+Requires: augeas
+Requires: %{name}-daemon = %{version}-%{release}
+Requires: %{name}-client = %{version}-%{release}
+
+%description lock-sanlock
+Includes the Sanlock lock manager plugin for the QEMU
+driver
+%endif
+
+%if %{with_python}
+%package python
+Summary: Python bindings for the libvirt library
+Group: Development/Libraries
+Requires: %{name}-client = %{version}-%{release}
+
+%description python
+The libvirt-python package contains a module that permits applications
+written in the Python programming language to use the interface
+supplied by the libvirt library to use the virtualization capabilities
+of recent versions of Linux (and other OSes).
+%endif
+
+%prep
+%setup -q
+
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch37 -p1
+%patch38 -p1
+chmod 755 docs/genaclperms.pl
+%patch39 -p1
+%patch40 -p1
+%patch41 -p1
+%patch42 -p1
+%patch43 -p1
+%patch44 -p1
+%patch45 -p1
+%patch46 -p1
+%patch47 -p1
+%patch48 -p1
+%patch49 -p1
+%patch50 -p1
+%patch51 -p1
+%patch52 -p1
+%patch53 -p1
+%patch54 -p1
+%patch55 -p1
+%patch56 -p1
+%patch57 -p1
+%patch58 -p1
+%patch59 -p1
+%patch60 -p1
+%patch61 -p1
+%patch62 -p1
+%patch63 -p1
+%patch64 -p1
+%patch65 -p1
+%patch66 -p1
+%patch67 -p1
+%patch68 -p1
+%patch69 -p1
+%patch70 -p1
+%patch71 -p1
+%patch72 -p1
+%patch73 -p1
+chmod 755 tests/virsh-uriprecedence
+%patch74 -p1
+%patch75 -p1
+%patch76 -p1
+%patch77 -p1
+%patch78 -p1
+%patch79 -p1
+%patch80 -p1
+%patch81 -p1
+%patch82 -p1
+%patch83 -p1
+%patch84 -p1
+%patch85 -p1
+%patch86 -p1
+%patch87 -p1
+%patch88 -p1
+%patch89 -p1
+%patch90 -p1
+%patch91 -p1
+%patch92 -p1
+%patch93 -p1
+%patch94 -p1
+%patch95 -p1
+%patch96 -p1
+%patch97 -p1
+%patch98 -p1
+%patch99 -p1
+%patch100 -p1
+%patch101 -p1
+%patch102 -p1
+%patch103 -p1
+%patch104 -p1
+%patch105 -p1
+%patch106 -p1
+%patch107 -p1
+%patch108 -p1
+%patch109 -p1
+%patch110 -p1
+%patch111 -p1
+%patch112 -p1
+%patch113 -p1
+%patch114 -p1
+%patch115 -p1
+%patch116 -p1
+%patch117 -p1
+%patch118 -p1
+%patch119 -p1
+%patch120 -p1
+%patch121 -p1
+%patch122 -p1
+%patch123 -p1
+%patch124 -p1
+%patch125 -p1
+%patch126 -p1
+%patch127 -p1
+%patch128 -p1
+%patch129 -p1
+%patch130 -p1
+%patch131 -p1
+%patch132 -p1
+%patch133 -p1
+%patch134 -p1
+%patch135 -p1
+%patch136 -p1
+%patch137 -p1
+%patch138 -p1
+%patch139 -p1
+%patch140 -p1
+%patch141 -p1
+%patch142 -p1
+%patch143 -p1
+%patch144 -p1
+%patch145 -p1
+%patch146 -p1
+%patch147 -p1
+%patch148 -p1
+%patch149 -p1
+%patch150 -p1
+%patch151 -p1
+%patch152 -p1
+%patch153 -p1
+%patch154 -p1
+%patch155 -p1
+%patch156 -p1
+%patch157 -p1
+%patch158 -p1
+%patch159 -p1
+%patch160 -p1
+%patch161 -p1
+%patch162 -p1
+%patch163 -p1
+%patch164 -p1
+%patch165 -p1
+%patch166 -p1
+%patch167 -p1
+%patch168 -p1
+%patch169 -p1
+%patch170 -p1
+%patch171 -p1
+%patch172 -p1
+%patch173 -p1
+%patch174 -p1
+%patch175 -p1
+%patch176 -p1
+%patch177 -p1
+%patch178 -p1
+%patch179 -p1
+%patch180 -p1
+%patch181 -p1
+%patch182 -p1
+%patch183 -p1
+%patch184 -p1
+%patch185 -p1
+%patch186 -p1
+%patch187 -p1
+%patch188 -p1
+%patch189 -p1
+%patch190 -p1
+%patch191 -p1
+%patch192 -p1
+%patch193 -p1
+%patch194 -p1
+%patch195 -p1
+%patch196 -p1
+%patch197 -p1
+%patch198 -p1
+%patch199 -p1
+%patch200 -p1
+%patch201 -p1
+%patch202 -p1
+%patch203 -p1
+%patch204 -p1
+%patch205 -p1
+%patch206 -p1
+%patch207 -p1
+%patch208 -p1
+%patch209 -p1
+%patch210 -p1
+%patch211 -p1
+%patch212 -p1
+%patch213 -p1
+%patch214 -p1
+%patch215 -p1
+%patch216 -p1
+%patch217 -p1
+%patch218 -p1
+%patch219 -p1
+%patch220 -p1
+%patch221 -p1
+%patch222 -p1
+%patch223 -p1
+%patch224 -p1
+%patch225 -p1
+%patch226 -p1
+%patch227 -p1
+%patch228 -p1
+%patch229 -p1
+%patch230 -p1
+%patch231 -p1
+%patch232 -p1
+%patch233 -p1
+%patch234 -p1
+%patch235 -p1
+%patch236 -p1
+%patch237 -p1
+%patch238 -p1
+%patch239 -p1
+%patch240 -p1
+%patch241 -p1
+%patch242 -p1
+%patch243 -p1
+%patch244 -p1
+%patch245 -p1
+%patch246 -p1
+%patch247 -p1
+%patch248 -p1
+%patch249 -p1
+%patch250 -p1
+%patch251 -p1
+%patch252 -p1
+%patch253 -p1
+%patch254 -p1
+%patch255 -p1
+%patch256 -p1
+%patch257 -p1
+%patch258 -p1
+%patch259 -p1
+%patch260 -p1
+%patch261 -p1
+%patch262 -p1
+%patch263 -p1
+%patch264 -p1
+
+
+%build
+%if ! %{with_xen}
+ %define _without_xen --without-xen
+%endif
+
+%if ! %{with_qemu}
+ %define _without_qemu --without-qemu
+%endif
+
+%if ! %{with_openvz}
+ %define _without_openvz --without-openvz
+%endif
+
+%if ! %{with_lxc}
+ %define _without_lxc --without-lxc
+%endif
+
+%if ! %{with_vbox}
+ %define _without_vbox --without-vbox
+%endif
+
+%if ! %{with_xenapi}
+ %define _without_xenapi --without-xenapi
+%endif
+
+%if ! %{with_libxl}
+ %define _without_libxl --without-libxl
+%endif
+
+%if ! %{with_sasl}
+ %define _without_sasl --without-sasl
+%endif
+
+%if ! %{with_avahi}
+ %define _without_avahi --without-avahi
+%endif
+
+%if ! %{with_phyp}
+ %define _without_phyp --without-phyp
+%endif
+
+%if ! %{with_esx}
+ %define _without_esx --without-esx
+%endif
+
+%if ! %{with_hyperv}
+ %define _without_hyperv --without-hyperv
+%endif
+
+%if ! %{with_vmware}
+ %define _without_vmware --without-vmware
+%endif
+
+%if ! %{with_parallels}
+ %define _without_parallels --without-parallels
+%endif
+
+%if ! %{with_polkit}
+ %define _without_polkit --without-polkit
+%endif
+
+%if ! %{with_python}
+ %define _without_python --without-python
+%endif
+
+%if ! %{with_libvirtd}
+ %define _without_libvirtd --without-libvirtd
+%endif
+
+%if ! %{with_uml}
+ %define _without_uml --without-uml
+%endif
+
+%if %{with_rhel5}
+ %define _with_rhel5_api --with-rhel5-api
+%endif
+
+%if ! %{with_interface}
+ %define _without_interface --without-interface
+%endif
+
+%if ! %{with_network}
+ %define _without_network --without-network
+%endif
+
+%if ! %{with_storage_fs}
+ %define _without_storage_fs --without-storage-fs
+%endif
+
+%if ! %{with_storage_lvm}
+ %define _without_storage_lvm --without-storage-lvm
+%endif
+
+%if ! %{with_storage_iscsi}
+ %define _without_storage_iscsi --without-storage-iscsi
+%endif
+
+%if ! %{with_storage_disk}
+ %define _without_storage_disk --without-storage-disk
+%endif
+
+%if ! %{with_storage_mpath}
+ %define _without_storage_mpath --without-storage-mpath
+%endif
+
+%if ! %{with_storage_rbd}
+ %define _without_storage_rbd --without-storage-rbd
+%endif
+
+%if ! %{with_storage_sheepdog}
+ %define _without_storage_sheepdog --without-storage-sheepdog
+%endif
+
+%if ! %{with_numactl}
+ %define _without_numactl --without-numactl
+%endif
+
+%if ! %{with_numad}
+ %define _without_numad --without-numad
+%endif
+
+%if ! %{with_capng}
+ %define _without_capng --without-capng
+%endif
+
+%if ! %{with_fuse}
+ %define _without_fuse --without-fuse
+%endif
+
+%if ! %{with_netcf}
+ %define _without_netcf --without-netcf
+%endif
+
+%if ! %{with_selinux}
+ %define _without_selinux --without-selinux
+%endif
+
+%if ! %{with_hal}
+ %define _without_hal --without-hal
+%endif
+
+%if ! %{with_udev}
+ %define _without_udev --without-udev
+%endif
+
+%if ! %{with_yajl}
+ %define _without_yajl --without-yajl
+%endif
+
+%if ! %{with_sanlock}
+ %define _without_sanlock --without-sanlock
+%endif
+
+%if ! %{with_libpcap}
+ %define _without_libpcap --without-libpcap
+%endif
+
+%if ! %{with_macvtap}
+ %define _without_macvtap --without-macvtap
+%endif
+
+%if ! %{with_audit}
+ %define _without_audit --without-audit
+%endif
+
+%if ! %{with_dtrace}
+ %define _without_dtrace --without-dtrace
+%endif
+
+%if ! %{with_driver_modules}
+ %define _without_driver_modules --without-driver-modules
+%endif
+
+%if %{with_firewalld}
+ %define _with_firewalld --with-firewalld
+%endif
+
+%define when %(date +"%%F-%%T")
+%define where %(hostname)
+%define who %{?packager}%{!?packager:Unknown}
+%define with_packager --with-packager="%{who}, %{when}, %{where}"
+%define with_packager_version --with-packager-version="%{release}"
+
+%if %{with_systemd}
+ %define init_scripts --with-init_script=systemd
+%else
+ %define init_scripts --with-init_script=redhat
+%endif
+
+%if 0%{?enable_autotools}
+ autoreconf -if
+%endif
+
+%if %{with_selinux}
+ %if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+ %define with_selinux_mount --with-selinux-mount="/sys/fs/selinux"
+ %else
+ %define with_selinux_mount --with-selinux-mount="/selinux"
+ %endif
+%endif
+
+%configure %{?_without_xen} \
+ %{?_without_qemu} \
+ %{?_without_openvz} \
+ %{?_without_lxc} \
+ %{?_without_vbox} \
+ %{?_without_libxl} \
+ %{?_without_xenapi} \
+ %{?_without_sasl} \
+ %{?_without_avahi} \
+ %{?_without_polkit} \
+ %{?_without_python} \
+ %{?_without_libvirtd} \
+ %{?_without_uml} \
+ %{?_without_phyp} \
+ %{?_without_esx} \
+ %{?_without_hyperv} \
+ %{?_without_vmware} \
+ %{?_without_parallels} \
+ %{?_without_interface} \
+ %{?_without_network} \
+ %{?_with_rhel5_api} \
+ %{?_without_storage_fs} \
+ %{?_without_storage_lvm} \
+ %{?_without_storage_iscsi} \
+ %{?_without_storage_disk} \
+ %{?_without_storage_mpath} \
+ %{?_without_storage_rbd} \
+ %{?_without_storage_sheepdog} \
+ %{?_without_numactl} \
+ %{?_without_numad} \
+ %{?_without_capng} \
+ %{?_without_fuse} \
+ %{?_without_netcf} \
+ %{?_without_selinux} \
+ %{?_with_selinux_mount} \
+ %{?_without_hal} \
+ %{?_without_udev} \
+ %{?_without_yajl} \
+ %{?_without_sanlock} \
+ %{?_without_libpcap} \
+ %{?_without_macvtap} \
+ %{?_without_audit} \
+ %{?_without_dtrace} \
+ %{?_without_driver_modules} \
+ %{?_with_firewalld} \
+ %{with_packager} \
+ %{with_packager_version} \
+ --with-qemu-user=%{qemu_user} \
+ --with-qemu-group=%{qemu_group} \
+ %{?enable_werror} \
+ %{init_scripts}
+make %{?_smp_mflags}
+gzip -9 ChangeLog
+
+%install
+rm -fr %{buildroot}
+
+# Avoid using makeinstall macro as it changes prefixes rather than setting
+# DESTDIR. Newer make_install macro would be better but it's not available
+# on RHEL 5, thus we need to expand it here.
+make install DESTDIR=%{?buildroot} SYSTEMD_UNIT_DIR=%{_unitdir}
+
+for i in domain-events/events-c dominfo domsuspend hellolibvirt openauth python xml/nwfilter systemtap
+do
+ (cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
+done
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/libvirt/lock-driver/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/libvirt/lock-driver/*.a
+%if %{with_driver_modules}
+rm -f $RPM_BUILD_ROOT%{_libdir}/libvirt/connection-driver/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/libvirt/connection-driver/*.a
+%endif
+
+%if %{with_network}
+install -d -m 0755 $RPM_BUILD_ROOT%{_datadir}/lib/libvirt/dnsmasq/
+# We don't want to install /etc/libvirt/qemu/networks in the main %files list
+# because if the admin wants to delete the default network completely, we don't
+# want to end up re-incarnating it on every RPM upgrade.
+install -d -m 0755 $RPM_BUILD_ROOT%{_datadir}/libvirt/networks/
+cp $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/default.xml \
+ $RPM_BUILD_ROOT%{_datadir}/libvirt/networks/default.xml
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/default.xml
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
+# Strip auto-generated UUID - we need it generated per-install
+sed -i -e "/<uuid>/d" $RPM_BUILD_ROOT%{_datadir}/libvirt/networks/default.xml
+%else
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/default.xml
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
+%endif
+%if ! %{with_qemu}
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd_qemu.aug
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
+%endif
+%find_lang %{name}
+
+%if ! %{with_sanlock}
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirt_sanlock.aug
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirt_sanlock.aug
+%endif
+
+%if ! %{with_lxc}
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd_lxc.aug
+rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd_lxc.aug
+%endif
+
+%if ! %{with_qemu}
+rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu.conf
+rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.qemu
+%endif
+%if ! %{with_lxc}
+rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/lxc.conf
+rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.lxc
+%endif
+%if ! %{with_uml}
+rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.uml
+%endif
+
+mv $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-%{version} \
+ $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-docs-%{version}
+
+%if %{with_dtrace}
+ %ifarch %{power64} s390x x86_64 ia64 alpha sparc64
+mv $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_probes.stp \
+ $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_probes-64.stp
+mv $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_qemu_probes.stp \
+ $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/libvirt_qemu_probes-64.stp
+ %endif
+%endif
+
+%if 0%{?fedora} < 14 && 0%{?rhel} < 6
+rm -f $RPM_BUILD_ROOT%{_prefix}/lib/sysctl.d/libvirtd.conf
+%endif
+
+%clean
+rm -fr %{buildroot}
+
+%check
+cd tests
+make
+# These tests don't current work in a mock build root
+for i in nodeinfotest seclabeltest
+do
+ rm -f $i
+ printf 'int main(void) { return 0; }' > $i.c
+ printf '#!/bin/sh\nexit 0\n' > $i
+ chmod +x $i
+done
+if ! make check VIR_TEST_DEBUG=1
+then
+ cat test-suite.log || true
+ exit 1
+fi
+
+%if %{with_libvirtd}
+%pre daemon
+ %if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+# We want soft static allocation of well-known ids, as disk images
+# are commonly shared across NFS mounts by id rather than name; see
+# https://fedoraproject.org/wiki/Packaging:UsersAndGroups
+getent group kvm >/dev/null || groupadd -f -g 36 -r kvm
+getent group qemu >/dev/null || groupadd -f -g 107 -r qemu
+if ! getent passwd qemu >/dev/null; then
+ if ! getent passwd 107 >/dev/null; then
+ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin -c "qemu user" qemu
+ else
+ useradd -r -g qemu -G kvm -d / -s /sbin/nologin -c "qemu user" qemu
+ fi
+fi
+exit 0
+ %endif
+
+%post daemon
+
+ %if %{with_network}
+# All newly defined networks will have a mac address for the bridge
+# auto-generated, but networks already existing at the time of upgrade
+# will not. We need to go through all the network configs, look for
+# those that don't have a mac address, and add one.
+
+network_files=$( (cd %{_localstatedir}/lib/libvirt/network && \
+ grep -L "mac address" *.xml; \
+ cd %{_sysconfdir}/libvirt/qemu/networks && \
+ grep -L "mac address" *.xml) 2>/dev/null \
+ | sort -u)
+
+for file in $network_files
+do
+ # each file exists in either the config or state directory (or both) and
+ # does not have a mac address specified in either. We add the same mac
+ # address to both files (or just one, if the other isn't there)
+
+ mac4=`printf '%X' $(($RANDOM % 256))`
+ mac5=`printf '%X' $(($RANDOM % 256))`
+ mac6=`printf '%X' $(($RANDOM % 256))`
+ for dir in %{_localstatedir}/lib/libvirt/network \
+ %{_sysconfdir}/libvirt/qemu/networks
+ do
+ if test -f $dir/$file
+ then
+ sed -i.orig -e \
+ "s|\(<bridge.*$\)|\0\n <mac address='52:54:00:$mac4:$mac5:$mac6'/>|" \
+ $dir/$file
+ if test $? != 0
+ then
+ echo "failed to add <mac address='52:54:00:$mac4:$mac5:$mac6'/>" \
+ "to $dir/$file"
+ mv -f $dir/$file.orig $dir/$file
+ else
+ rm -f $dir/$file.orig
+ fi
+ fi
+ done
+done
+ %endif
+
+ %if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_post libvirtd.service
+ %else
+if [ $1 -eq 1 ] ; then
+ # Initial installation
+ /bin/systemctl enable virtlockd.socket >/dev/null 2>&1 || :
+ /bin/systemctl enable libvirtd.service >/dev/null 2>&1 || :
+fi
+ %endif
+ %else
+ %if %{with_cgconfig}
+# Starting with Fedora 16/RHEL-7, systemd automounts all cgroups,
+# and cgconfig is no longer a necessary service.
+ %if (0%{?rhel} && 0%{?rhel} < 7) || (0%{?fedora} && 0%{?fedora} < 16)
+if [ "$1" -eq "1" ]; then
+/sbin/chkconfig cgconfig on
+fi
+ %endif
+ %endif
+
+/sbin/chkconfig --add libvirtd
+if [ "$1" -ge "1" ]; then
+ /sbin/service libvirtd condrestart > /dev/null 2>&1
+fi
+ %endif
+
+%preun daemon
+ %if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_preun libvirtd.service
+ %else
+if [ $1 -eq 0 ] ; then
+ # Package removal, not upgrade
+ /bin/systemctl --no-reload disable virtlockd.socket > /dev/null 2>&1 || :
+ /bin/systemctl --no-reload disable libvirtd.service > /dev/null 2>&1 || :
+ /bin/systemctl stop libvirtd.service > /dev/null 2>&1 || :
+ /bin/systemctl stop virtlockd.service > /dev/null 2>&1 || :
+fi
+ %endif
+ %else
+if [ $1 = 0 ]; then
+ /sbin/service libvirtd stop 1>/dev/null 2>&1
+ /sbin/chkconfig --del libvirtd
+fi
+ %endif
+
+%postun daemon
+ %if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_postun_with_restart libvirtd.service
+ %else
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ] ; then
+ # Package upgrade, not uninstall
+ /bin/systemctl status virtlockd.service >/dev/null 2>&1
+ if [ $? = 1 ] ; then
+ /bin/systemctl kill --signal=USR1 virtlockd.service >/dev/null 2>&1 || :
+ fi
+ /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
+fi
+ %endif
+ %endif
+
+ %if %{with_network}
+%post daemon-config-network
+if test $1 -eq 1 && test ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml ; then
+ UUID=`/usr/bin/uuidgen`
+ sed -e "s,</name>,</name>\n <uuid>$UUID</uuid>," \
+ < %{_datadir}/libvirt/networks/default.xml \
+ > %{_sysconfdir}/libvirt/qemu/networks/default.xml
+ ln -s ../default.xml %{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
+fi
+ %endif
+
+ %if %{with_systemd}
+%triggerun -- libvirt < 0.9.4
+%{_bindir}/systemd-sysv-convert --save libvirtd >/dev/null 2>&1 ||:
+
+# If the package is allowed to autostart:
+/bin/systemctl --no-reload enable libvirtd.service >/dev/null 2>&1 ||:
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del libvirtd >/dev/null 2>&1 || :
+/bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
+ %endif
+%endif # %{with_libvirtd}
+
+%preun client
+
+%if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_preun libvirt-guests.service
+ %endif
+%else
+if [ $1 = 0 ]; then
+ /sbin/chkconfig --del libvirt-guests
+ rm -f /var/lib/libvirt/libvirt-guests
+fi
+%endif
+
+%post client
+
+/sbin/ldconfig
+%if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_post libvirt-guests.service
+ %endif
+%else
+/sbin/chkconfig --add libvirt-guests
+%endif
+
+%postun client
+
+/sbin/ldconfig
+%if %{with_systemd}
+ %if %{with_systemd_macros}
+ %systemd_postun_with_restart libvirt-guests.service
+ %endif
+%triggerun client -- libvirt < 0.9.4
+%{_bindir}/systemd-sysv-convert --save libvirt-guests >/dev/null 2>&1 ||:
+
+# If the package is allowed to autostart:
+/bin/systemctl --no-reload enable libvirt-guests.service >/dev/null 2>&1 ||:
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del libvirt-guests >/dev/null 2>&1 || :
+/bin/systemctl try-restart libvirt-guests.service >/dev/null 2>&1 || :
+%endif
+
+%if %{with_sanlock}
+%post lock-sanlock
+if getent group sanlock > /dev/null ; then
+ chmod 0770 %{_localstatedir}/lib/libvirt/sanlock
+ chown root:sanlock %{_localstatedir}/lib/libvirt/sanlock
+fi
+%endif
+
+%files
+%defattr(-, root, root)
+
+%files docs
+%defattr(-, root, root)
+%doc AUTHORS ChangeLog.gz NEWS README TODO
+
+# Website
+%dir %{_datadir}/doc/libvirt-docs-%{version}
+%dir %{_datadir}/doc/libvirt-docs-%{version}/html
+%{_datadir}/doc/libvirt-docs-%{version}/html/*
+
+# API docs
+%dir %{_datadir}/gtk-doc/html/libvirt/
+%doc %{_datadir}/gtk-doc/html/libvirt/*.devhelp
+%doc %{_datadir}/gtk-doc/html/libvirt/*.html
+%doc %{_datadir}/gtk-doc/html/libvirt/*.png
+%doc %{_datadir}/gtk-doc/html/libvirt/*.css
+
+%if %{with_libvirtd}
+%files daemon
+%defattr(-, root, root)
+
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/
+
+ %if %{with_network}
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/autostart
+ %endif
+
+%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/nwfilter/
+
+ %if %{with_systemd}
+%{_unitdir}/libvirtd.service
+%{_unitdir}/virtlockd.service
+%{_unitdir}/virtlockd.socket
+ %else
+%{_sysconfdir}/rc.d/init.d/libvirtd
+%{_sysconfdir}/rc.d/init.d/virtlockd
+ %endif
+%doc daemon/libvirtd.upstart
+%config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
+%config(noreplace) %{_sysconfdir}/sysconfig/virtlockd
+%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
+%config(noreplace) %{_sysconfdir}/libvirt/virtlockd.conf
+ %if 0%{?fedora} >= 14 || 0%{?rhel} >= 6
+%config(noreplace) %{_prefix}/lib/sysctl.d/libvirtd.conf
+ %endif
+%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
+%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/lxc/
+%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/uml/
+ %if %{with_libxl}
+%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/libxl/
+ %endif
+
+%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd
+ %if %{with_qemu}
+%config(noreplace) %{_sysconfdir}/libvirt/qemu.conf
+%config(noreplace) %{_sysconfdir}/libvirt/qemu-lockd.conf
+%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.qemu
+ %endif
+ %if %{with_lxc}
+%config(noreplace) %{_sysconfdir}/libvirt/lxc.conf
+%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.lxc
+ %endif
+ %if %{with_uml}
+%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.uml
+ %endif
+
+%dir %{_datadir}/libvirt/
+
+ %if %{with_network}
+%dir %{_datadir}/libvirt/networks/
+%{_datadir}/libvirt/networks/default.xml
+ %endif
+
+%ghost %dir %{_localstatedir}/run/libvirt/
+
+%dir %attr(0711, root, root) %{_localstatedir}/lib/libvirt/images/
+%dir %attr(0711, root, root) %{_localstatedir}/lib/libvirt/filesystems/
+%dir %attr(0711, root, root) %{_localstatedir}/lib/libvirt/boot/
+%dir %attr(0711, root, root) %{_localstatedir}/cache/libvirt/
+
+ %if %{with_qemu}
+%ghost %dir %attr(0700, root, root) %{_localstatedir}/run/libvirt/qemu/
+%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}/cache/libvirt/qemu/
+ %endif
+ %if %{with_lxc}
+%ghost %dir %{_localstatedir}/run/libvirt/lxc/
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/lxc/
+ %endif
+ %if %{with_uml}
+%ghost %dir %{_localstatedir}/run/libvirt/uml/
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/uml/
+ %endif
+ %if %{with_libxl}
+%ghost %dir %{_localstatedir}/run/libvirt/libxl/
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/libxl/
+ %endif
+ %if %{with_xen}
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/xen/
+ %endif
+ %if %{with_network}
+%ghost %dir %{_localstatedir}/run/libvirt/network/
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/network/
+%dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/dnsmasq/
+ %endif
+
+%dir %attr(0755, root, root) %{_libdir}/libvirt/lock-driver
+%attr(0755, root, root) %{_libdir}/libvirt/lock-driver/lockd.so
+
+ %if %{with_qemu}
+%{_datadir}/augeas/lenses/libvirtd_qemu.aug
+%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
+ %endif
+
+ %if %{with_lxc}
+%{_datadir}/augeas/lenses/libvirtd_lxc.aug
+%{_datadir}/augeas/lenses/tests/test_libvirtd_lxc.aug
+ %endif
+
+%{_datadir}/augeas/lenses/libvirtd.aug
+%{_datadir}/augeas/lenses/tests/test_libvirtd.aug
+%{_datadir}/augeas/lenses/virtlockd.aug
+%{_datadir}/augeas/lenses/tests/test_virtlockd.aug
+%{_datadir}/augeas/lenses/libvirt_lockd.aug
+%{_datadir}/augeas/lenses/tests/test_libvirt_lockd.aug
+
+ %if %{with_polkit}
+ %if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
+%{_datadir}/polkit-1/actions/org.libvirt.unix.policy
+%{_datadir}/polkit-1/actions/org.libvirt.api.policy
+ %else
+%{_datadir}/PolicyKit/policy/org.libvirt.unix.policy
+ %endif
+ %endif
+
+%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/
+
+ %if %{with_lxc}
+%attr(0755, root, root) %{_libexecdir}/libvirt_lxc
+ %endif
+
+ %if %{with_storage_disk}
+%attr(0755, root, root) %{_libexecdir}/libvirt_parthelper
+ %endif
+
+%attr(0755, root, root) %{_libexecdir}/libvirt_iohelper
+%attr(0755, root, root) %{_sbindir}/libvirtd
+%attr(0755, root, root) %{_sbindir}/virtlockd
+
+%{_mandir}/man8/libvirtd.8*
+%{_mandir}/man8/virtlockd.8*
+
+ %if %{with_driver_modules}
+ %if %{with_network}
+%files daemon-config-network
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_nwfilter}
+%files daemon-config-nwfilter
+%defattr(-, root, root)
+%{_sysconfdir}/libvirt/nwfilter/*.xml
+ %endif
+
+ %if %{with_interface}
+%files daemon-driver-interface
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_interface.so
+ %endif
+
+ %if %{with_network}
+%files daemon-driver-network
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_network.so
+ %endif
+
+ %if %{with_nodedev}
+%files daemon-driver-nodedev
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_nodedev.so
+ %endif
+
+ %if %{with_nwfilter}
+%files daemon-driver-nwfilter
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_nwfilter.so
+ %endif
+
+%files daemon-driver-secret
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_secret.so
+
+ %if %{with_storage}
+%files daemon-driver-storage
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_storage.so
+ %endif
+
+ %if %{with_qemu}
+%files daemon-driver-qemu
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_qemu.so
+ %endif
+
+ %if %{with_lxc}
+%files daemon-driver-lxc
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_lxc.so
+ %endif
+
+ %if %{with_uml}
+%files daemon-driver-uml
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_uml.so
+ %endif
+
+ %if %{with_xen}
+%files daemon-driver-xen
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_xen.so
+ %endif
+
+ %if %{with_libxl}
+%files daemon-driver-libxl
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_libxl.so
+ %endif
+
+ %if %{with_vbox}
+%files daemon-driver-vbox
+%defattr(-, root, root)
+%{_libdir}/%{name}/connection-driver/libvirt_driver_vbox.so
+ %endif
+ %endif # %{with_driver_modules}
+
+ %if %{with_qemu_tcg}
+%files daemon-qemu
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_qemu_kvm}
+%files daemon-kvm
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_lxc}
+%files daemon-lxc
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_uml}
+%files daemon-uml
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_xen} || %{with_libxl}
+%files daemon-xen
+%defattr(-, root, root)
+ %endif
+
+ %if %{with_vbox}
+%files daemon-vbox
+%defattr(-, root, root)
+ %endif
+%endif # %{with_libvirtd}
+
+%if %{with_sanlock}
+%files lock-sanlock
+%defattr(-, root, root)
+ %if %{with_qemu}
+%config(noreplace) %{_sysconfdir}/libvirt/qemu-sanlock.conf
+ %endif
+%attr(0755, root, root) %{_libdir}/libvirt/lock-driver/sanlock.so
+%{_datadir}/augeas/lenses/libvirt_sanlock.aug
+%{_datadir}/augeas/lenses/tests/test_libvirt_sanlock.aug
+%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/sanlock
+%{_sbindir}/virt-sanlock-cleanup
+%{_mandir}/man8/virt-sanlock-cleanup.8*
+%attr(0755, root, root) %{_libexecdir}/libvirt_sanlock_helper
+%endif
+
+%files client -f %{name}.lang
+%defattr(-, root, root)
+%doc COPYING COPYING.LESSER
+
+%config(noreplace) %{_sysconfdir}/libvirt/libvirt.conf
+%{_mandir}/man1/virsh.1*
+%{_mandir}/man1/virt-xml-validate.1*
+%{_mandir}/man1/virt-pki-validate.1*
+%{_mandir}/man1/virt-host-validate.1*
+%{_bindir}/virsh
+%{_bindir}/virt-xml-validate
+%{_bindir}/virt-pki-validate
+%{_bindir}/virt-host-validate
+%{_libdir}/lib*.so.*
+
+%if %{with_dtrace}
+%{_datadir}/systemtap/tapset/libvirt_probes*.stp
+%{_datadir}/systemtap/tapset/libvirt_qemu_probes*.stp
+%{_datadir}/systemtap/tapset/libvirt_functions.stp
+%endif
+
+%dir %{_datadir}/libvirt/
+%dir %{_datadir}/libvirt/schemas/
+
+%{_datadir}/libvirt/schemas/basictypes.rng
+%{_datadir}/libvirt/schemas/capability.rng
+%{_datadir}/libvirt/schemas/domain.rng
+%{_datadir}/libvirt/schemas/domaincommon.rng
+%{_datadir}/libvirt/schemas/domainsnapshot.rng
+%{_datadir}/libvirt/schemas/interface.rng
+%{_datadir}/libvirt/schemas/network.rng
+%{_datadir}/libvirt/schemas/networkcommon.rng
+%{_datadir}/libvirt/schemas/nodedev.rng
+%{_datadir}/libvirt/schemas/nwfilter.rng
+%{_datadir}/libvirt/schemas/secret.rng
+%{_datadir}/libvirt/schemas/storageencryption.rng
+%{_datadir}/libvirt/schemas/storagefilefeatures.rng
+%{_datadir}/libvirt/schemas/storagepool.rng
+%{_datadir}/libvirt/schemas/storagevol.rng
+
+%{_datadir}/libvirt/cpu_map.xml
+%{_datadir}/libvirt/libvirtLogo.png
+
+%if %{with_systemd}
+%{_unitdir}/libvirt-guests.service
+%else
+%{_sysconfdir}/rc.d/init.d/libvirt-guests
+%endif
+%config(noreplace) %{_sysconfdir}/sysconfig/libvirt-guests
+%attr(0755, root, root) %{_libexecdir}/libvirt-guests.sh
+%dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/
+
+%if %{with_sasl}
+%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
+%endif
+
+%if %{with_lxc}
+%files login-shell
+%attr(4755, root, root) %{_bindir}/virt-login-shell
+%config(noreplace) %{_sysconfdir}/libvirt/virt-login-shell.conf
+%{_mandir}/man1/virt-login-shell.1*
+%endif
+
+%files devel
+%defattr(-, root, root)
+
+%{_libdir}/lib*.so
+%dir %{_includedir}/libvirt
+%{_includedir}/libvirt/*.h
+%{_libdir}/pkgconfig/libvirt.pc
+
+%dir %{_datadir}/libvirt/api/
+%{_datadir}/libvirt/api/libvirt-api.xml
+%{_datadir}/libvirt/api/libvirt-qemu-api.xml
+%{_datadir}/libvirt/api/libvirt-lxc-api.xml
+
+%doc docs/*.html docs/html docs/*.gif
+%doc docs/libvirt-api.xml
+%doc examples/hellolibvirt
+%doc examples/domain-events/events-c
+%doc examples/dominfo
+%doc examples/domsuspend
+%doc examples/openauth
+%doc examples/xml
+%doc examples/systemtap
+
+%if %{with_python}
+%files python
+%defattr(-, root, root)
+
+%{_libdir}/python*/site-packages/libvirt.py*
+%{_libdir}/python*/site-packages/libvirt_qemu.py*
+%{_libdir}/python*/site-packages/libvirt_lxc.py*
+%{_libdir}/python*/site-packages/libvirtmod*
+%doc examples/python
+%doc examples/domain-events/events-python
+%endif
+
+%changelog
+* Fri Nov 8 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-12
+- virpci: Don't error on unbinded devices (rhbz#1019387)
+- network: Fix connections count in case of allocate failure (rhbz#1020135)
+- qemu: Clean up migration ports when migration cancelled (rhbz#1019237)
+- qemuMigrationBeginPhase: Check for 'drive-mirror' for NBD (rhbz#1022393)
+- Allow root directory in filesystem source dir schema (rhbz#1028107)
+- Use a port from the migration range for NBD as well (rhbz#1025699)
+- qemu: Avoid double free of VM (rhbz#1018267)
+- util: Use size_t instead of unsigned int for num_virtual_functions (rhbz#1025397)
+- pci: Properly handle out-of-order SRIOV virtual functions (rhbz#1025397)
+- conf: Do better job when comparing features ABI compatibility (rhbz#1008989)
+- schema: Rename option 'hypervtristate' to 'featurestate' (rhbz#1008989)
+- conf: Mark user provided strings in error messages when parsing XML (rhbz#1008989)
+- cpu: Add support for loading and storing CPU data (rhbz#1008989)
+- cpu: x86: Rename struct cpuX86cpuid as virCPUx86CPUID (rhbz#1008989)
+- cpu: x86: Rename struct cpuX86Data as virCPUx86Data (rhbz#1008989)
+- cpu: x86: Rename x86DataFree() as virCPUx86DataFree() (rhbz#1008989)
+- Ensure 'arch' is always set in cpuArchNodeData (rhbz#1008989)
+- cpu: x86: Rename x86MakeCPUData as virCPUx86MakeData (rhbz#1008989)
+- cpu: x86: Rename x86DataAddCpuid as virCPUx86DataAddCPUID (rhbz#1008989)
+- cpu: x86: Rename data_iterator and DATA_ITERATOR_INIT (rhbz#1008989)
+- cpu: x86: Fix return types of x86cpuidMatch and x86cpuidMatchMasked (rhbz#1008989)
+- cpu: x86: Use whitespace to clarify context and use consistent labels (rhbz#1008989)
+- cpu: x86: Clean up error messages in x86VendorLoad() (rhbz#1008989)
+- cpu: Export few x86-specific APIs (rhbz#1008989)
+- cpu: x86: Parse the CPU feature map only once (rhbz#1008989)
+- cpu_x86: Refactor storage of CPUID data to add support for KVM features (rhbz#1008989)
+- qemu: Add monitor APIs to fetch CPUID data from QEMU (rhbz#1008989)
+- cpu: x86: Add internal CPUID features support and KVM feature bits (rhbz#1008989)
+- conf: Refactor storing and usage of feature flags (rhbz#1008989)
+- qemu: Add support for paravirtual spinlocks in the guest (rhbz#1008989)
+- qemu: process: Validate specific CPUID flags of a guest (rhbz#1008989)
+
+* Fri Nov 1 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-11
+- Add helpers for getting env vars in a setuid environment (rhbz#1015247)
+- Only allow 'stderr' log output when running setuid (CVE-2013-4400)
+- Close all non-stdio FDs in virt-login-shell (CVE-2013-4400)
+- Don't link virt-login-shell against libvirt.so (CVE-2013-4400)
+- build: Fix linking virt-login-shell (rhbz#1015247)
+- build: Fix build of virt-login-shell on systems with older gnutls (rhbz#1015247)
+- Set a sane $PATH for virt-login-shell (rhbz#1015247)
+- spec: Fix rpm build when lxc disabled (rhbz#1015247)
+- Move virt-login-shell into libvirt-login-shell sub-RPM (rhbz#1015247)
+- Make virCommand env handling robust in setuid env (rhbz#1015247)
+- Remove all direct use of getenv (rhbz#1015247)
+- Block all use of getenv with syntax-check (rhbz#1015247)
+- Only allow the UNIX transport in remote driver when setuid (rhbz#1015247)
+- Don't allow remote driver daemon autostart when running setuid (rhbz#1015247)
+- Add stub getegid impl for platforms lacking it (rhbz#1015247)
+- Remove (nearly) all use of getuid()/getgid() (rhbz#1015247)
+- Block all use of libvirt.so in setuid programs (rhbz#1015247)
+- spec: Clean up distribution of ChangeLog (and others) (rhbz#1024393)
+- Push RPM deps down into libvirt-daemon-driver-XXXX sub-RPMs (rhbz#1024393)
+
+* Wed Oct 23 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-10
+- qemu_process: Make qemuProcessReadLog() more versatile and reusable (rhbz#1001738)
+- qemu: monitor: Add infrastructure to access VM logs for better err msgs (rhbz#1001738)
+- qemu: monitor: Produce better errors on monitor hangup (rhbz#1001738)
+- qemu: Wire up better early error reporting (rhbz#1001738)
+- qemu: process: Silence coverity warning when rewinding log file (rhbz#1001738)
+- qemu: hostdev: Refactor PCI passhrough handling (rhbz#1001738)
+- qemu: hostdev: Fix function spacing and header formatting (rhbz#1001738)
+- qemu: hostdev: Add checks if PCI passthrough is available in the host (rhbz#1001738)
+- qemu: Prefer VFIO for PCI device passthrough (rhbz#1001738)
+- qemu: Init @pcidevs in qemuPrepareHostdevPCIDevices (rhbz#1001738)
+- Fix max stream packet size for old clients (rhbz#950416)
+- Adjust legacy max payload size to account for header information (rhbz#950416)
+- rpc: Correct the wrong payload size checking (rhbz#950416)
+- qemu: Simplify calling qemuDomainHostdevNetConfigRestore (rhbz#1005682)
+- qemu: Move qemuDomainRemoveNetDevice to avoid forward reference (rhbz#1005682)
+- qemu: Fix removal of <interface type='hostdev'> (rhbz#1005682)
+- remote: Fix regression in event deregistration (rhbz#1020376)
+- qemu: managedsave: Add support for compressing managed save images (rhbz#1017227)
+- qemu: snapshot: Add support for compressing external snapshot memory (rhbz#1017227)
+- Migration: Introduce VIR_MIGRATE_PARAM_LISTEN_ADDRESS (rhbz#1015215)
+- virsocket: Introduce virSocketAddrIsWildcard (rhbz#1015215)
+- qemu: Implement support for VIR_MIGRATE_PARAM_LISTEN_ADDRESS (rhbz#1015215)
+- qemu_conf: Introduce "migration_address" (rhbz#1015215)
+- qemu: Include listenAddress in debug prints (rhbz#1015215)
+- docs: Expand description of host-model CPU mode (rhbz#1014682)
+- qemu: Avoid assigning unavailable migration ports (rhbz#1019237)
+- qemu: Make migration port range configurable (rhbz#1019237)
+- qemu: Fix augeas support for migration ports (rhbz#1019237)
+- Fix perms for virConnectDomainXML{To, From}Native (CVE-2013-4401)
+
+* Tue Oct 15 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-9
+- virNetDevBandwidthEqual: Make it more robust (rhbz#1014503)
+- qemu_hotplug: Allow QoS update in qemuDomainChangeNet (rhbz#1014503)
+- qemu: Check actual netdev type rather than config netdev type during init (rhbz#1012824)
+- Fix crash in libvirtd when events are registered & ACLs active (CVE-2013-4399) (rhbz#1011429)
+- Remove virConnectPtr arg from virNWFilterDefParse* (rhbz#1015108)
+- Don't pass virConnectPtr in nwfilter 'struct domUpdateCBStruct' (rhbz#1015108)
+- Remove use of virConnectPtr from all remaining nwfilter code (rhbz#1015108)
+- Don't set netdev offline in container cleanup (rhbz#1014604)
+- Avoid reporting an error if veth device is already deleted (rhbz#1014604)
+- Avoid deleting NULL veth device name (rhbz#1014604)
+- Retry veth device creation on failure (rhbz#1014604)
+- Use 'vnet' as prefix for veth devices (rhbz#1014604)
+- Free cmd in virNetDevVethDelete (rhbz#1014604)
+- Free cmd in virNetDevVethCreate (rhbz#1014604)
+- LXC: Fix handling of RAM filesystem size units (rhbz#1015689)
+- build: Add lxc testcase to dist list (rhbz#1015689)
+- tests: Work with older dbus (rhbz#1018730)
+- virdbus: Add virDBusHasSystemBus() (rhbz#1018730)
+- virsystemd: Don't fail to start VM if DBus isn't available or compiled in (rhbz#1018730)
+- DBus: Introduce virDBusIsServiceEnabled (rhbz#1018730)
+- Change way we fake dbus method calls (rhbz#1018730)
+- Fix virsystemdtest for previous commit (rhbz#1018730)
+- LXC: Workaround machined uncleaned data with containers running systemd. (rhbz#1018730)
+- Allow use of a private dbus bus connection (rhbz#998365)
+- Add a method for closing the dbus system bus connection (rhbz#998365)
+- Make LXC controller use a private dbus connection & close it (rhbz#998365)
+- Fix flaw in detecting log format (rhbz#927072)
+- Fix exit status of lxc controller (rhbz#927072)
+- Improve error reporting with LXC controller (rhbz#927072)
+- nwfilter: Don't fail to start if DBus isn't available (rhbz#927072)
+- Don't ignore all dbus connection errors (rhbz#927072)
+- LXC: Check the existence of dir before resolving symlinks (rhbz#927072)
+- Ensure lxcContainerMain reports errors on stderr (rhbz#927072)
+- Ensure lxcContainerResolveSymlinks reports errors (rhbz#927072)
+- Improve log filtering in virLXCProcessReadLogOutputData (rhbz#927072)
+- Initialize threading & error layer in LXC controller (rhbz#1018725)
+- qemu_migration: Avoid crashing if domain dies too quickly (rhbz#1018267)
+- Convert uuid to a string before printing it (rhbz#1019023)
+
+* Wed Oct 2 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-8
+- conf: Don't crash on invalid chardev source definition of RNGs and other (rhbz#1012196)
+- rpc: Increase bound limit for virDomainGetJobStats (rhbz#1012818)
+- qemu: Free all driver data in qemuStateCleanup (rhbz#1011330)
+- qemu: Don't leak reference to virQEMUDriverConfigPtr (rhbz#1011330)
+- qemu: Eliminate redundant if clauses in qemuCollectPCIAddress (rhbz#1003983)
+- qemu: Allow some PCI devices to be attached to PCIe slots (rhbz#1003983)
+- qemu: Replace multiple strcmps with a switch on an enum (rhbz#1003983)
+- qemu: Support ich9-intel-hda audio device (rhbz#1003983)
+- qemu: Turn if into switch in qemuDomainValidateDevicePCISlotsQ35 (rhbz#1003983)
+- qemu: Prefer to put a Q35 machine's dmi-to-pci-bridge at 00:1E.0 (rhbz#1003983)
+
+* Wed Sep 25 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-7
+- Fix crash in remoteDispatchDomainMemoryStats (CVE-2013-4296)
+- LXC: Don't mount securityfs when user namespace enabled (rhbz#872648)
+- Move array of mounts out of lxcContainerMountBasicFS (rhbz#872648)
+- Ensure root filesystem is recursively mounted readonly (rhbz#872648)
+- qemu: Fix seamless SPICE migration (rhbz#1010861)
+- qemu: Use "ide" as device name for implicit SATA controller on Q35 (rhbz#1008903)
+- qemu: Only parse basename when determining emulator properties (rhbz#1010617)
+- qemu: Recognize -machine accel=kvm when parsing native (rhbz#1010617)
+- qemu: Don't leave shutdown inhibited on attach failure (rhbz#1010617)
+- qemu: Don't leak vm on failure (rhbz#1010617)
+- Fix typo in identity code which is pre-requisite for CVE-2013-4311 (rhbz#1006272)
+
+* Thu Sep 19 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-6
+- Also store user & group ID values in virIdentity (rhbz#1006272)
+- Ensure system identity includes process start time (rhbz#1006272)
+- Add support for using 3-arg pkcheck syntax for process (CVE-2013-4311)
+- Free slicename in virSystemdCreateMachine (rhbz#1008619)
+- qemu: Fix checking of ABI stability when restoring external checkpoints (rhbz#1008340)
+- qemu: Use "migratable" XML definition when doing external checkpoints (rhbz#1008340)
+- qemu: Fix memleak after commit 59898a88ce8431bd3ea249b8789edc2ef9985827 (rhbz#1008340)
+- qemu: Avoid dangling job in qemuDomainSetBlockIoTune (rhbz#700443)
+
+* Sat Sep 14 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-5
+- Pass AM_LDFLAGS to driver modules too (rhbz#1006299)
+- virsh domjobinfo: Do not return 1 if job is NONE (rhbz#1006864)
+- Fix polkit permission names for storage pools, vols & node devices (rhbz#700443)
+- Fix naming of permission for detecting storage pools (rhbz#700443)
+- security: Provide supplemental groups even when parsing label (CVE-2013-4291) (rhbz#1006513)
+- virFileNBDDeviceAssociate: Avoid use of uninitialized variable (CVE-2013-4297)
+- Rename "struct interface_driver" to virNetcfDriverState (rhbz#983026)
+- netcf driver: Use a single netcf handle for all connections (rhbz#983026)
+- virDomainDefParseXML: Set the argument of virBitmapFree to NULL after calling virBitmapFree (rhbz#1006722)
+- Add test for the nodemask double free crash (rhbz#1006722)
+- qemu: Fix checking of guest ABI compatibility when reverting snapshots (rhbz#1006886)
+
+* Fri Sep 6 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-4
+- Don't crash in qemuBuildDeviceAddressStr (rhbz#1003526)
+- Fix leaks in python bindings (rhbz#1003828)
+- Process virtlockd.conf instead of libvirtd.conf (rhbz#1003685)
+- test_virtlockd.aug.in: Use the correct file (rhbz#1003685)
+- qemu: Make domain renaming work during migration (rhbz#999352)
+- qemu: Handle huge number of queues correctly (rhbz#651941)
+- conf: Remove the actual hostdev when removing a network (rhbz#1003537)
+- conf: Don't deref NULL actual network in virDomainNetGetActualHostdev() (rhbz#1003537)
+- python: Fix a PyList usage mistake (rhbz#1002558)
+- Add '<nat>' element to '<forward>' network schemas (rhbz#1004364)
+- Always specify qcow2 compat level on qemu-img command line (rhbz#997977)
+- selinux: Distinguish failure to label from request to avoid label (rhbz#924153)
+- selinux: Enhance test to cover nfs label failure (rhbz#924153)
+
+* Fri Aug 30 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-3
+- RPC: Don't accept client if it would overcommit max_clients (rhbz#981729)
+- Introduce max_queued_clients (rhbz#981729)
+- conf: Add default USB controller in qemu post-parse callback (rhbz#819968)
+- qemu: Rename some functions in qemu_command.c (rhbz#819968)
+- qemu: Eliminate almost-duplicate code in qemu_command.c (rhbz#819968)
+- qemu: Enable auto-allocate of all PCI addresses (rhbz#819968)
+- qemu: Add pcie-root controller (rhbz#819968)
+- qemu: Add dmi-to-pci-bridge controller (rhbz#819968)
+- qemu: Fix handling of default/implicit devices for q35 (rhbz#819968)
+- qemu: Properly set/use device alias for pci controllers (rhbz#819968)
+- qemu: Enable using implicit sata controller in q35 machines (rhbz#819968)
+- qemu: Improve error reporting during PCI address validation (rhbz#819968)
+- qemu: Refactor qemuDomainCheckDiskPresence for only disk presence check (rhbz#910171)
+- qemu: Add helper functions for diskchain checking (rhbz#910171)
+- qemu: Check presence of each disk and its backing file as well (rhbz#910171)
+- conf: Add startupPolicy attribute for harddisk (rhbz#910171)
+- qemu: Support to drop disk with 'optional' startupPolicy (rhbz#910171)
+- Split TLS test into two separate tests (rhbz#994158)
+- Avoid re-generating certs every time (rhbz#994158)
+- Change data passed into TLS test cases (rhbz#994158)
+- Fix validation of CA certificate chains (rhbz#994158)
+- Fix parallel runs of TLS test suites (rhbz#994158)
+- tests: Fix parallel runs of TLS test suites (rhbz#994158)
+- Add a man page for virtlockd daemon (rhbz#991494)
+- Add an example config file for virtlockd (rhbz#991494)
+- Properly handle -h / -V for --help/--version aliases in virtlockd/libvirtd (rhbz#991494)
+- Make check for /dev/loop device names stricter to avoid /dev/loop-control (rhbz#924815)
+- Ensure securityfs is mounted readonly in container (rhbz#872642)
+- Add info about access control checks into API reference (rhbz#700443)
+- Record the where the auto-generated data comes from (rhbz#700443)
+- Add documentation for access control system (rhbz#700443)
+- virsh-domain: Flip logic in cmdSetvcpus (rhbz#996552)
+- Honour root prefix in lxcContainerMountFSBlockAuto (rhbz#924815)
+- util: Add virGetUserDirectoryByUID (rhbz#988491)
+- Introduce a virt-login-shell binary (rhbz#988491)
+- build: Fix compilation of virt-login-shell.c (rhbz#988491)
+- Fix double-free and broken logic in virt-login-shell (rhbz#988491)
+- Address missed feedback from review of virt-login-shell (rhbz#988491)
+- Ensure that /dev exists in the container root filesystem (rhbz#924815)
+- remote: Fix a segfault in remoteDomainCreateWithFlags (rhbz#994855)
+- build: Avoid -lgcrypt with newer gnutls (rhbz#951637)
+- virnettlscontext: Resolve Coverity warnings (UNINIT) (rhbz#994158)
+- build: Fix missing max_queued_clients in augeas test file for libvirtd.conf (rhbz#981729)
+- virsh-domain: Fix memleak in cmdCPUBaseline (rhbz#997798)
+- Fix typo in domain name in polkit acl example (rhbz#700443)
+- Update polkit examples to use 'lookup' method (rhbz#700443)
+- Add bounds checking on virDomainMigrate*Params RPC calls (CVE-2013-4292) (rhbz#1002667)
+- Add bounds checking on virDomainGetJobStats RPC call (rhbz#1002667)
+- Add bounds checking on virDomain{SnapshotListAllChildren, ListAllSnapshots} RPC calls (rhbz#1002667)
+- Add bounds checking on virConnectListAllDomains RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllStoragePools RPC call (rhbz#1002667)
+- Add bounds checking on virStoragePoolListAllVolumes RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllNetworks RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllInterfaces RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllNodeDevices RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllNWFilters RPC call (rhbz#1002667)
+- Add bounds checking on virConnectListAllSecrets RPC call (rhbz#1002667)
+- Prohibit unbounded arrays in XDR protocols (rhbz#1002667)
+- virbitmap: Refactor virBitmapParse to avoid access beyond bounds of array (rhbz#997906)
+- virbitmaptest: Fix function header formatting (rhbz#997906)
+- virbitmaptest: Add test for out of bounds condition (rhbz#997906)
+- virsh-domain: Fix memleak in cmdUndefine with storage (rhbz#999057)
+- virsh: Modify vshStringToArray to duplicate the elements too (rhbz#999057)
+- virsh: Don't leak list of volumes when undefining domain with storage (rhbz#999057)
+- Fix URI connect precedence (rhbz#999323)
+- tests: Add URI precedence checking (rhbz#999323)
+- Don't free NULL network in cmdNetworkUpdate (rhbz#1001094)
+- virsh: Fix debugging (rhbz#1001628)
+- qemu: Remove hostdev entry when freeing the depending network entry (rhbz#1002669)
+- Set security label on FD for virDomainOpenGraphics (rhbz#999925)
+- virsh: Free the caps list properly if one of them is invalid (rhbz#1001957)
+- virsh: Free the formatting string when listing pool details (rhbz#1001957)
+- virsh-pool.c: Don't jump over variable declaration (rhbz#1001957)
+- virsh: Free the list from ListAll APIs even for 0 items (rhbz#1001957)
+- virsh: Free messages after logging them to a file (rhbz#1001957)
+- Reverse logic allowing partial DHCP host XML (rhbz#1001078)
+- virsh: Print cephx and iscsi usage (rhbz#1000155)
+- qemu_conf: Fix broken logic for adding passthrough iscsi lun (rhbz#1000159)
+- Report secret usage error message similarly (rhbz#1000168)
+- docs: Update the formatdomain disk examples (rhbz#1000169)
+- docs: Update formatsecrets to include more examples of each type (rhbz#1000169)
+- docs: Update iSCSI storage pool example (rhbz#1000169)
+- docs: Reformat <disk> attribute description in formatdomain (rhbz#1000169)
+- qemuBuildNicDevStr: Add mq=on for multiqueue networking (rhbz#651941)
+- migration: Do not restore labels on failed migration (rhbz#822052)
+- qemu: Drop qemuDomainMemoryLimit (rhbz#1001143)
+- docs: Discourage users to set hard_limit (rhbz#1001143)
+- docs: Clean 09adfdc62de2b up (rhbz#1001143)
+- qemuSetupMemoryCgroup: Handle hard_limit properly (rhbz#1001143)
+- qemuBuildCommandLine: Fall back to mem balloon if there's no hard_limit (rhbz#1001143)
+- qemuDomainAttachHostPciDevice: Fall back to mem balloon if there's no hard_limit (rhbz#1001143)
+
+* Fri Aug 2 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-2
+- spec: Change --enable-werror handling to match upstream
+- Delete obsolete / unused python test files (rhbz#884103)
+- Remove reference to python/tests from RPM %doc (rhbz#884103)
+- spec: Explicitly claim ownership of channel subdir (rhbz#884103)
+- Add APIs for formatting systemd slice/scope names (rhbz#980929)
+- Add support for systemd cgroup mount (rhbz#980929)
+- Cope with races while killing processes (rhbz#980929)
+- Enable support for systemd-machined in cgroups creation (rhbz#980929)
+- Ensure LXC/QEMU APIs set the filename for errors (rhbz#991348)
+- Avoid crash if NULL is passed for filename/funcname in logging (rhbz#991348)
+
+* Tue Jul 30 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.1-1
+- Rebased to libvirt-1.1.1
+
+* Fri Jul 12 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.0-2
+- qemu: Fix double free in qemuMigrationPrepareDirect (rhbz#977961)
+- Fix crash when multiple event callbacks were registered (CVE-2013-2230)
+- Paused domain should remain paused after migration (rhbz#981139)
+
+* Mon Jul 1 2013 Jiri Denemark <jdenemar@redhat.com> - 1.1.0-1
+- Rebased to libvirt-1.1.0
+
+* Mon Jun 3 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.6-1
+- Rebased to libvirt-1.0.6
+
+* Mon May 13 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.5-2
+- virInitctlRequest: Don't hardcode 384 bytes size
+- network: Fix network driver startup for qemu:///session
+- virInitctlRequest: Unbreak make syntax check
+- virInitctlRequest: Unbreak make syntax check
+- build: Always include sanitytest in tarball
+- qemu: Fix stupid typos in VFIO cgroup setup/teardown
+- build: Always include libvirt_lxc.syms in tarball
+- build: Clean up stray files found by 'make distcheck'
+- spec: Proper soft static allocation of qemu uid
+- Fix F_DUPFD_CLOEXEC operation args
+- build: Fix mingw build of virprocess.c
+- Fix potential use of undefined variable in remote dispatch code
+- build: Avoid non-portable cast of pthread_t
+- Fix release of resources with lockd plugin
+- Fixup rpcgen code on kFreeBSD too
+- Make detect_scsi_host_caps a function on all architectures
+- qemu: Allocate network connections sooner during domain startup
+- tests: Files named '.*-invalid.xml' should fail validation
+- conf: Don't crash on a tpm device with no backends
+- Don't mention disk controllers in generic controller errors
+- iscsi: Don't leak portal string when starting a pool
+- util: Fix virFileOpenAs return value and resulting error logs
+
+* Thu May 2 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.5-1
+- Rebased to libvirt-1.0.5
+
+* Fri Apr 19 2013 Daniel Mach <dmach@redhat.com> - 1.0.4-1.1
+- Rebuild for cyrus-sasl
+
+* Mon Apr 8 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.4-1
+- Rebased to libvirt-1.0.4
+
+* Mon Apr 08 2013 Richard W.M. Jones <rjones@redhat.com> - 1.0.3-2
+- Rebuild against gnutls 3.
+
+* Tue Mar 5 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.3-1
+- Rebased to libvirt-1.0.3
+
+* Thu Jan 31 2013 Jiri Denemark <jdenemar@redhat.com> - 1.0.2-1
+- Rebased to libvirt-1.0.2
+
+* Tue Dec 18 2012 Jiri Denemark <jdenemar@redhat.com> - 1.0.1-1
+- Rebased to libvirt-1.0.1
+
+* Wed Nov 14 2012 Jiri Denemark <jdenemar@redhat.com> - 1.0.0-1
+- Rebased to libvirt-1.0.0
+
+* Tue Oct 30 2012 Cole Robinson <crobinso@redhat.com> - 0.10.2.1-2
+- Disable libxl on F18 too
+
+* Sat Oct 27 2012 Cole Robinson <crobinso@redhat.com> - 0.10.2.1-1
+- Rebased to version 0.10.2.1
+- Fix lvm volume creation when alloc=0 (bz #866481)
+- Clarify virsh send-keys man page example (bz #860004)
+- Fix occasional deadlock via virDomainDestroy (bz #859009)
+- Fix LXC deadlock from ctrl-c (bz #848119)
+- Fix occasional selinux denials with macvtap (bz #798605)
+- Fix multilib conflict with systemtap files (bz #831425)
+- Don't trigger keytab warning in system logs (bz #745203)
+- Fix qemu domxml-2-native NIC model out (bz #636832)
+- Fix error message if not enough space for lvm vol (bz #609104)
+
+* Thu Oct 25 2012 Cole Robinson <crobinso@redhat.com> - 0.10.2-4
+- Disable libxl driver, since it doesn't build with xen 4.2 in rawhide
+
+* Mon Sep 24 2012 Richard W.M. Jones <rjones@redhat.com> - 0.10.2-3
+- Re-add Use-qemu-system-i386-as-binary-instead-of-qemu.patch
+ NB: This patch is Fedora-specific and not upstream.
+- Add upstream patches: don't duplicate environment variables (RHBZ#859596).
+
+* Mon Sep 24 2012 Daniel Veillard <veillard@redhat.com> - 0.10.2-1
+- Upstream release 0.10.2
+- network: define new API virNetworkUpdate
+- add support for QEmu sandbox support
+- blockjob: add virDomainBlockCommit
+- New APIs to get/set Node memory parameters
+- new API virConnectListAllSecrets
+- new API virConnectListAllNWFilters
+- new API virConnectListAllNodeDevices
+- parallels: add support of containers to the driver
+- new API virConnectListAllInterfaces
+- new API virConnectListAllNetworks
+- new API virStoragePoolListAllVolumes
+- Add PMSUSPENDED life cycle event
+- new API virStorageListAllStoragePools
+- Add per-guest S3/S4 state configuration
+- qemu: Support for Block Device IO Limits
+- a lot of bug fixes, improvements and portability work
+
+* Fri Sep 21 2012 Richard W.M. Jones <rjones@redhat.com> - 0.10.1-5
+- Add (upstream) patches to label sockets for SELinux (RHBZ#853393).
+
+* Thu Sep 13 2012 Richard W.M. Jones <rjones@redhat.com> - 0.10.1-4
+- Fix for 32 bit qemu renamed to qemu-system-i386 (RHBZ#857026).
+
+* Wed Sep 12 2012 Cole Robinson <crobinso@redhat.com> - 0.10.1-3
+- Fix libvirtd segfault with old netcf-libs (bz 853381)
+- Drop unneeded dnsmasq --filterwin2k
+- Fix unwanted connection closing, needed for boxes
+
+* Wed Sep 5 2012 Daniel P. Berrange <berrange@redhat.com> - 0.10.1-2
+- Remove dep on ceph RPM (rhbz #854360)
+
+* Fri Aug 31 2012 Daniel Veillard <veillard@redhat.com> - 0.10.1-1
+- upstream release of 0.10.1
+- many fixes from 0.10.0
+
+* Wed Aug 29 2012 Daniel Veillard <veillard@redhat.com> - 0.10.0-1
+- upstream release of 0.10.0
+- agent: add qemuAgentArbitraryCommand() for general qemu agent command
+- Introduce virDomainPinEmulator and virDomainGetEmulatorPinInfo functions
+- network: use firewalld instead of iptables, when available
+- network: make network driver vlan-aware
+- esx: Implement network driver
+- driver for parallels hypervisor
+- Various LXC improvements
+- Add virDomainGetHostname
+- a lot of bug fixes, improvements and portability work
+
+* Thu Aug 23 2012 Daniel Veillard <veillard@redhat.com> - 0.10.0-0rc1
+- release candidate 1 of 0.10.0
+
+* Tue Aug 14 2012 Daniel P. Berrange <berrange@redhat.com> - 0.10.0-0rc0.2
+- Enable autotools to make previous patch work
+
+* Tue Aug 14 2012 Daniel Veillard <veillard@redhat.com> - 0.10.0-0rc0.1
+- fix security driver missing from the daemon
+
+* Wed Aug 8 2012 Daniel Veillard <veillard@redhat.com> - 0.10.0-0rc0
+- snapshot before 0.10.0 in a few weeks
+- adds the parallel driver support
+
+* Mon Jul 23 2012 Richard W.M. Jones <rjones@redhat.com> - 0.9.13-3
+- Add upstream patch to fix RHBZ#842114.
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.13-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Mon Jul 2 2012 Daniel Veillard <veillard@redhat.com> - 0.9.13-1
+- S390: support for s390(x)
+- snapshot: implement new APIs for esx and vbox
+- snapshot: new query APIs and many improvements
+- virsh: Allow users to reedit rejected XML
+- nwfilter: add DHCP snooping
+- Enable driver modules in libvirt RPM
+- Default to enable driver modules for libvirtd
+- storage backend: Add RBD (RADOS Block Device) support
+- sVirt support for LXC domains inprovement
+- a lot of bug fixes, improvements and portability work
+
+* Mon May 14 2012 Daniel Veillard <veillard@redhat.com> - 0.9.12-1
+- qemu: allow snapshotting of sheepdog and rbd disks
+- blockjob: add new APIs
+- a lot of bug fixes, improvements and portability work
+
+* Thu Apr 26 2012 Cole Robinson <crobinso@redhat.com> - 0.9.11.3-1
+- Rebased to version 0.9.11.3
+- Abide URI username when connecting to hypervisor (bz 811397)
+- Fix managed USB mode (bz 814866)
+- Fix crash connecting to ESX host (bz 811891)
+
+* Wed Apr 4 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.11-1
+- Update to 0.9.11 release
+
+* Tue Apr 3 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.10-4
+- Revert previous change
+
+* Sat Mar 31 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.10-3
+- Refactor RPM spec to allow install without default configs
+
+* Thu Mar 15 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.10-2
+- Rebuild for libparted soname break
+
+* Mon Feb 13 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.10-1
+- Update to 0.9.10
+
+* Thu Jan 12 2012 Daniel P. Berrange <berrange@redhat.com> - 0.9.9-2
+- Fix LXC I/O handling
+
+* Sat Jan 7 2012 Daniel Veillard <veillard@redhat.com> - 0.9.9-1
+- Add API virDomain{S,G}etInterfaceParameters
+- Add API virDomain{G, S}etNumaParameters
+- Add support for ppc64 qemu
+- Support Xen domctl v8
+- many improvements and bug fixes
+
+* Thu Dec 8 2011 Daniel P. Berrange <berrange@redhat.com> - 0.9.8-2
+- Fix install of libvirt-guests.service & libvirtd.service
+
+* Thu Dec 8 2011 Daniel Veillard <veillard@redhat.com> - 0.9.8-1
+- Add support for QEMU 1.0
+- Add preliminary PPC cpu driver
+- Add new API virDomain{Set, Get}BlockIoTune
+- block_resize: Define the new API
+- Add a public API to invoke suspend/resume on the host
+- various improvements for LXC containers
+- Define keepalive protocol and add virConnectIsAlive API
+- Add support for STP and VLAN filtering
+- many improvements and bug fixes
+
+* Mon Nov 14 2011 Justin M. Forbes <jforbes@redhat.com> - 0.9.7-3
+- Remove versioned buildreq for yajl as 2.0.x features are not required.
+
+* Thu Nov 10 2011 Daniel P. Berrange <berrange@redhat.com> - 0.9.7-2
+- Rebuild for yajl 2.0.1
+
+* Tue Nov 8 2011 Daniel P. Berrange <berrange@redhat.com> - 0.9.7-1
+- Update to 0.9.7 release
+
+* Tue Oct 11 2011 Dan Horák <dan[at]danny.cz> - 0.9.6-3
+- xenlight available only on Xen arches (#745020)
+
+* Mon Oct 3 2011 Laine Stump <laine@redhat.com> - 0.9.6-2
+- Make PCI multifunction support more manual - Bug 742836
+- F15 build still uses cgconfig - Bug 738725
+
+* Thu Sep 22 2011 Daniel Veillard <veillard@redhat.com> - 0.9.6-1
+- Fix the qemu reboot bug and a few others bug fixes
+
+* Tue Sep 20 2011 Daniel Veillard <veillard@redhat.com> - 0.9.5-1
+- many snapshot improvements (Eric Blake)
+- latency: Define new public API and structure (Osier Yang)
+- USB2 and various USB improvements (Marc-André Lureau)
+- storage: Add fs pool formatting (Osier Yang)
+- Add public API for getting migration speed (Jim Fehlig)
+- Add basic driver for Microsoft Hyper-V (Matthias Bolte)
+- many improvements and bug fixes
+
+* Wed Aug 3 2011 Daniel Veillard <veillard@redhat.com> - 0.9.4-1
+- network bandwidth QoS control
+- Add new API virDomainBlockPull*
+- save: new API to manipulate save file images
+- CPU bandwidth limits support
+- allow to send NMI and key event to guests
+- new API virDomainUndefineFlags
+- Implement code to attach to external QEMU instances
+- bios: Add support for SGA
+- various missing python binding
+- many improvements and bug fixes
+
+* Sat Jul 30 2011 Dan Hor?k <dan[at]danny.cz> - 0.9.3-3
+- xenlight available only on Xen arches
+
+* Wed Jul 6 2011 Peter Robinson <pbrobinson@gmail.com> - 0.9.3-2
+- Add ARM to NUMA platform excludes
+
+* Mon Jul 4 2011 Daniel Veillard <veillard@redhat.com> - 0.9.3-1
+- new API virDomainGetVcpupinInfo
+- Add TXT record support for virtual DNS service
+- Support reboots with the QEMU driver
+- New API virDomainGetControlInfo API
+- New API virNodeGetMemoryStats
+- New API virNodeGetCPUTime
+- New API for send-key
+- New API virDomainPinVcpuFlags
+- support multifunction PCI device
+- lxc: various improvements
+- many improvements and bug fixes
+
+* Wed Jun 29 2011 Richard W.M. Jones <rjones@redhat.com> - 0.9.2-3
+- Rebuild because of libparted soname bump (libparted.so.0 -> libparted.so.1).
+
+* Tue Jun 21 2011 Laine Stump <laine@redhat.com> - 0.9.2-2
+- add rule to require netcf-0.1.8 during build so that new transactional
+ network change APIs are included.
+- document that CVE-2011-2178 has been fixed (by virtue of rebase
+ to 0.9.2 - see https://bugzilla.redhat.com/show_bug.cgi?id=709777)
+
+* Mon Jun 6 2011 Daniel Veillard <veillard@redhat.com> - 0.9.2-1
+- Framework for lock manager plugins
+- API for network config change transactions
+- flags for setting memory parameters
+- virDomainGetState public API
+- qemu: allow blkstat/blkinfo calls during migration
+- Introduce migration v3 API
+- Defining the Screenshot public API
+- public API for NMI injection
+- Various improvements and bug fixes
+
+* Wed May 25 2011 Richard W.M. Jones <rjones@redhat.com> - 0.9.1-3
+- Add upstream patches:
+ 0001-json-Avoid-passing-large-positive-64-bit-integers-to.patch
+ 0001-qemudDomainMemoryPeek-change-ownership-selinux-label.patch
+ 0002-remote-remove-bogus-virDomainFree.patch
+ so that users can try out virt-dmesg.
+- Change /var/cache mode to 0711.
+
+* Thu May 5 2011 Daniel Veillard <veillard@redhat.com> - 0.9.1-1
+- support various persistent domain updates
+- improvements on memory APIs
+- Add virDomainEventRebootNew
+- various improvements to libxl driver
+- Spice: support audio, images and stream compression
+- Various improvements and bug fixes
+
+* Thu Apr 7 2011 Daniel Veillard <veillard@redhat.com> - 0.9.0-1
+- Support cputune cpu usage tuning
+- Add public APIs for storage volume upload/download
+- Add public API for setting migration speed on the fly
+- Add libxenlight driver
+- qemu: support migration to fd
+- libvirt: add virDomain{Get,Set}BlkioParameters
+- setmem: introduce a new libvirt API (virDomainSetMemoryFlags)
+- Expose event loop implementation as a public API
+- Dump the debug buffer to libvirtd.log on fatal signal
+- Audit support
+- Various improvements and bug fixes
+
+* Mon Mar 14 2011 Daniel Veillard <veillard@redhat.com> - 0.8.8-3
+- fix a lack of API check on read-only connections
+- CVE-2011-1146
+
+* Mon Feb 21 2011 Daniel P. Berrange <berrange@redhat.com> - 0.8.8-2
+- Fix kernel boot with latest QEMU
+
+* Thu Feb 17 2011 Daniel Veillard <veillard@redhat.com> - 0.8.8-1
+- expose new API for sysinfo extraction
+- cgroup blkio weight support
+- smartcard device support
+- qemu: Support per-device boot ordering
+- Various improvements and bug fixes
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.8.7-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Thu Jan 6 2011 Daniel Veillard <veillard@redhat.com> - 0.8.7-1
+- Preliminary support for VirtualBox 4.0
+- IPv6 support
+- Add VMware Workstation and Player driver driver
+- Add network disk support
+- Various improvements and bug fixes
+- from 0.8.6:
+- Add support for iSCSI target auto-discovery
+- QED: Basic support for QED images
+- remote console support
+- support for SPICE graphics
+- sysinfo and VMBIOS support
+- virsh qemu-monitor-command
+- various improvements and bug fixes
+
+* Fri Oct 29 2010 Daniel Veillard <veillard@redhat.com> - 0.8.5-1
+- Enable JSON and netdev features in QEMU >= 0.13
+- framework for auditing integration
+- framework DTrace/SystemTap integration
+- Setting the number of vcpu at boot
+- Enable support for nested SVM
+- Virtio plan9fs filesystem QEMU
+- Memory parameter controls
+- various improvements and bug fixes
+
+* Wed Sep 29 2010 jkeating - 0.8.4-3
+- Rebuilt for gcc bug 634757
+
+* Thu Sep 16 2010 Dan Horák <dan[at]danny.cz> - 0.8.4-2
+- disable the nwfilterxml2xmltest also on s390(x)
+
+* Mon Sep 13 2010 Daniel Veillard <veillard@redhat.com> - 0.8.4-1
+- Upstream release 0.8.4
+
+* Mon Aug 23 2010 Daniel P. Berrange <berrange@redhat.com> - 0.8.3-2
+- Fix potential overflow in boot menu code
+
+* Mon Aug 23 2010 Daniel P. Berrange <berrange@redhat.com> - 0.8.3-1
+- Upstream release 0.8.3
+
+* Wed Jul 21 2010 David Malcolm <dmalcolm@redhat.com> - 0.8.2-3
+- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
+
+* Mon Jul 12 2010 Daniel P. Berrange <berrange@redhat.com> - 0.8.2-2
+- CVE-2010-2237 ignoring defined main disk format when looking up disk backing stores
+- CVE-2010-2238 ignoring defined disk backing store format when recursing into disk
+ image backing stores
+- CVE-2010-2239 not setting user defined backing store format when creating new image
+- CVE-2010-2242 libvirt: improperly mapped source privileged ports may allow for
+ obtaining privileged resources on the host
+
+* Mon Jul 5 2010 Daniel Veillard <veillard@redhat.com> - 0.8.2-1
+- Upstream release 0.8.2
+- phyp: adding support for IVM
+- libvirt: introduce domainCreateWithFlags API
+- add 802.1Qbh and 802.1Qbg switches handling
+- Support for VirtualBox version 3.2
+- Init script for handling guests on shutdown/boot
+- qemu: live migration with non-shared storage for kvm
+
+* Fri Apr 30 2010 Daniel Veillard <veillard@redhat.com> - 0.8.1-1
+- Upstream release 0.8.1
+- Starts dnsmasq from libvirtd with --dhcp-hostsfile
+- Add virDomainGetBlockInfo API to query disk sizing
+- a lot of bug fixes and cleanups
+
+* Mon Apr 12 2010 Daniel Veillard <veillard@redhat.com> - 0.8.0-1
+- Upstream release 0.8.0
+- Snapshotting support (QEmu/VBox/ESX)
+- Network filtering API
+- XenAPI driver
+- new APIs for domain events
+- Libvirt managed save API
+- timer subselection for domain clock
+- synchronous hooks
+- API to update guest CPU to host CPU
+- virDomainUpdateDeviceFlags new API
+- migrate max downtime API
+- volume wiping API
+- and many bug fixes
+
+* Tue Mar 30 2010 Richard W.M. Jones <rjones@redhat.com> - 0.7.7-3.fc14
+- No change, just rebuild against new libparted with bumped soname.
+
+* Mon Mar 22 2010 Cole Robinson <crobinso@redhat.com> - 0.7.7-2.fc14
+- Fix USB devices by product with security enabled (bz 574136)
+- Set kernel/initrd in security driver, fixes some URL installs (bz 566425)
+
+* Fri Mar 5 2010 Daniel Veillard <veillard@redhat.com> - 0.7.7-1
+- macvtap support
+- async job handling
+- virtio channel
+- computing baseline CPU
+- virDomain{Attach,Detach}DeviceFlags
+- assorted bug fixes and lots of cleanups
+
+* Tue Feb 16 2010 Adam Jackson <ajax@redhat.com> 0.7.6-2
+- libvirt-0.7.6-add-needed.patch: Fix FTBFS from --no-add-needed
+- Add BuildRequires: xmlrpc-c-client for libxmlrpc_client.so
+
+* Wed Feb 3 2010 Daniel Veillard <veillard@redhat.com> - 0.7.6-1
+- upstream release of 0.7.6
+- Use QEmu new device adressing when possible
+- Implement CPU topology support for QEMU driver
+- Implement SCSI controller hotplug/unplug for QEMU
+- Implement support for multi IQN
+- a lot of fixes and improvements
+
+* Thu Jan 14 2010 Chris Weyl <cweyl@alumni.drew.edu> 0.7.5-3
+- bump for libssh2 rebuild
+
+* Tue Jan 12 2010 Daniel P. Berrange <berrange@redhat.com> - 0.7.5-2
+- Rebuild for libparted soname change
+
+* Wed Dec 23 2009 Daniel Veillard <veillard@redhat.com> - 0.7.5-1
+- Add new API virDomainMemoryStats
+- Public API and domain extension for CPU flags
+- vbox: Add support for version 3.1
+- Support QEMU's virtual FAT block device driver
+- a lot of fixes
+
+* Fri Nov 20 2009 Daniel Veillard <veillard@redhat.com> - 0.7.4-1
+- upstream release of 0.7.4
+- udev node device backend
+- API to check object properties
+- better QEmu monitor processing
+- MAC address based port filtering for qemu
+- support IPv6 and multiple addresses per interfaces
+- a lot of fixes
+
+* Thu Nov 19 2009 Daniel P. Berrange <berrange@redhat.com> - 0.7.2-6
+- Really fix restore file labelling this time
+
+* Wed Nov 11 2009 Daniel P. Berrange <berrange@redhat.com> - 0.7.2-5
+- Disable numactl on s390[x]. Again.
+
+* Wed Nov 11 2009 Daniel P. Berrange <berrange@redhat.com> - 0.7.2-4
+- Fix QEMU save/restore permissions / labelling
+
+* Thu Oct 29 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.2-3
+- Avoid compressing small log files (#531030)
+
+* Thu Oct 29 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.2-2
+- Make libvirt-devel require libvirt-client, not libvirt
+- Fix qemu machine types handling
+
+* Wed Oct 14 2009 Daniel Veillard <veillard@redhat.com> - 0.7.2-1
+- Upstream release of 0.7.2
+- Allow to define ESX domains
+- Allows suspend and resulme of LXC domains
+- API for data streams
+- many bug fixes
+
+* Tue Oct 13 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-12
+- Fix restore of qemu guest using raw save format (#523158)
+
+* Fri Oct 9 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-11
+- Fix libvirtd memory leak during error reply sending (#528162)
+- Add several PCI hot-unplug typo fixes from upstream
+
+* Tue Oct 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-10
+- Create /var/log/libvirt/{lxc,uml} dirs for logrotate
+- Make libvirt-python dependon on libvirt-client
+- Sync misc minor changes from upstream spec
+
+* Tue Oct 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-9
+- Change logrotate config to weekly (#526769)
+
+* Thu Oct 1 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-8
+- Disable sound backend, even when selinux is disabled (#524499)
+- Re-label qcow2 backing files (#497131)
+
+* Wed Sep 30 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-7
+- Fix USB device passthrough (#522683)
+
+* Mon Sep 21 2009 Chris Weyl <cweyl@alumni.drew.edu> - 0.7.1-6
+- rebuild for libssh2 1.2
+
+* Mon Sep 21 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-5
+- Don't set a bogus error in virDrvSupportsFeature()
+- Fix raw save format
+
+* Thu Sep 17 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-4
+- A couple of hot-unplug memory handling fixes (#523953)
+
+* Thu Sep 17 2009 Daniel Veillard <veillard@redhat.com> - 0.7.1-3
+- disable numactl on s390[x]
+
+* Thu Sep 17 2009 Daniel Veillard <veillard@redhat.com> - 0.7.1-2
+- revamp of spec file for modularity and RHELs
+
+* Tue Sep 15 2009 Daniel Veillard <veillard@redhat.com> - 0.7.1-1
+- Upstream release of 0.7.1
+- ESX, VBox driver updates
+- mutipath support
+- support for encrypted (qcow) volume
+- compressed save image format for Qemu/KVM
+- QEmu host PCI device hotplug support
+- configuration of huge pages in guests
+- a lot of fixes
+
+* Mon Sep 14 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-0.2.gitfac3f4c
+- Update to newer snapshot of 0.7.1
+- Stop libvirt using untrusted 'info vcpus' PID data (#520864)
+- Support relabelling of USB and PCI devices
+- Enable multipath storage support
+- Restart libvirtd upon RPM upgrade
+
+* Sun Sep 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-0.1.gitg3ef2e05
+- Update to pre-release git snapshot of 0.7.1
+- Drop upstreamed patches
+
+* Wed Aug 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.0-6
+- Fix migration completion with newer versions of qemu (#516187)
+
+* Wed Aug 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.0-5
+- Add PCI host device hotplug support
+- Allow PCI bus reset to reset other devices (#499678)
+- Fix stupid PCI reset error message (bug #499678)
+- Allow PM reset on multi-function PCI devices (bug #515689)
+- Re-attach PCI host devices after guest shuts down (bug #499561)
+- Fix list corruption after disk hot-unplug
+- Fix minor 'virsh nodedev-list --tree' annoyance
+
+* Thu Aug 13 2009 Daniel P. Berrange <berrange@redhat.com> - 0.7.0-4
+- Rewrite policykit support (rhbz #499970)
+- Log and ignore NUMA topology problems (rhbz #506590)
+
+* Mon Aug 10 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.0-3
+- Don't fail to start network if ipv6 modules is not loaded (#516497)
+
+* Thu Aug 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.0-2
+- Make sure qemu can access kernel/initrd (bug #516034)
+- Set perms on /var/lib/libvirt/boot to 0711 (bug #516034)
+
+* Wed Aug 5 2009 Daniel Veillard <veillard@redhat.com> - 0.7.0-1
+- ESX, VBox3, Power Hypervisor drivers
+- new net filesystem glusterfs
+- Storage cloning for LVM and Disk backends
+- interface implementation based on netcf
+- Support cgroups in QEMU driver
+- QEmu hotplug NIC support
+- a lot of fixes
+
+* Fri Jul 3 2009 Daniel Veillard <veillard@redhat.com> - 0.6.5-1
+- release of 0.6.5
+
+* Fri May 29 2009 Daniel Veillard <veillard@redhat.com> - 0.6.4-1
+- release of 0.6.4
+- various new APIs
+
+* Fri Apr 24 2009 Daniel Veillard <veillard@redhat.com> - 0.6.3-1
+- release of 0.6.3
+- VirtualBox driver
+
+* Fri Apr 3 2009 Daniel Veillard <veillard@redhat.com> - 0.6.2-1
+- release of 0.6.2
+
+* Wed Mar 4 2009 Daniel Veillard <veillard@redhat.com> - 0.6.1-1
+- release of 0.6.1
+
+* Sat Jan 31 2009 Daniel Veillard <veillard@redhat.com> - 0.6.0-1
+- release of 0.6.0
+
+* Tue Nov 25 2008 Daniel Veillard <veillard@redhat.com> - 0.5.0-1
+- release of 0.5.0
+
+* Tue Sep 23 2008 Daniel Veillard <veillard@redhat.com> - 0.4.6-1
+- release of 0.4.6
+
+* Mon Sep 8 2008 Daniel Veillard <veillard@redhat.com> - 0.4.5-1
+- release of 0.4.5
+
+* Wed Jun 25 2008 Daniel Veillard <veillard@redhat.com> - 0.4.4-1
+- release of 0.4.4
+- mostly a few bug fixes from 0.4.3
+
+* Thu Jun 12 2008 Daniel Veillard <veillard@redhat.com> - 0.4.3-1
+- release of 0.4.3
+- lots of bug fixes and small improvements
+
+* Tue Apr 8 2008 Daniel Veillard <veillard@redhat.com> - 0.4.2-1
+- release of 0.4.2
+- lots of bug fixes and small improvements
+
+* Mon Mar 3 2008 Daniel Veillard <veillard@redhat.com> - 0.4.1-1
+- Release of 0.4.1
+- Storage APIs
+- xenner support
+- lots of assorted improvements, bugfixes and cleanups
+- documentation and localization improvements
+
+* Tue Dec 18 2007 Daniel Veillard <veillard@redhat.com> - 0.4.0-1
+- Release of 0.4.0
+- SASL based authentication
+- PolicyKit authentication
+- improved NUMA and statistics support
+- lots of assorted improvements, bugfixes and cleanups
+- documentation and localization improvements
+
+* Sun Sep 30 2007 Daniel Veillard <veillard@redhat.com> - 0.3.3-1
+- Release of 0.3.3
+- Avahi support
+- NUMA support
+- lots of assorted improvements, bugfixes and cleanups
+- documentation and localization improvements
+
+* Tue Aug 21 2007 Daniel Veillard <veillard@redhat.com> - 0.3.2-1
+- Release of 0.3.2
+- API for domains migration
+- APIs for collecting statistics on disks and interfaces
+- lots of assorted bugfixes and cleanups
+- documentation and localization improvements
+
+* Tue Jul 24 2007 Daniel Veillard <veillard@redhat.com> - 0.3.1-1
+- Release of 0.3.1
+- localtime clock support
+- PS/2 and USB input devices
+- lots of assorted bugfixes and cleanups
+- documentation and localization improvements
+
+* Mon Jul 9 2007 Daniel Veillard <veillard@redhat.com> - 0.3.0-1
+- Release of 0.3.0
+- Secure remote access support
+- unification of daemons
+- lots of assorted bugfixes and cleanups
+- documentation and localization improvements
+
+* Fri Jun 8 2007 Daniel Veillard <veillard@redhat.com> - 0.2.3-1
+- Release of 0.2.3
+- lot of assorted bugfixes and cleanups
+- support for Xen-3.1
+- new scheduler API
+
+* Tue Apr 17 2007 Daniel Veillard <veillard@redhat.com> - 0.2.2-1
+- Release of 0.2.2
+- lot of assorted bugfixes and cleanups
+- preparing for Xen-3.0.5
+
+* Thu Mar 22 2007 Jeremy Katz <katzj@redhat.com> - 0.2.1-2.fc7
+- don't require xen; we don't need the daemon and can control non-xen now
+- fix scriptlet error (need to own more directories)
+- update description text
+
+* Fri Mar 16 2007 Daniel Veillard <veillard@redhat.com> - 0.2.1-1
+- Release of 0.2.1
+- lot of bug and portability fixes
+- Add support for network autostart and init scripts
+- New API to detect the virtualization capabilities of a host
+- Documentation updates
+
+* Fri Feb 23 2007 Daniel P. Berrange <berrange@redhat.com> - 0.2.0-4.fc7
+- Fix loading of guest & network configs
+
+* Fri Feb 16 2007 Daniel P. Berrange <berrange@redhat.com> - 0.2.0-3.fc7
+- Disable kqemu support since its not in Fedora qemu binary
+- Fix for -vnc arg syntax change in 0.9.0 QEMU
+
+* Thu Feb 15 2007 Daniel P. Berrange <berrange@redhat.com> - 0.2.0-2.fc7
+- Fixed path to qemu daemon for autostart
+- Fixed generation of <features> block in XML
+- Pre-create config directory at startup
+
+* Wed Feb 14 2007 Daniel Veillard <veillard@redhat.com> 0.2.0-1.fc7
+- support for KVM and QEmu
+- support for network configuration
+- assorted fixes
+
+* Mon Jan 22 2007 Daniel Veillard <veillard@redhat.com> 0.1.11-1.fc7
+- finish inactive Xen domains support
+- memory leak fix
+- RelaxNG schemas for XML configs
+
+* Wed Dec 20 2006 Daniel Veillard <veillard@redhat.com> 0.1.10-1.fc7
+- support for inactive Xen domains
+- improved support for Xen display and vnc
+- a few bug fixes
+- localization updates
+
+* Thu Dec 7 2006 Jeremy Katz <katzj@redhat.com> - 0.1.9-2
+- rebuild against python 2.5
+
+* Wed Nov 29 2006 Daniel Veillard <veillard@redhat.com> 0.1.9-1
+- better error reporting
+- python bindings fixes and extensions
+- add support for shareable drives
+- add support for non-bridge style networking
+- hot plug device support
+- added support for inactive domains
+- API to dump core of domains
+- various bug fixes, cleanups and improvements
+- updated the localization
+
+* Tue Nov 7 2006 Daniel Veillard <veillard@redhat.com> 0.1.8-3
+- it's pkgconfig not pgkconfig !
+
+* Mon Nov 6 2006 Daniel Veillard <veillard@redhat.com> 0.1.8-2
+- fixing spec file, added %%dist, -devel requires pkgconfig and xen-devel
+- Resolves: rhbz#202320
+
+* Mon Oct 16 2006 Daniel Veillard <veillard@redhat.com> 0.1.8-1
+- fix missing page size detection code for ia64
+- fix mlock size when getting domain info list from hypervisor
+- vcpu number initialization
+- don't label crashed domains as shut off
+- fix virsh man page
+- blktapdd support for alternate drivers like blktap
+- memory leak fixes (xend interface and XML parsing)
+- compile fix
+- mlock/munlock size fixes
+
+* Fri Sep 22 2006 Daniel Veillard <veillard@redhat.com> 0.1.7-1
+- Fix bug when running against xen-3.0.3 hypercalls
+- Fix memory bug when getting vcpus info from xend
+
+* Fri Sep 22 2006 Daniel Veillard <veillard@redhat.com> 0.1.6-1
+- Support for localization
+- Support for new Xen-3.0.3 cdrom and disk configuration
+- Support for setting VNC port
+- Fix bug when running against xen-3.0.2 hypercalls
+- Fix reconnection problem when talking directly to http xend
+
+* Tue Sep 5 2006 Jeremy Katz <katzj@redhat.com> - 0.1.5-3
+- patch from danpb to support new-format cd devices for HVM guests
+
+* Tue Sep 5 2006 Daniel Veillard <veillard@redhat.com> 0.1.5-2
+- reactivating ia64 support
+
+* Tue Sep 5 2006 Daniel Veillard <veillard@redhat.com> 0.1.5-1
+- new release
+- bug fixes
+- support for new hypervisor calls
+- early code for config files and defined domains
+
+* Mon Sep 4 2006 Daniel Berrange <berrange@redhat.com> - 0.1.4-5
+- add patch to address dom0_ops API breakage in Xen 3.0.3 tree
+
+* Mon Aug 28 2006 Jeremy Katz <katzj@redhat.com> - 0.1.4-4
+- add patch to support paravirt framebuffer in Xen
+
+* Mon Aug 21 2006 Daniel Veillard <veillard@redhat.com> 0.1.4-3
+- another patch to fix network handling in non-HVM guests
+
+* Thu Aug 17 2006 Daniel Veillard <veillard@redhat.com> 0.1.4-2
+- patch to fix virParseUUID()
+
+* Wed Aug 16 2006 Daniel Veillard <veillard@redhat.com> 0.1.4-1
+- vCPUs and affinity support
+- more complete XML, console and boot options
+- specific features support
+- enforced read-only connections
+- various improvements, bug fixes
+
+* Wed Aug 2 2006 Jeremy Katz <katzj@redhat.com> - 0.1.3-6
+- add patch from pvetere to allow getting uuid from libvirt
+
+* Wed Aug 2 2006 Jeremy Katz <katzj@redhat.com> - 0.1.3-5
+- build on ia64 now
+
+* Thu Jul 27 2006 Jeremy Katz <katzj@redhat.com> - 0.1.3-4
+- don't BR xen, we just need xen-devel
+
+* Thu Jul 27 2006 Daniel Veillard <veillard@redhat.com> 0.1.3-3
+- need rebuild since libxenstore is now versionned
+
+* Mon Jul 24 2006 Mark McLoughlin <markmc@redhat.com> - 0.1.3-2
+- Add BuildRequires: xen-devel
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 0.1.3-1.1
+- rebuild
+
+* Tue Jul 11 2006 Daniel Veillard <veillard@redhat.com> 0.1.3-1
+- support for HVM Xen guests
+- various bugfixes
+
+* Mon Jul 3 2006 Daniel Veillard <veillard@redhat.com> 0.1.2-1
+- added a proxy mechanism for read only access using httpu
+- fixed header includes paths
+
+* Wed Jun 21 2006 Daniel Veillard <veillard@redhat.com> 0.1.1-1
+- extend and cleanup the driver infrastructure and code
+- python examples
+- extend uuid support
+- bug fixes, buffer handling cleanups
+- support for new Xen hypervisor API
+- test driver for unit testing
+- virsh --conect argument
+
+* Mon Apr 10 2006 Daniel Veillard <veillard@redhat.com> 0.1.0-1
+- various fixes
+- new APIs: for Node information and Reboot
+- virsh improvements and extensions
+- documentation updates and man page
+- enhancement and fixes of the XML description format
+
+* Tue Feb 28 2006 Daniel Veillard <veillard@redhat.com> 0.0.6-1
+- added error handling APIs
+- small bug fixes
+- improve python bindings
+- augment documentation and regression tests
+
+* Thu Feb 23 2006 Daniel Veillard <veillard@redhat.com> 0.0.5-1
+- new domain creation API
+- new UUID based APIs
+- more tests, documentation, devhelp
+- bug fixes
+
+* Fri Feb 10 2006 Daniel Veillard <veillard@redhat.com> 0.0.4-1
+- fixes some problems in 0.0.3 due to the change of names
+
+* Wed Feb 8 2006 Daniel Veillard <veillard@redhat.com> 0.0.3-1
+- changed library name to libvirt from libvir, complete and test the python
+ bindings
+
+* Sun Jan 29 2006 Daniel Veillard <veillard@redhat.com> 0.0.2-1
+- upstream release of 0.0.2, use xend, save and restore added, python bindings
+ fixed
+
+* Wed Nov 2 2005 Daniel Veillard <veillard@redhat.com> 0.0.1-1
+- created