[libvirt] [PATCH 1/2] Only keep one polkit rules file
by Cole Robinson
Just tweak it at build time depending on what polkit version we are
building for.
---
.gitignore | 1 +
daemon/Makefile.am | 16 +++++++++++-----
daemon/libvirtd.policy-0 | 42 ------------------------------------------
daemon/libvirtd.policy-1 | 42 ------------------------------------------
daemon/libvirtd.policy.in | 42 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 54 insertions(+), 89 deletions(-)
delete mode 100644 daemon/libvirtd.policy-0
delete mode 100644 daemon/libvirtd.policy-1
create mode 100644 daemon/libvirtd.policy.in
diff --git a/.gitignore b/.gitignore
index 1cd2d45..1b22b92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@
/daemon/libvirtd.init
/daemon/libvirtd.pod
/daemon/libvirtd.service
+/daemon/libvirtd.policy
/daemon/test_libvirtd.aug
/docs/apibuild.py.stamp
/docs/devhelp/libvirt.devhelp
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3405c67..f747c48 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -35,8 +35,7 @@ EXTRA_DIST = \
libvirtd.conf \
libvirtd.init.in \
libvirtd.upstart \
- libvirtd.policy-0 \
- libvirtd.policy-1 \
+ libvirtd.policy.in \
libvirtd.sasl \
libvirtd.sysconf \
libvirtd.sysctl \
@@ -173,13 +172,20 @@ libvirtd_LDADD += ../src/libvirt.la
if HAVE_POLKIT
if HAVE_POLKIT0
policydir = $(datadir)/PolicyKit/policy
-policyfile = libvirtd.policy-0
+policyauth = auth_admin_keep_session
else
policydir = $(datadir)/polkit-1/actions
-policyfile = libvirtd.policy-1
+policyauth = auth_admin_keep
endif
endif
+libvirtd.policy: libvirtd.policy.in $(top_builddir)/config.status
+ $(AM_V_GEN) sed \
+ -e 's![@]authaction[@]!$(policyauth)!g' \
+ < $< > $@-t && \
+ mv $@-t $@
+BUILT_SOURCES += libvirtd.policy
+
install-data-local: install-init-redhat install-init-systemd install-init-upstart \
install-data-sasl install-data-polkit \
install-logrotate install-sysctl
@@ -197,7 +203,7 @@ uninstall-local:: uninstall-init-redhat uninstall-init-systemd uninstall-init-up
if HAVE_POLKIT
install-data-polkit::
$(MKDIR_P) $(DESTDIR)$(policydir)
- $(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy
+ $(INSTALL_DATA) $(srcdir)/libvirtd.policy $(DESTDIR)$(policydir)/org.libvirt.unix.policy
uninstall-data-polkit::
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
rmdir $(DESTDIR)$(policydir) || :
diff --git a/daemon/libvirtd.policy-0 b/daemon/libvirtd.policy-0
deleted file mode 100644
index 5d6845c..0000000
--- a/daemon/libvirtd.policy-0
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!--
-Policy definitions for libvirt daemon
-
-Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
-
-libvirt is licensed to you under the GNU Lesser General Public License
-version 2. See COPYING for details.
-
-NOTE: If you make changes to this file, make sure to validate the file
-using the polkit-policy-file-validate(1) tool. Changes made to this
-file are instantly applied.
--->
-
-<policyconfig>
- <action id="org.libvirt.unix.monitor">
- <description>Monitor local virtualized systems</description>
- <message>System policy prevents monitoring of local virtualized systems</message>
- <defaults>
- <!-- Any program can use libvirt in read-only mode for monitoring,
- even if not part of a session -->
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.libvirt.unix.manage">
- <description>Manage local virtualized systems</description>
- <message>System policy prevents management of local virtualized systems</message>
- <defaults>
- <!-- Only a program in the active host session can use libvirt in
- read-write mode for management, and we require user password -->
- <allow_any>auth_admin</allow_any>
- <allow_inactive>auth_admin</allow_inactive>
- <allow_active>auth_admin_keep_session</allow_active>
- </defaults>
- </action>
-</policyconfig>
diff --git a/daemon/libvirtd.policy-1 b/daemon/libvirtd.policy-1
deleted file mode 100644
index c2bec1f..0000000
--- a/daemon/libvirtd.policy-1
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!--
-Policy definitions for libvirt daemon
-
-Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
-
-libvirt is licensed to you under the GNU Lesser General Public License
-version 2. See COPYING for details.
-
-NOTE: If you make changes to this file, make sure to validate the file
-using the polkit-policy-file-validate(1) tool. Changes made to this
-file are instantly applied.
--->
-
-<policyconfig>
- <action id="org.libvirt.unix.monitor">
- <description>Monitor local virtualized systems</description>
- <message>System policy prevents monitoring of local virtualized systems</message>
- <defaults>
- <!-- Any program can use libvirt in read-only mode for monitoring,
- even if not part of a session -->
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.libvirt.unix.manage">
- <description>Manage local virtualized systems</description>
- <message>System policy prevents management of local virtualized systems</message>
- <defaults>
- <!-- Only a program in the active host session can use libvirt in
- read-write mode for management, and we require user password -->
- <allow_any>auth_admin</allow_any>
- <allow_inactive>auth_admin</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-</policyconfig>
diff --git a/daemon/libvirtd.policy.in b/daemon/libvirtd.policy.in
new file mode 100644
index 0000000..45b0d79
--- /dev/null
+++ b/daemon/libvirtd.policy.in
@@ -0,0 +1,42 @@
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!--
+Policy definitions for libvirt daemon
+
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
+
+libvirt is licensed to you under the GNU Lesser General Public License
+version 2. See COPYING for details.
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+ <action id="org.libvirt.unix.monitor">
+ <description>Monitor local virtualized systems</description>
+ <message>System policy prevents monitoring of local virtualized systems</message>
+ <defaults>
+ <!-- Any program can use libvirt in read-only mode for monitoring,
+ even if not part of a session -->
+ <allow_any>yes</allow_any>
+ <allow_inactive>yes</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.libvirt.unix.manage">
+ <description>Manage local virtualized systems</description>
+ <message>System policy prevents management of local virtualized systems</message>
+ <defaults>
+ <!-- Only a program in the active host session can use libvirt in
+ read-write mode for management, and we require user password -->
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>@authaction@</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
--
1.7.11.4
12 years, 1 month
[libvirt] [PATCH] util: switch virLogEatParams to virLogSource
by Ján Tomko
Commit e8fd8757c89abbd38571092bbb987650b7658aec changed 'const char *'
category to virLogSource enum. This changes it in virLogEatParams as
well, thus fixing the build with --disable-debug.
--
Hopefully moving the enum declarations is less ugly than using int.
---
src/util/logging.h | 60 ++++++++++++++++++++++++++--------------------------
1 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/src/util/logging.h b/src/util/logging.h
index 4fe0c8e..c67377f 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -26,6 +26,35 @@
# include "buf.h"
/*
+ * To be made public
+ */
+typedef enum {
+ VIR_LOG_DEBUG = 1,
+ VIR_LOG_INFO,
+ VIR_LOG_WARN,
+ VIR_LOG_ERROR,
+} virLogPriority;
+
+# define VIR_LOG_DEFAULT VIR_LOG_WARN
+
+typedef enum {
+ VIR_LOG_TO_STDERR = 1,
+ VIR_LOG_TO_SYSLOG,
+ VIR_LOG_TO_FILE,
+ VIR_LOG_TO_JOURNALD,
+} virLogDestination;
+
+typedef enum {
+ VIR_LOG_FROM_FILE,
+ VIR_LOG_FROM_ERROR,
+ VIR_LOG_FROM_AUDIT,
+ VIR_LOG_FROM_TRACE,
+ VIR_LOG_FROM_LIBRARY,
+
+ VIR_LOG_FROM_LAST,
+} virLogSource;
+
+/*
* If configured with --enable-debug=yes then library calls
* are printed to stderr for debugging or to an appropriate channel
* defined at runtime from the libvirt daemon configuration file
@@ -39,7 +68,7 @@
*
* Do nothing but eat parameters.
*/
-static inline void virLogEatParams(const char *unused, ...)
+static inline void virLogEatParams(virLogSource unused, ...)
{
/* Silence gcc */
unused = unused;
@@ -64,35 +93,6 @@ static inline void virLogEatParams(const char *unused, ...)
# define VIR_ERROR(...) \
VIR_ERROR_INT(VIR_LOG_FROM_FILE, __FILE__, __LINE__, __func__, __VA_ARGS__)
-/*
- * To be made public
- */
-typedef enum {
- VIR_LOG_DEBUG = 1,
- VIR_LOG_INFO,
- VIR_LOG_WARN,
- VIR_LOG_ERROR,
-} virLogPriority;
-
-# define VIR_LOG_DEFAULT VIR_LOG_WARN
-
-typedef enum {
- VIR_LOG_TO_STDERR = 1,
- VIR_LOG_TO_SYSLOG,
- VIR_LOG_TO_FILE,
- VIR_LOG_TO_JOURNALD,
-} virLogDestination;
-
-typedef enum {
- VIR_LOG_FROM_FILE,
- VIR_LOG_FROM_ERROR,
- VIR_LOG_FROM_AUDIT,
- VIR_LOG_FROM_TRACE,
- VIR_LOG_FROM_LIBRARY,
-
- VIR_LOG_FROM_LAST,
-} virLogSource;
-
/**
* virLogOutputFunc:
* @src: the src for the message
--
1.7.8.6
12 years, 1 month
[libvirt] [PATCH] node_memory: Add new parameter field to tune the new sysfs knob
by Osier Yang
Upstream kernel introduced new sysfs knob "merge_across_nodes" to
specify if pages from different numa nodes can be merged. When set
to 0, only pages which physically reside in the memory area of
same NUMA node can be merged. When set to 1, pages from all nodes
can be merged.
This patch supports the tuning by adding new param field
"shm-merge-across-nodes".
---
Perhaps two bool options like "--disable-shm-merge-across-nodes",
and "--enable-shm-merge-across-nodes" are good, but could the
kernel sysfs knob have other values beyond 0 and 1 in future?
---
include/libvirt/libvirt.h.in | 10 ++++++++++
src/nodeinfo.c | 26 +++++++++++++++++++++++---
tools/virsh-host.c | 20 ++++++++++++++++++++
tools/virsh.pod | 5 ++++-
4 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 81f12a4..56ee2f5 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4489,6 +4489,16 @@ typedef virMemoryParameter *virMemoryParameterPtr;
*/
# define VIR_NODE_MEMORY_SHARED_FULL_SCANS "shm_full_scans"
+/* VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES:
+ *
+ * Macro for typed parameter that represents whether pages from
+ * different NUMA nodes can be merged, when its value is 0, only
+ * pages which physically reside in the memory area of same NUMA
+ * node are merged, otherwise pages from all nodes can be merged.
+ */
+# define VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES "shm_merge_across_nodes"
+
+
int virNodeGetMemoryParameters(virConnectPtr conn,
virTypedParameterPtr params,
int *nparams,
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 021eb05..6002789 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1004,6 +1004,13 @@ nodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
/* Out of memory */
if (ret == -2)
return -1;
+ } else if (STREQ(param->field,
+ VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES)) {
+ ret = nodeSetMemoryParameterValue("merge_across_nodes", param);
+
+ /* Out of memory */
+ if (ret == -2)
+ return -1;
}
}
@@ -1039,8 +1046,9 @@ nodeGetMemoryParameterValue(const char *field,
if ((tmp = strchr(buf, '\n')))
*tmp = '\0';
- if (STREQ(field, "pages_to_scan") ||
- STREQ(field, "sleep_millisecs"))
+ if (STREQ(field, "pages_to_scan") ||
+ STREQ(field, "sleep_millisecs") ||
+ STREQ(field, "merge_across_nodes"))
rc = virStrToLong_ui(buf, NULL, 10, (unsigned int *)value);
else if (STREQ(field, "pages_shared") ||
STREQ(field, "pages_sharing") ||
@@ -1063,7 +1071,7 @@ cleanup:
}
#endif
-#define NODE_MEMORY_PARAMETERS_NUM 7
+#define NODE_MEMORY_PARAMETERS_NUM 8
int
nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
virTypedParameterPtr params ATTRIBUTE_UNUSED,
@@ -1075,6 +1083,7 @@ nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
#ifdef __linux__
unsigned int pages_to_scan;
unsigned int sleep_millisecs;
+ unsigned int merge_across_nodes;
unsigned long long pages_shared;
unsigned long long pages_sharing;
unsigned long long pages_unshared;
@@ -1168,6 +1177,17 @@ nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
break;
+ case 7:
+ if (nodeGetMemoryParameterValue("merge_across_nodes",
+ &merge_across_nodes) < 0)
+ return -1;
+
+ if (virTypedParameterAssign(param, VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
+ VIR_TYPED_PARAM_UINT, merge_across_nodes) < 0)
+ return -1;
+
+ break;
+
default:
break;
}
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 2c46336..62ecafc 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -900,6 +900,8 @@ static const vshCmdOptDef opts_node_memory_tune[] = {
{"shm-sleep-millisecs", VSH_OT_INT, VSH_OFLAG_NONE,
N_("number of millisecs the shared memory service should "
"sleep before next scan")},
+ {"shm-merge-across-nodes", VSH_OT_INT, VSH_OFLAG_NONE,
+ N_("Specifies if pages from different numa nodes can be merged")},
{NULL, 0, 0, NULL}
};
@@ -911,6 +913,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
unsigned int flags = 0;
unsigned int shm_pages_to_scan = 0;
unsigned int shm_sleep_millisecs = 0;
+ unsigned int shm_merge_across_nodes = 0;
bool ret = false;
int i = 0;
@@ -926,12 +929,21 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
return false;
}
+ if (vshCommandOptUInt(cmd, "shm-merge-across-nodes",
+ &shm_merge_across_nodes) < 0) {
+ vshError(ctl, "%s", _("invalid shm-merge-across-nodes number"));
+ return false;
+ }
+
if (shm_pages_to_scan)
nparams++;
if (shm_sleep_millisecs)
nparams++;
+ if (shm_merge_across_nodes)
+ nparams++;
+
if (nparams == 0) {
/* Get the number of memory parameters */
if (virNodeGetMemoryParameters(ctl->conn, NULL, &nparams, flags) != 0) {
@@ -983,6 +995,14 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
goto error;
}
+ if (i < nparams && shm_merge_across_nodes) {
+ if (virTypedParameterAssign(¶ms[i++],
+ VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
+ VIR_TYPED_PARAM_UINT,
+ shm_merge_across_nodes) < 0)
+ goto error;
+ }
+
if (virNodeSetMemoryParameters(ctl->conn, params, nparams, flags) != 0)
goto error;
else
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 2120429..d975f06 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -299,7 +299,10 @@ Allows you to display or set the node memory parameters.
I<shm-pages-to-scan> can be used to set the number of pages to scan
before the shared memory service goes to sleep; I<shm-sleep-millisecs>
can be used to set the number of millisecs the shared memory service should
-sleep before next scan.
+sleep before next scan; I<shm-merge-across-nodes> specifies if pages from
+different numa nodes can be merged. When set to 0, only pages which physically
+reside in the memory area of same NUMA node can be merged. When set to 1,
+pages from all nodes can be merged. Default to 1.
=item B<capabilities>
--
1.7.7.3
12 years, 1 month
[libvirt] [PATCH] Fix tab vs space
by Guido Günther
I've pushed that one already under the build breaker rule:
that broke "make syntax-check"
found by http://honk.sigxcpu.org:8001/job/libvirt-syntax-check/157/
Pushed under the build breaker rule.
---
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 b3e8424..b380d2d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3731,7 +3731,7 @@ static int qemudDomainHotplugVcpus(struct qemud_driver *driver,
}
virCgroupFree(&cgroup_vcpu);
- }
+ }
} else {
for (i = oldvcpus - 1; i >= nvcpus; i--) {
virDomainVcpuPinDefPtr vcpupin = NULL;
--
1.7.10.4
12 years, 1 month
[libvirt] [PATCH] Avoid straying </cpuset>
by Guido Günther
by using the same condition as for the <cpuset>.
Fixes "make check" found by
http://honk.sigxcpu.org:8001/job/libvirt-check/160/
---
src/conf/domain_conf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index cb80f09..83d7742 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13663,8 +13663,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virBufferAsprintf(buf, "cpuset='%s'/>\n", cpumask);
VIR_FREE(cpumask);
}
-
- if (def->cputune.shares || def->cputune.vcpupin ||
+ if (def->cputune.shares ||
+ (def->cputune.vcpupin && !virDomainIsAllVcpupinInherited(def)) ||
def->cputune.period || def->cputune.quota ||
def->cputune.emulatorpin ||
def->cputune.emulator_period || def->cputune.emulator_quota)
--
1.7.10.4
12 years, 1 month
[libvirt] [PATCHv2 3/4] qemu: reorganize qemuDomainChangeNet
by Laine Stump
(V1 of this patch is in the following thread:
https://www.redhat.com/archives/libvir-list/2012-October/msg00542.html
I'm posting it because PATCH 4/4 of that series attempts to use
apparently non-existent/non-working functionality in qemu; modifying
PATCH 3/4 slightly gives back some of the functionality lost by not
having 4/4. Once this is ACKed, I will push 1-3 only, and leave 4/4
untilits problem is discovered/resolved)
****
This patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=805071
to the extent that it can be resolved with current qemu functionality.
It attempts to detect as many situations as possible when the simple
operation of disconnecting an existing tap device from one bridge and
attaching it to another will satisfy the change requested in
virDomainUpdateDeviceFlags() for a network device. Before this patch,
that situation could only be detected if the pre-change interface
*and* the post-change interface definition were both "type='bridge'".
After this patch, it can also be detected if the before or after
interfaces are any combination of type='bridge' and type='network'
(the networks can be <forward mode='nat|route|bridge'>, as long as
they use a Linux host bridge and not macvtap connections).
This extra effort is especially useful since the recent discovery that
a netdev_del+netdev_add combo (to reconnect the network device with
completely different hostside configuration) doesn't work properly
with current qemu (1.2) unless it is accompanied by the matching
device_del+device_add - see this mailing list message for details:
http://lists.nongnu.org/archive/html/qemu-devel/2012-10/msg02355.html
(A slight modification of the patch referenced there has been prepared
to apply on top of this patch, but won't be pushed until qemu can be
made to work with it.)
* qemuDomainChangeNet needs access to the virDomainDeviceDef that
holds the new netdef (so that it can clear out the virDomainDeviceDef
if it ends up using the NetDef to replace the original), so the
virDomainNetDefPtr arg is replaced with a virDomainDeviceDefPtr.
* qemuDomainChangeNet previously checked for *some* changes to the
interface config, but this check was by no means complete. It was also
a bit disorganized.
This refactoring of the code is (I believe) complete in its check of
all NetDef attributes that might be changed, and either returns a
failure (for changes that are simply impossible), or sets one of three
flags:
needLinkStateChange - if the device link state needs to go up/down
needBridgeChange - if everything else is the same, but it needs
to be connected to a difference linux host
bridge
needReconnect - if the entire host side of the device needs
to be torn down and reconstructed (currently
non-working, as mentioned above)
Note that this function will refuse to make any change that requires
the *guest* side of the device to be detached (e.g. changing the PCI
address or mac address). Those would be disruptive enough to the guest
that it's reasonable to require an explicit detach/attach sequence
from the management application.
* As mentioned above, qemuDomainChangeNet also does its best to
understand when a simple change in attached bridge for the existing
tap device will work vs. the need to completely tear down/reconstruct
the host side of the device (including tap device).
This patch *does not* implement the "reconnect" code anyway - there is
a placeholder that turns that into an error. Rather, the purpose of
this patch is to replicate existing behavior with code that is ready
to have that functionality plugged in in a later patch.
* The expanded uses for qemuDomainChangeNetBridge meant that it needed
to be enhanced as well - it no longer replaces the original brname
string in olddev with the new brname; instead, it relies on the
caller to replace the *entire* olddev with newdev (since we've gone
to great lengths to assure they are functionally identical other
than the name of the bridge, this is now not only safe, but more
correct). Additionally, qemuDomainNetChangeBridge can now set the
bridge for type='network' interfaces as well as plain type='bridge'
interfaces. (Note that I had to make this change simultaneous to the
reorganization of qemuDomainChangeNet because the two are too
closely intertwined to separate).
---
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_hotplug.c | 502 ++++++++++++++++++++++++++++++++++++++----------
src/qemu/qemu_hotplug.h | 4 +-
3 files changed, 401 insertions(+), 107 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0787039..3a78465 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5987,7 +5987,7 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
break;
case VIR_DOMAIN_DEVICE_NET:
- ret = qemuDomainChangeNet(driver, vm, dom, dev->data.net);
+ ret = qemuDomainChangeNet(driver, vm, dom, dev);
break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 78f1278..0fe236f 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -33,6 +33,7 @@
#include "domain_audit.h"
#include "domain_nwfilter.h"
#include "logging.h"
+#include "datatypes.h"
#include "virterror_internal.h"
#include "memory.h"
#include "pci.h"
@@ -1209,27 +1210,88 @@ cleanup:
return -1;
}
-static virDomainNetDefPtr qemuDomainFindNet(virDomainObjPtr vm,
- virDomainNetDefPtr dev)
+static virDomainNetDefPtr *qemuDomainFindNet(virDomainObjPtr vm,
+ virDomainNetDefPtr dev)
{
int i;
for (i = 0; i < vm->def->nnets; i++) {
if (virMacAddrCmp(&vm->def->nets[i]->mac, &dev->mac) == 0)
- return vm->def->nets[i];
+ return &vm->def->nets[i];
}
return NULL;
}
-static
-int qemuDomainChangeNetBridge(virDomainObjPtr vm,
- virDomainNetDefPtr olddev,
- virDomainNetDefPtr newdev)
+static char *
+qemuDomainNetGetBridgeName(virConnectPtr conn, virDomainNetDefPtr net)
+{
+ char *brname = NULL;
+ int actualType = virDomainNetGetActualType(net);
+
+ if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ const char *tmpbr = virDomainNetGetActualBridgeName(net);
+ if (!tmpbr) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("interface is missing bridge name"));
+ goto cleanup;
+ }
+ /* we need a copy, not just a pointer to the original */
+ if (!(brname = strdup(tmpbr))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ int active;
+ virErrorPtr errobj;
+ virNetworkPtr network;
+
+ if (!(network = virNetworkLookupByName(conn, net->data.network.name))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Couldn't find network '%s'"),
+ net->data.network.name);
+ goto cleanup;
+ }
+
+ active = virNetworkIsActive(network);
+ if (active == 1) {
+ brname = virNetworkGetBridgeName(network);
+ } else if (active == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network '%s' is not active."),
+ net->data.network.name);
+ }
+
+ /* Make sure any above failure is preserved */
+ errobj = virSaveLastError();
+ virNetworkFree(network);
+ virSetError(errobj);
+ virFreeError(errobj);
+ goto cleanup;
+
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network type %d is not supported"),
+ virDomainNetGetActualType(net));
+cleanup:
+ return brname;
+}
+
+static int
+qemuDomainChangeNetBridge(virConnectPtr conn,
+ virDomainObjPtr vm,
+ virDomainNetDefPtr olddev,
+ virDomainNetDefPtr newdev)
{
int ret = -1;
- char *oldbridge = olddev->data.bridge.brname;
- char *newbridge = newdev->data.bridge.brname;
+ char *oldbridge = NULL, *newbridge = NULL;
+
+ if (!(oldbridge = qemuDomainNetGetBridgeName(conn, olddev)))
+ goto cleanup;
+
+ if (!(newbridge = qemuDomainNetGetBridgeName(conn, newdev)))
+ goto cleanup;
VIR_DEBUG("Change bridge for interface %s: %s -> %s",
olddev->ifname, oldbridge, newbridge);
@@ -1237,23 +1299,19 @@ int qemuDomainChangeNetBridge(virDomainObjPtr vm,
if (virNetDevExists(newbridge) != 1) {
virReportError(VIR_ERR_OPERATION_FAILED,
_("bridge %s doesn't exist"), newbridge);
- return -1;
+ goto cleanup;
}
if (oldbridge) {
ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
if (ret < 0)
- return -1;
+ goto cleanup;
}
- /* move newbridge into olddev now so Audit log is correct */
- olddev->data.bridge.brname = newbridge;
ret = virNetDevBridgeAddPort(newbridge, olddev->ifname);
- virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
+ virDomainAuditNet(vm, NULL, newdev, "attach", ret == 0);
if (ret < 0) {
- /* restore oldbridge to olddev */
- olddev->data.bridge.brname = oldbridge;
ret = virNetDevBridgeAddPort(oldbridge, olddev->ifname);
virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
if (ret < 0) {
@@ -1261,12 +1319,14 @@ int qemuDomainChangeNetBridge(virDomainObjPtr vm,
_("unable to recover former state by adding port "
"to bridge %s"), oldbridge);
}
- return -1;
+ goto cleanup;
}
- /* oldbridge no longer needed, and newbridge moved to olddev */
+ /* caller will replace entire olddev with newdev in domain nets list */
+ ret = 0;
+cleanup:
VIR_FREE(oldbridge);
- newdev->data.bridge.brname = NULL;
- return 0;
+ VIR_FREE(newbridge);
+ return ret;
}
int qemuDomainChangeNetLinkState(struct qemud_driver *driver,
@@ -1300,124 +1360,358 @@ cleanup:
return ret;
}
-int qemuDomainChangeNet(struct qemud_driver *driver,
- virDomainObjPtr vm,
- virDomainPtr dom ATTRIBUTE_UNUSED,
- virDomainNetDefPtr dev)
-
+int
+qemuDomainChangeNet(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainPtr dom,
+ virDomainDeviceDefPtr dev)
{
- virDomainNetDefPtr olddev = qemuDomainFindNet(vm, dev);
- int ret = 0;
+ virDomainNetDefPtr newdev = dev->data.net;
+ virDomainNetDefPtr *devslot = qemuDomainFindNet(vm, newdev);
+ virDomainNetDefPtr olddev;
+ int oldType, newType;
+ bool needReconnect = false;
+ bool needBridgeChange = false;
+ bool needLinkStateChange = false;
+ bool needReplaceDevDef = false;
+ int ret = -1;
- if (!olddev) {
+ if (!devslot || !(olddev = *devslot)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("cannot find existing network device to modify"));
- return -1;
+ goto cleanup;
+ }
+
+ oldType = virDomainNetGetActualType(olddev);
+ if (oldType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ /* no changes are possible to a type='hostdev' interface */
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot change config of '%s' network type"),
+ virDomainNetTypeToString(oldType));
+ goto cleanup;
}
- if (olddev->type != dev->type) {
+ /* Check individual attributes for changes that can't be done to a
+ * live netdev. These checks *mostly* go in order of the
+ * declarations in virDomainNetDef in order to assure nothing is
+ * omitted. (exceptiong where noted in comments - in particular,
+ * some things require that a new "actual device" be allocated
+ * from the network driver first, but we delay doing that until
+ * after we've made as many other checks as possible)
+ */
+
+ /* type: this can change (with some restrictions), but the actual
+ * type of the new device connection isn't known until after we
+ * allocate the "actual" device.
+ */
+
+ if (virMacAddrCmp(&olddev->mac, &newdev->mac)) {
+ char oldmac[VIR_MAC_STRING_BUFLEN], newmac[VIR_MAC_STRING_BUFLEN];
+
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot change network interface mac address "
+ "from %s to %s"),
+ virMacAddrFormat(&olddev->mac, oldmac),
+ virMacAddrFormat(&newdev->mac, newmac));
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(olddev->model, newdev->model)) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot modify network device model from %s to %s"),
+ olddev->model ? olddev->model : "(default)",
+ newdev->model ? newdev->model : "(default)");
+ goto cleanup;
+ }
+
+ if (olddev->model && STREQ(olddev->model, "virtio") &&
+ (olddev->driver.virtio.name != newdev->driver.virtio.name ||
+ olddev->driver.virtio.txmode != newdev->driver.virtio.txmode ||
+ olddev->driver.virtio.ioeventfd != newdev->driver.virtio.ioeventfd ||
+ olddev->driver.virtio.event_idx != newdev->driver.virtio.event_idx)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot change network interface type"));
- return -1;
+ _("cannot modify virtio network device driver attributes"));
+ goto cleanup;
}
- if (!virNetDevVPortProfileEqual(olddev->virtPortProfile, dev->virtPortProfile)) {
+ /* data: this union will be examined later, after allocating new actualdev */
+ /* virtPortProfile: will be examined later, after allocating new actualdev */
+
+ if (olddev->tune.sndbuf_specified != newdev->tune.sndbuf_specified ||
+ olddev->tune.sndbuf != newdev->tune.sndbuf) {
+ needReconnect = true;
+ }
+
+ if (STRNEQ_NULLABLE(olddev->script, newdev->script)) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot change <virtualport> settings"));
+ _("cannot modify network device script attribute"));
+ goto cleanup;
}
- switch (olddev->type) {
- case VIR_DOMAIN_NET_TYPE_USER:
- break;
+ /* ifname: check if it's set in newdev. If not, retain the autogenerated one */
+ if (!(newdev->ifname ||
+ (newdev->ifname = strdup(olddev->ifname)))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (STRNEQ_NULLABLE(olddev->ifname, newdev->ifname)) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network device tap name"));
+ goto cleanup;
+ }
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (STRNEQ_NULLABLE(olddev->data.ethernet.dev, dev->data.ethernet.dev) ||
- STRNEQ_NULLABLE(olddev->script, dev->script) ||
- STRNEQ_NULLABLE(olddev->data.ethernet.ipaddr, dev->data.ethernet.ipaddr)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify ethernet network device configuration"));
- return -1;
- }
- break;
+ /* info: if newdev->info is empty, fill it in from olddev,
+ * otherwise verify that it matches - nothing is allowed to
+ * change. (There is no helper function to do this, so
+ * individually check the few feidls of virDomainDeviceInfo that
+ * are relevant in this case).
+ */
+ if (!virDomainDeviceAddressIsValid(&newdev->info,
+ VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
+ virDomainDeviceInfoCopy(&newdev->info, &olddev->info) < 0) {
+ goto cleanup;
+ }
+ if (!virDevicePCIAddressEqual(&olddev->info.addr.pci,
+ &newdev->info.addr.pci)) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network device guest PCI address"));
+ goto cleanup;
+ }
+ /* grab alias from olddev if not set in newdev */
+ if (!(newdev->info.alias ||
+ (newdev->info.alias = strdup(olddev->info.alias)))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (STRNEQ_NULLABLE(olddev->info.alias, newdev->info.alias)) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network device alias"));
+ goto cleanup;
+ }
+ if (olddev->info.rombar != newdev->info.rombar) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network device rom bar setting"));
+ goto cleanup;
+ }
+ if (STRNEQ_NULLABLE(olddev->info.romfile, newdev->info.romfile)) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network rom file"));
+ goto cleanup;
+ }
+ if (olddev->info.bootIndex != newdev->info.bootIndex) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("cannot modify network device boot index setting"));
+ goto cleanup;
+ }
+ /* (end of device info checks) */
- case VIR_DOMAIN_NET_TYPE_SERVER:
- case VIR_DOMAIN_NET_TYPE_CLIENT:
- case VIR_DOMAIN_NET_TYPE_MCAST:
- if (STRNEQ_NULLABLE(olddev->data.socket.address, dev->data.socket.address) ||
- olddev->data.socket.port != dev->data.socket.port) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify network socket device configuration"));
- return -1;
- }
- break;
+ if (STRNEQ_NULLABLE(olddev->filter, newdev->filter))
+ needReconnect = true;
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- if (STRNEQ_NULLABLE(olddev->data.network.name, dev->data.network.name) ||
- STRNEQ_NULLABLE(olddev->data.network.portgroup, dev->data.network.portgroup)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify network device configuration"));
- return -1;
- }
+ /* bandwidth can be modified, and will be checked later */
+ /* vlan can be modified, and will be checked later */
+ /* linkstate can be modified */
+
+ /* allocate new actual device to compare to old - we will need to
+ * free it if we fail for any reason
+ */
+ if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+ networkAllocateActualDevice(newdev) < 0) {
+ goto cleanup;
+ }
+
+ newType = virDomainNetGetActualType(newdev);
+
+ if (newType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ /* can't turn it into a type='hostdev' interface */
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot change network interface type to '%s'"),
+ virDomainNetTypeToString(newType));
+ goto cleanup;
+ }
+
+ if (olddev->type == newdev->type && oldType == newType) {
+ /* if type hasn't changed, check the relevant fields for the type */
+ switch (newdev->type) {
+ case VIR_DOMAIN_NET_TYPE_USER:
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (STRNEQ_NULLABLE(olddev->data.ethernet.dev,
+ newdev->data.ethernet.dev) ||
+ STRNEQ_NULLABLE(olddev->script, newdev->script) ||
+ STRNEQ_NULLABLE(olddev->data.ethernet.ipaddr,
+ newdev->data.ethernet.ipaddr)) {
+ needReconnect = true;
+ }
break;
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
- /* allow changing brname */
- break;
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ if (STRNEQ_NULLABLE(olddev->data.socket.address,
+ newdev->data.socket.address) ||
+ olddev->data.socket.port != newdev->data.socket.port) {
+ needReconnect = true;
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (STRNEQ(olddev->data.network.name, newdev->data.network.name)) {
+ if (virDomainNetGetActualVirtPortProfile(newdev))
+ needReconnect = true;
+ else
+ needBridgeChange = true;
+ }
+ /* other things handled in common code directly below this switch */
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ /* all handled in bridge name checked in common code below */
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ if (STRNEQ_NULLABLE(olddev->data.internal.name,
+ newdev->data.internal.name)) {
+ needReconnect = true;
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ /* all handled in common code directly below this switch */
+ break;
+
+ default:
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("unable to change config on '%s' network type"),
+ virDomainNetTypeToString(newdev->type));
+ break;
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
- if (STRNEQ_NULLABLE(olddev->data.internal.name, dev->data.internal.name)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify internal network device configuration"));
- return -1;
}
- break;
+ } else {
+ /* interface type has changed. There are a few special cases
+ * where this can only require a minor (or even no) change,
+ * but in most cases we need to do a full reconnection.
+ *
+ * If we switch (in either direction) between type='bridge'
+ * and type='network' (for a traditional managed virtual
+ * network that uses a host bridge, i.e. forward
+ * mode='route|nat'), we just need to change the bridge.
+ */
+ if ((oldType == VIR_DOMAIN_NET_TYPE_NETWORK &&
+ newType == VIR_DOMAIN_NET_TYPE_BRIDGE) ||
+ (oldType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ newType == VIR_DOMAIN_NET_TYPE_NETWORK)) {
+
+ needBridgeChange = true;
+
+ } else if (oldType == VIR_DOMAIN_NET_TYPE_DIRECT &&
+ newType == VIR_DOMAIN_NET_TYPE_DIRECT) {
+
+ /* this is the case of switching from type='direct' to
+ * type='network' for a network that itself uses direct
+ * (macvtap) devices. If the physical device and mode are
+ * the same, this doesn't require any actual setup
+ * change. If the physical device or mode *does* change,
+ * that will be caught in the common section below */
+
+ } else {
+
+ /* for all other combinations, we'll need a full reconnect */
+ needReconnect = true;
- case VIR_DOMAIN_NET_TYPE_DIRECT:
- if (STRNEQ_NULLABLE(olddev->data.direct.linkdev, dev->data.direct.linkdev) ||
- olddev->data.direct.mode != dev->data.direct.mode) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify direct network device configuration"));
- return -1;
}
- break;
+ }
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("unable to change config on '%s' network type"),
- virDomainNetTypeToString(dev->type));
- break;
+ /* now several things that are in multiple (but not all)
+ * different types, and can be safely compared even for those
+ * cases where they don't apply to a particular type.
+ */
+ if (STRNEQ_NULLABLE(virDomainNetGetActualBridgeName(olddev),
+ virDomainNetGetActualBridgeName(newdev))) {
+ if (virDomainNetGetActualVirtPortProfile(newdev))
+ needReconnect = true;
+ else
+ needBridgeChange = true;
+ }
+ if (STRNEQ_NULLABLE(virDomainNetGetActualDirectDev(olddev),
+ virDomainNetGetActualDirectDev(newdev)) ||
+ virDomainNetGetActualDirectMode(olddev) != virDomainNetGetActualDirectMode(olddev) ||
+ !virNetDevVPortProfileEqual(virDomainNetGetActualVirtPortProfile(olddev),
+ virDomainNetGetActualVirtPortProfile(newdev)) ||
+ !virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
+ virDomainNetGetActualBandwidth(newdev)) ||
+ !virNetDevVlanEqual(virDomainNetGetActualVlan(olddev),
+ virDomainNetGetActualVlan(newdev))) {
+ needReconnect = true;
}
- /* all other unmodifiable parameters */
- if (STRNEQ_NULLABLE(olddev->model, dev->model) ||
- STRNEQ_NULLABLE(olddev->filter, dev->filter)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify network device configuration"));
- return -1;
+ if (olddev->linkstate != newdev->linkstate)
+ needLinkStateChange = true;
+
+ /* FINALLY - actually perform the required actions */
+
+ if (needReconnect) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("unable to change config on '%s' network type"),
+ virDomainNetTypeToString(newdev->type));
+ goto cleanup;
}
- /* check if device name has been set, if no, retain the autogenerated one */
- if (dev->ifname &&
- STRNEQ_NULLABLE(olddev->ifname, dev->ifname)) {
- virReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("cannot modify network device configuration"));
- return -1;
+ if (needBridgeChange) {
+ if (qemuDomainChangeNetBridge(dom->conn, vm, olddev, newdev) < 0)
+ goto cleanup;
+ /* we successfully switched to the new bridge, and we've
+ * determined that the rest of newdev is equivalent to olddev,
+ * so move newdev into place, so that the */
+ needReplaceDevDef = true;
}
- if (olddev->type == VIR_DOMAIN_NET_TYPE_BRIDGE
- && STRNEQ_NULLABLE(olddev->data.bridge.brname,
- dev->data.bridge.brname)) {
- if ((ret = qemuDomainChangeNetBridge(vm, olddev, dev)) < 0)
- return ret;
+ if (needLinkStateChange &&
+ qemuDomainChangeNetLinkState(driver, vm, olddev, newdev->linkstate) < 0) {
+ goto cleanup;
}
- if (olddev->linkstate != dev->linkstate) {
- if ((ret = qemuDomainChangeNetLinkState(driver, vm, olddev, dev->linkstate)) < 0)
- return ret;
+ if (needReplaceDevDef) {
+ /* the changes above warrant replacing olddev with newdev in
+ * the domain's nets list.
+ */
+ networkReleaseActualDevice(olddev);
+ virDomainNetDefFree(olddev);
+ /* move newdev into the nets list, and NULL it out from the
+ * virDomainDeviceDef that we were given so that the caller
+ * won't delete it on return.
+ */
+ *devslot = newdev;
+ newdev = dev->data.net = NULL;
+ dev->type = VIR_DOMAIN_DEVICE_NONE;
}
+ ret = 0;
+cleanup:
+ /* When we get here, we will be in one of these two states:
+ *
+ * 1) newdev has been moved into the domain's list of nets and
+ * newdev set to NULL, and dev->data.net will be NULL (and
+ * dev->type is NONE). olddev will have been completely
+ * released and freed. (aka success) In this case no extra
+ * cleanup is needed.
+ *
+ * 2) newdev has *not* been moved into the domain's list of nets,
+ * and dev->data.net == newdev (and dev->type == NET). In this *
+ * case, we need to at least release the "actual device" from *
+ * newdev (the caller will free dev->data.net a.k.a. newdev, and
+ * the original olddev is still in used)
+ *
+ * Note that case (2) isn't necessarily a failure. It may just be
+ * that the changes were minor enough that we didn't need to
+ * replace the entire device object.
+ */
+ if (newdev)
+ networkReleaseActualDevice(newdev);
+
return ret;
}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 36c0580..a7864c3 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -1,7 +1,7 @@
/*
* qemu_hotplug.h: QEMU device hotplug management
*
- * Copyright (C) 2006-2007, 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2012 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -77,7 +77,7 @@ int qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
int qemuDomainChangeNet(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainPtr dom,
- virDomainNetDefPtr dev);
+ virDomainDeviceDefPtr dev);
int qemuDomainChangeNetLinkState(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainNetDefPtr dev,
--
1.7.11.7
12 years, 1 month
[libvirt] Potential race condition problem
by Benjamin Wang (gendwang)
Hi,
Currently virInitialize() method defined in libvirt.c has the following code:
int
virInitialize(void)
{
if (initialized)
return 0;
initialized = 1;
if (virThreadInitialize() < 0 ||
virErrorInitialize() < 0 ||
virRandomInitialize(time(NULL) ^ getpid()) ||
virNodeSuspendInit() < 0)
return -1;
......
}
When two threads access virInitialize method, there is no lock for the "initialized" parameter. If the first thread enters this method and set "initialized" to 1,
the second thread could see that "initialized" is 1(Because initialized is not volatiled, I say could). In some situation, before the first thread finishes all the initialization,
the second thread could use some resources which should be initialized in Initialize method.
If you have any comments, please let me know. Thanks!
B.R.
Benjamin Wang
12 years, 1 month
[libvirt] how to enable ceph-rbd in libvirt.
by yue
1.my libvirtd version is 0.9.10. i rebuild qemu with --enable-rbd.
it seems not work if guest-os has a rbd disk.
-----rbd disk info ----
<disk type='network' device='disk'>
<driver name='qemu' type='raw'/>
<auth username='cloud'>
<secret type='ceph' uuid='7a91dc24-b072-43c4-98fb-4b2415322b0f'/>
</auth>
<source protocol='rbd' name='cloud/testrbd'>
<host name='192.168.10.4' port='6789'/>
</source>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
2.-----------------------error log---------
LC_ALL=C PATH=/sbin:/usr/sbin:/bin:/usr/bin HOME=/root USER=root LOGNAME=root QEMU_AUDIO_DRV=none /usr/libexec/qemu-kvm -S -M rhel6.2.0 -enable-kvm -m 512 -smp 1,sockets=1,cores=1,threads=1 -name xpSP3 -uuid b45bd66a-6700-4905-c5f4-4c799413d7b7 -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/xpSP3.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=localtime,driftfix=slew -no-shutdown -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/var/lib/libvirt/images/xpSP3.img,if=none,id=drive-ide0-0-0,format=raw,cache=none -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -drive file=rbd:cloud/testrbd:id=cloud:key=AQCGbGRQ+M+NGBAATtylZNiSxqCTQ4uaApd+9w==:auth_supported=cephx none:mon_host=192.168.10.4\:6789,if=none,id=drive-virtio-disk1,format=raw -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1 -netdev tap,fd=26,id=hostnet0 -device e!
1000,netdev=hostnet0,id=net0,mac=52:54:00:2a:8c:48,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -vnc 0.0.0.0:0 -vga std -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
Domain id=6 is tainted: high-privileges
char device redirected to /dev/pts/4
qemu-kvm: -drive file=rbd:cloud/testrbd:id=cloud:key=AQCGbGRQ+M+NGBAATtylZNiSxqCTQ4uaApd+9w==:auth_supported=cephx none:mon_host=192.168.10.4\:6789,if=none,id=drive-virtio-disk1,format=raw: could not open disk image rbd:cloud/testrbd:id=cloud:key=AQCGbGRQ+M+NGBAATtylZNiSxqCTQ4uaApd+9w==:auth_supported=cephx none:mon_host=192.168.10.4\:6789: No such file or directory
2012-10-11 10:37:24.215+0000: shutting down
12 years, 1 month
[libvirt] [PATCH 0/7 v2] CPU tuning improvements
by Osier Yang
As proposed in
https://www.redhat.com/archives/libvir-list/2012-October/msg00522.html,
This patch set is trying to resolve the conflicts between <vcpu>
, <vcpupin>, and <emulatorpin>, when doing CPU tuning for domain
process or vcpu threads.
PATCH 1/7 changes all the doc together, as the 3 elements are
related with each other too tightly, splitting the changes in
separate patches will just make things obscure and hard to
review. See commit log of PATCH 1/7 for overview/details about
the solution.
Osier Yang (7):
doc: Clarify the relationship between <vcpu>, <vcpupin>, and
<emulatorpin>
conf: Do not allow vcpupin's cpuid exceed current vcpus number
conf: Initialize the pinning policy for vcpus
qemu: Create or remove cgroup when doing vcpu hotpluging
qemu: Initialize cpuset for hotplugged vcpu as def->cpuset
conf: Prohibit emulatorpin if vcpu placement is auto
qemu: Ignore def->cpumask if emulatorpin is specified
docs/formatdomain.html.in | 42 +++++++++++------
src/conf/domain_conf.c | 103 ++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 3 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 3 +-
6 files changed, 243 insertions(+), 19 deletions(-)
--
1.7.7.6
Regards,
Osier
12 years, 1 month
[libvirt] [PATCH] daemon: Use $(AM_V_GEN) in a few more places
by Cole Robinson
---
daemon/Makefile.am | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3405c67..1c7505b 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -84,10 +84,10 @@ augeastests_DATA = test_libvirtd.aug
CLEANFILES += test_libvirtd.aug
libvirtd.8: $(srcdir)/libvirtd.8.in
- sed \
+ $(AM_V_GEN)sed \
-e 's!SYSCONFDIR!$(sysconfdir)!g' \
-e 's!LOCALSTATEDIR!$(localstatedir)!g' \
- < $< > $@-t
+ < $< > $@-t && \
mv $@-t $@
libvirtd_SOURCES = $(DAEMON_SOURCES)
@@ -215,15 +215,15 @@ LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \
BUILT_SOURCES += $(LOGROTATE_CONFS)
libvirtd.logrotate: libvirtd.logrotate.in
- sed \
+ $(AM_V_GEN)sed \
-e 's![@]localstatedir[@]!$(localstatedir)!g' \
- < $< > $@-t
+ < $< > $@-t && \
mv $@-t $@
libvirtd.qemu.logrotate: libvirtd.qemu.logrotate.in
- sed \
+ $(AM_V_GEN)sed \
-e 's![@]localstatedir[@]!$(localstatedir)!g' \
- < $< > $@-t
+ < $< > $@-t && \
mv $@-t $@
libvirtd.lxc.logrotate: libvirtd.lxc.logrotate.in
--
1.7.11.4
12 years, 1 month