[libvirt] [RFC PATCH 00/12] Add support for memory hotplug
by Peter Krempa
!! this series applies on top of the cleanup series posted earlier !!
Hi,
this is my try to implement memory hotplug in libvirt (for the qemu) driver.
This series is almost code-complete but is lacking tests and docs as I wanted
to agree on design first before attempting to write the documentation.
Additionally this series is also lacking code that would fix memballoon
handling but I'm waiting on a clousure how it's supposed to work from qemu's
side as it appears to be broken there too.
The basic XML used to add a memory device:
<memory model='acpi-dimm'>
<target>
<size unit='KiB'>524287</size>
<node>0</node>
</target>
</memory>
The <target> subelement is mandatory, whereas the <source> subelement (that
contains source numa nodes, source page size ) is optional and is inferred
from the NUMA tuning for given target numa node.
Please note that at least one guest numa node has to be configured for the
guest for this to work (limitation of qemu).
What's missing in this series:
- tests
- docs
- commit message touch-up
- code to audit the memory size changes
- code to make memory balloning working with correct size
Peter Krempa (12):
qemu: caps: Add capability bit for the "pc-dimm" device
conf: Add support for parsing and formatting max memory and slot count
qemu: Implement setup of memory hotplug parameters
conf: Add device address type for dimm devices
conf: Add interface to parse and format memory device information
qemu: memdev: Add infrastructure to load memory device information
qemu: migration: Forbid migration with memory modules lacking info
qemu: add support for memory devices
conf: Introduce helper to find duplicate device address
qemu: conf: Add support for memory device cold(un)plug
qemu: Implement memory device hotplug
qemu: Implement memory device hotunplug
docs/formatdomain.html.in | 19 +
docs/schemas/domaincommon.rng | 76 +++
src/bhyve/bhyve_domain.c | 9 +-
src/conf/domain_conf.c | 655 ++++++++++++++++++++-
src/conf/domain_conf.h | 63 ++
src/libvirt_private.syms | 7 +
src/libxl/libxl_domain.c | 8 +
src/lxc/lxc_domain.c | 8 +
src/openvz/openvz_driver.c | 14 +-
src/parallels/parallels_driver.c | 6 +-
src/phyp/phyp_driver.c | 6 +-
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 157 ++++-
src/qemu/qemu_command.h | 15 +
src/qemu/qemu_domain.c | 58 ++
src/qemu/qemu_domain.h | 6 +
src/qemu/qemu_driver.c | 29 +
src/qemu/qemu_hotplug.c | 178 ++++++
src/qemu/qemu_hotplug.h | 6 +
src/qemu/qemu_migration.c | 14 +
src/qemu/qemu_monitor.c | 45 ++
src/qemu/qemu_monitor.h | 14 +
src/qemu/qemu_monitor_json.c | 116 ++++
src/qemu/qemu_monitor_json.h | 5 +
src/qemu/qemu_process.c | 4 +
src/uml/uml_driver.c | 9 +-
src/vbox/vbox_common.c | 6 +-
src/vmware/vmware_driver.c | 6 +-
src/vmx/vmx.c | 6 +-
src/xen/xen_driver.c | 7 +
src/xenapi/xenapi_driver.c | 9 +-
tests/domainschemadata/maxMemory.xml | 19 +
tests/qemucapabilitiesdata/caps_2.1.1-1.caps | 1 +
.../qemuxml2argv-memory-hotplug-dimm.xml | 47 ++
.../qemuxml2argv-memory-hotplug-nonuma.xml | 22 +
.../qemuxml2argv-memory-hotplug.args | 6 +
.../qemuxml2argv-memory-hotplug.xml | 34 ++
tests/qemuxml2argvtest.c | 4 +
tests/qemuxml2xmltest.c | 4 +
40 files changed, 1682 insertions(+), 19 deletions(-)
create mode 100644 tests/domainschemadata/maxMemory.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-dimm.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-nonuma.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug.xml
--
2.2.2
9 years, 9 months
[libvirt] [PATCH 0/2] S390: ccw support for virsh attach-disk address parameter
by Stefan Zimmermann
This patch add the ccw support for the optional address parameter of virsh
attach-disk.
Stefan Zimmermann (2):
S390: ccw support for virsh attach-disk address parameter
S390: Documentation for ccw address type
docs/formatdomain.html.in | 5 ++---
tools/virsh-domain.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
tools/virsh.pod | 3 ++-
3 files changed, 49 insertions(+), 5 deletions(-)
--
2.1.4
9 years, 9 months
[libvirt] [PATCH 0/6] security: Add check for invalid security models and duplicates
by Erik Skultety
Add a check for invalid security models in per-device configuration as well as a
check for seclabel duplicates in per-device configuration
Erik Skultety (6):
security: Add check for valid security model
conf: fix a minor typo
conf: forbid seclabel duplicates for domain devices
schema: allow multiple seclabel for devices in domaincommon.rng
test: add test to check for device seclabel duplicates
po: add security_stack.c into POTFILES.in
docs/schemas/domaincommon.rng | 16 ++++----
po/POTFILES.in | 1 +
src/conf/domain_conf.c | 11 ++++-
src/security/security_manager.c | 5 +++
src/security/security_manager.h | 1 +
src/security/security_stack.c | 48 +++++++++++++++++++++-
.../qemuxml2argv-seclabel-device-multiple.xml | 35 ++++++++++++++++
7 files changed, 106 insertions(+), 11 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-seclabel-device-multiple.xml
--
1.9.3
9 years, 9 months
[libvirt] [PATCH] Follow up fix of commit a58e1cb4
by Cédric Bosdonnat
commit a58e1cb4 didn't fix the bug if the security_default_confined is
not set to 1. We now clean up even if there is no seclabel defined or
the default one.
---
src/lxc/lxc_process.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index b385423..19ea7f3 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -1022,6 +1022,7 @@ int virLXCProcessStart(virConnectPtr conn,
virCgroupPtr selfcgroup;
int status;
char *pidfile = NULL;
+ bool clearSeclabel = false;
if (virCgroupNewSelf(&selfcgroup) < 0)
return -1;
@@ -1126,6 +1127,10 @@ int virLXCProcessStart(virConnectPtr conn,
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
VIR_DEBUG("Generating domain security label (if required)");
+
+ clearSeclabel = vm->def->nseclabels == 0 ||
+ vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT;
+
if (vm->def->nseclabels &&
vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT)
vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;
@@ -1387,7 +1392,8 @@ int virLXCProcessStart(virConnectPtr conn,
virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
/* Clear out dynamically assigned labels */
if (vm->def->nseclabels &&
- vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+ (vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC ||
+ clearSeclabel)) {
VIR_FREE(vm->def->seclabels[0]->model);
VIR_FREE(vm->def->seclabels[0]->label);
VIR_FREE(vm->def->seclabels[0]->imagelabel);
--
2.1.4
9 years, 9 months
[libvirt] ANNOUNCE: libvirt 1.2.9.2 maintenance release
by Cole Robinson
libvirt 1.2.9.2 is now available. This is a maintenance release of
libvirt 1.2.9 with additional bugfixes that have accumulated
upstream since the initial release.
This release can be downloaded at:
http://libvirt.org/sources/stable_updates/libvirt-1.2.9.2.tar.gz
Changes in this version:
* util: storage: Fix parsing of nbd:// URI without path
* qemu: fix domain startup failing with 'strict' mode in numatune
* storage: Need to clear pool prior to refreshPool during Autostart
* xend: Don't crash in virDomainXMLDevID
* CVE-2015-0236: qemu: Check ACLs when dumping security info from
snapshots
* CVE-2015-0236: qemu: Check ACLs when dumping security info from save
image
* conf: goto error when value of max_sectors is too large
* Fix hotplugging of block device-backed usb disks
* conf: fix crash when hotplug a channel chr device with no target
* qemu: migration: Unlock vm on failed ACL check in protocol v2 APIs
* storage: fix crash caused by no check return before set close
* qemu: bulk stats: Fix logic in monitor handling
* CVE-2014-8131: Fix possible deadlock and segfault in
qemuConnectGetAllDomainStats()
* qemu: Drop OVMF whitelist
* qemu: Support OVMF on armv7l aarch64 guests
For info about past maintenance releases, see:
http://wiki.libvirt.org/page/Maintenance_Releases
Thanks,
Cole
9 years, 9 months
[libvirt] virt-manager issue, FreeBSD
by Jason Helfman
Hi,
I am working on resolving an issue with virt-manager on FreeBSD. A
contributor recently worked on getting spice-gtk ported to FreeBSD,
however I am working on this error when launching console.py.
[helfman@its-helfman03 ~/workspace/ports/deskutils/virt-manager]$ python
/usr/local/share/virt-manager/virtManager/console.py
Traceback (most recent call last):
File "/usr/local/share/virt-manager/virtManager/console.py", line 42, in
<module>
from virtManager.autodrawer import AutoDrawer
ImportError: No module named virtManager.autodrawer
Thanks for your help!
Jason
--
Jason Helfman | FreeBSD Committer
jgh(a)FreeBSD.org | http://people.freebsd.org/~jgh | The Power to Serve
9 years, 9 months
[libvirt] [PATCH v3] qemu: Pass file descriptor when using TPM passthrough
by Stefan Berger
Pass the TPM file descriptor to QEMU via command line.
Instead of passing /dev/tpm0 we now pass /dev/fdset/10 and the additional
parameters -add-fd set=10,fd=20.
This addresses the use case when QEMU is started with non-root privileges
and QEMU cannot open /dev/tpm0 for example.
One problem is that for the passing of the file descriptor set to work,
virCommandReorderFDs must not be called on the virCommand. This is prevented
by setting a flag in the virCommandPassFDGetFDIndex that is checked to be
clear when virCommandReorderFDs is run.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
v2->v3: Fixed some memory leaks
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 136 ++++++++++++++++++++++++++++++++++++++++++++---
src/util/vircommand.c | 33 ++++++++++++
src/util/vircommand.h | 3 ++
4 files changed, 166 insertions(+), 7 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index aeec440..3194e8b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1164,6 +1164,7 @@ virCommandNewArgList;
virCommandNewArgs;
virCommandNonblockingFDs;
virCommandPassFD;
+virCommandPassFDGetFDIndex;
virCommandPassListenFDs;
virCommandRawStatus;
virCommandRequireHandshake;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8ed7934..17debba 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -159,6 +159,58 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
"interleave");
/**
+ * qemuVirCommandGetFDSet:
+ * @cmd: the command to modify
+ * @fd: fd to reassign to the child
+ *
+ * Get the parameters for the QEMU -add-fd command line option
+ * for the given file descriptor. The file descriptor must previously
+ * have been 'transferred' in a virCommandPassFD() call.
+ * This function for example returns "set=10,fd=20".
+ */
+static char *
+qemuVirCommandGetFDSet(virCommandPtr cmd, int fd)
+{
+ char *result = NULL;
+ int idx = virCommandPassFDGetFDIndex(cmd, fd);
+
+ if (idx >= 0) {
+ ignore_value(virAsprintf(&result, "set=%d,fd=%d", idx, fd) < 0);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("file descriptor %d has not been transferred"), fd);
+ }
+
+ return result;
+}
+
+/**
+ * qemuVirCommandGetDevSet:
+ * @cmd: the command to modify
+ * @fd: fd to reassign to the child
+ *
+ * Get the parameters for the QEMU path= parameter where a file
+ * descriptor is accessed via a file descriptor set, for example
+ * /dev/fdset/10. The file descriptor must previously have been
+ * 'transferred' in a virCommandPassFD() call.
+ */
+static char *
+qemuVirCommandGetDevSet(virCommandPtr cmd, int fd)
+{
+ char *result = NULL;
+ int idx = virCommandPassFDGetFDIndex(cmd, fd);
+
+ if (idx >= 0) {
+ ignore_value(virAsprintf(&result, "/dev/fdset/%d", idx) < 0);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("file descriptor %d has not been transferred"), fd);
+ }
+ return result;
+}
+
+
+/**
* qemuPhysIfaceConnect:
* @def: the definition of the VM (needed by 802.1Qbh and audit)
* @driver: pointer to the driver instance
@@ -5926,14 +5978,20 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
static char *qemuBuildTPMBackendStr(const virDomainDef *def,
+ virCommandPtr cmd,
virQEMUCapsPtr qemuCaps,
- const char *emulator)
+ const char *emulator,
+ int *tpmfd, int *cancelfd)
{
const virDomainTPMDef *tpm = def->tpm;
virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *type = virDomainTPMBackendTypeToString(tpm->type);
- char *cancel_path;
+ char *cancel_path = NULL;
const char *tpmdev;
+ char *devset = NULL, *cancel_devset = NULL;
+
+ *tpmfd = -1;
+ *cancelfd = -1;
virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias);
@@ -5946,11 +6004,49 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
goto error;
- virBufferAddLit(&buf, ",path=");
- virBufferEscape(&buf, ',', ",", "%s", tpmdev);
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ADD_FD)) {
+ *tpmfd = open(tpmdev, O_RDWR);
+ if (*tpmfd < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not open TPM device %s"), tpmdev);
+ goto error;
+ }
+
+ virCommandPassFD(cmd, *tpmfd,
+ VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ devset = qemuVirCommandGetDevSet(cmd, *tpmfd);
+ if (devset == NULL)
+ goto error;
+
+ *cancelfd = open(cancel_path, O_WRONLY);
+ if (*cancelfd < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not open TPM device's cancel path "
+ "%s"), cancel_path);
+ goto error;
+ }
+
+ virCommandPassFD(cmd, *cancelfd,
+ VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ cancel_devset = qemuVirCommandGetDevSet(cmd, *cancelfd);
+ if (cancel_devset == NULL)
+ goto error;
+
+ virBufferAddLit(&buf, ",path=");
+ virBufferEscape(&buf, ',', ",", "%s", devset);
+ VIR_FREE(devset);
- virBufferAddLit(&buf, ",cancel-path=");
- virBufferEscape(&buf, ',', ",", "%s", cancel_path);
+ virBufferAddLit(&buf, ",cancel-path=");
+ virBufferEscape(&buf, ',', ",", "%s", cancel_devset);
+ VIR_FREE(cancel_devset);
+ } else {
+ /* all test cases will use this path */
+ virBufferAddLit(&buf, ",path=");
+ virBufferEscape(&buf, ',', ",", "%s", tpmdev);
+
+ virBufferAddLit(&buf, ",cancel-path=");
+ virBufferEscape(&buf, ',', ",", "%s", cancel_path);
+ }
VIR_FREE(cancel_path);
break;
@@ -5970,6 +6066,10 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
emulator, type);
error:
+ VIR_FREE(devset);
+ VIR_FREE(cancel_devset);
+ VIR_FREE(cancel_path);
+
virBufferFreeAndReset(&buf);
return NULL;
}
@@ -9223,13 +9323,35 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->tpm) {
char *optstr;
+ int tpmfd = -1;
+ int cancelfd = -1;
+ char *fdset;
- if (!(optstr = qemuBuildTPMBackendStr(def, qemuCaps, emulator)))
+ if (!(optstr = qemuBuildTPMBackendStr(def, cmd, qemuCaps, emulator,
+ &tpmfd, &cancelfd)))
goto error;
virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
VIR_FREE(optstr);
+ if (tpmfd >= 0) {
+ fdset = qemuVirCommandGetFDSet(cmd, tpmfd);
+ if (!fdset)
+ goto error;
+
+ virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
+ VIR_FREE(fdset);
+ }
+
+ if (cancelfd >= 0) {
+ fdset = qemuVirCommandGetFDSet(cmd, cancelfd);
+ if (!fdset)
+ goto error;
+
+ virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
+ VIR_FREE(fdset);
+ }
+
if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps, emulator)))
goto error;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 6527d85..2616446 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -67,6 +67,7 @@ enum {
VIR_EXEC_RUN_SYNC = (1 << 3),
VIR_EXEC_ASYNC_IO = (1 << 4),
VIR_EXEC_LISTEN_FDS = (1 << 5),
+ VIR_EXEC_FIXED_FDS = (1 << 6),
};
typedef struct _virCommandFD virCommandFD;
@@ -214,6 +215,12 @@ virCommandReorderFDs(virCommandPtr cmd)
if (!cmd || cmd->has_error || !cmd->npassfd)
return;
+ if ((cmd->flags & VIR_EXEC_FIXED_FDS)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("The fds are fixed and cannot be reordered"));
+ goto error;
+ }
+
for (i = 0; i < cmd->npassfd; i++)
maxfd = MAX(cmd->passfd[i].fd, maxfd);
@@ -1019,6 +1026,32 @@ virCommandPassListenFDs(virCommandPtr cmd)
cmd->flags |= VIR_EXEC_LISTEN_FDS;
}
+/*
+ * virCommandPassFDGetFDIndex:
+ * @cmd: pointer to virCommand
+ * @fd: FD to get index of
+ *
+ * Determine the index of the FD in the transfer set.
+ *
+ * Returns index >= 0 if @set contains @fd,
+ * -1 otherwise.
+ */
+int
+virCommandPassFDGetFDIndex(virCommandPtr cmd, int fd)
+{
+ size_t i = 0;
+
+ while (i < cmd->npassfd) {
+ if (cmd->passfd[i].fd == fd) {
+ cmd->flags |= VIR_EXEC_FIXED_FDS;
+ return i;
+ }
+ i++;
+ }
+
+ return -1;
+}
+
/**
* virCommandSetPidFile:
* @cmd: the command to modify
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index bf65de4..198da2f 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -62,6 +62,9 @@ void virCommandPassFD(virCommandPtr cmd,
void virCommandPassListenFDs(virCommandPtr cmd);
+int virCommandPassFDGetFDIndex(virCommandPtr cmd,
+ int fd);
+
void virCommandSetPidFile(virCommandPtr cmd,
const char *pidfile) ATTRIBUTE_NONNULL(2);
--
1.9.3
9 years, 9 months
[libvirt] [PATCH v2] maint: improve usage of autogen's --no-git
by Stefan Zimmermann
If you will build libvirt with the no-git-option than you is the
gnulib-srcdir mandatory. You will lose this information till now. With
this patch you will save this information.
Signed-off-by: Stefan Zimmermann <stzi(a)linux.vnet.ibm.com>
---
autogen.sh | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/autogen.sh b/autogen.sh
index 1965f64..d1c319d 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -20,6 +20,10 @@ no_git=
if test "x$1" = "x--no-git"; then
no_git=" $1"
shift
+ case "$1 $2" in
+ --gnulib-srcdir=*) no_git="$no_git $1"; shift ;;
+ --gnulib-srcdir\ *) no_git="$no_git $1=$2"; shift; shift;;
+ esac
fi
if test -z "$NOCONFIGURE" ; then
if test "x$1" = "x--system"; then
--
2.1.4
9 years, 9 months
[libvirt] [PATCH] network: don't allow multiple portgroups with the same name in a network
by Laine Stump
When defining and creating networks, we have been checking to make
sure there is only a single "default" portgroup, but haven't verified
that no two portgroups have the same name. We *do* check for multiple
definitions when updating the portgroups in an existing network
though.
This patch adds a check to networkValidate(), which is called when a
network is defined or created, to disallow duplicate names. It would
actually make sense to do this in the network XML parser (since it's
not really "something that might make sense but isn't supported by
this driver", but is instead "something that should never be
allowed"), but doing that carries the danger of causing errors when
rereading the config of existing networks when libvirtd is restarted
after an upgrade, and that would result in networks disappearing from
libvirt's list. (I'm thinking I should change the error to "XML_ERROR"
instead of "UNSUPPORTED", even though that's not the type of error
that networkValidate is intended for)
This resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1115858
---
src/network/bridge_driver.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c56e8f2..d549ca5 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1,7 +1,7 @@
/*
* bridge_driver.c: core driver methods for managing network
*
- * Copyright (C) 2006-2014 Red Hat, Inc.
+ * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -2728,7 +2728,7 @@ static int
networkValidate(virNetworkDefPtr def,
bool check_active)
{
- size_t i;
+ size_t i, j;
bool vlanUsed, vlanAllowed, badVlanUse = false;
virPortGroupDefPtr defaultPortGroup = NULL;
virNetworkIpDefPtr ipdef;
@@ -2874,7 +2874,15 @@ networkValidate(virNetworkDefPtr def,
}
defaultPortGroup = &def->portGroups[i];
}
-
+ for (j = i+1; j < def->nPortGroups; j++) {
+ if (STREQ(def->portGroups[i].name, def->portGroups[j].name)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("multiple <portgroup> elements with the "
+ "same name (%s) in network '%s'"),
+ def->portGroups[i].name, def->name);
+ return -1;
+ }
+ }
if (def->portGroups[i].bandwidth && !bandwidthAllowed) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported <bandwidth> element in network '%s' "
--
2.1.0
9 years, 9 months