[libvirt] [PATCH v3 0/4] Allow to make disk optional on migration
by Michal Privoznik
This is a 3rd version of patches [1].
Diff to v2 includes Daniel's review and some other improvements.
The aim of these patches is to mark CDROM and floppy optional,
thus they might get dropped during migration, domain startup,
restore, etc. The granularity is set on disk level, so user
can decide which cd-roms are important and which not.
There are 3 levels of optionality:
- mandatory - fail if missing for any reason (the default)
- requisite - fail if missing on boot up, drop if missing on
migrate/restore/revert
- optional - drop if missing at any start attempt.
To assign a disk one of these, just append 'on_missing' attribute
to its <source>.
If a domain is then eventually started (migrated, restored, whatever),
we check for source path being accessible (currently only qemu driver
is supported) from hypervisor's POV. This is done by virFileAccessibleAs()
function. Currently, only uid+gid are considered. Ideally, this
should be extended to SElinux labeling and cgroups.
1: https://www.redhat.com/archives/libvir-list/2011-October/msg00032.html
Michal Privoznik (4):
conf: Introduce optional on_missing attribute for cdrom and floppy
util: Create virFileAccessibleAs function
qemu: implement on_missing
on_missing: Emit event on disk source dropping
daemon/remote.c | 37 ++++++++++
docs/formatdomain.html.in | 26 ++++++-
docs/schemas/domaincommon.rng | 22 +++++-
examples/domain-events/events-c/event-test.c | 27 +++++++-
examples/domain-events/events-python/event-test.py | 4 +
include/libvirt/libvirt.h.in | 28 +++++++
python/libvirt-override-virConnect.py | 9 +++
python/libvirt-override.c | 51 +++++++++++++
src/conf/domain_conf.c | 43 ++++++++++-
src/conf/domain_conf.h | 11 +++
src/conf/domain_event.c | 50 +++++++++++++
src/conf/domain_event.h | 7 ++
src/libvirt_private.syms | 4 +
src/qemu/qemu_domain.c | 73 +++++++++++++++++++
src/qemu/qemu_domain.h | 4 +
src/qemu/qemu_process.c | 4 +
src/remote/remote_driver.c | 34 +++++++++
src/remote/remote_protocol.x | 9 ++-
src/remote_protocol-structs | 5 ++
src/util/util.c | 76 ++++++++++++++++++++
src/util/util.h | 3 +
.../qemuxml2xmlout-disk-cdrom-empty.xml | 31 ++++++++
22 files changed, 548 insertions(+), 10 deletions(-)
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-disk-cdrom-empty.xml
--
1.7.3.4
13 years, 2 months
[libvirt] [PATCH 1/2] Fix occasional container creation failure due to misuse of grantpt
by Serge E. Hallyn
glibc's grantpt and ptsname cannot be used on a fd for a pty not in
/dev/pts. The lxc controller tries to do just that. So if you try to
start a container on a system where /dev/pts/0 is not available, it
will fail. You can make this happen by opening a terminal on
/dev/pts/0, and doing 'sleep 2h & disown; exit'. To fix this, I call
the virFileOpenTtyAt() from a forked task in a new mount ns, and first
mount the container's /dev/pts onto /dev/pts. (Then the opened fd must
be passed back to the lxc driver). Another solution would be to just
do it all by hand without grantpt and ptsname.
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/863629
Signed-off-by: Serge Hallyn <serge.hallyn(a)canonical.com>
---
src/lxc/lxc_controller.c | 117 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 112 insertions(+), 5 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 51488e7..1a56e0c 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -780,6 +780,113 @@ static int lxcSetPersonality(virDomainDefPtr def)
# define MS_SLAVE (1<<19)
#endif
+static int send_pty(int sock, int *pty)
+{
+ struct iovec vector;
+ struct msghdr msg;
+ struct cmsghdr * cmsg;
+ int ret;
+
+ vector.iov_base = "PTY";
+ vector.iov_len = 3;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &vector;
+ msg.msg_iovlen = 1;
+
+ cmsg = alloca(sizeof(struct cmsghdr) + sizeof(*pty));
+ cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(*pty);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ memcpy(CMSG_DATA(cmsg), pty, sizeof(*pty));
+
+ msg.msg_control = cmsg;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ ret = sendmsg(sock, &msg, 0);
+ if (ret < 0)
+ return -1;
+ return 0;
+}
+
+static int recv_pty(int sock, int *pty, char **path, char *devpts)
+{
+ char buf[50];
+ struct iovec vector;
+ struct msghdr msg;
+ struct cmsghdr * cmsg;
+ int ret;
+
+ vector.iov_base = buf;
+ vector.iov_len = 50;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &vector;
+ msg.msg_iovlen = 1;
+
+ cmsg = alloca(sizeof(struct cmsghdr) + sizeof(*pty));
+ cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(*pty);
+ msg.msg_control = cmsg;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ ret = recvmsg(sock, &msg, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(pty, CMSG_DATA(cmsg), sizeof(*pty));
+
+ if (VIR_ALLOC_N(*path, PATH_MAX) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Failed to allocate space for ptyname"));
+ return -ENOMEM;
+ }
+ //snprintf(*path, PATH_MAX, "%s/0", devpts);
+ snprintf(*path, PATH_MAX, "/dev/pts/0");
+ return 0;
+}
+
+static int private_open_tty_at(char *devpts, char *devptmx,
+ int *containerPty,
+ char **containerPtyPath, int rawmode)
+{
+ int pid;
+ int ret;
+ int status;
+ int s[2];
+
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, s);
+ if (ret < 0)
+ return ret;
+
+ pid = fork();
+ if (pid < 0)
+ exit(pid);
+ if (pid == 0) {
+ close(s[1]);
+ ret = unshare(CLONE_NEWNS);
+ if (ret < 0)
+ exit(ret);
+ ret = mount(devpts, "/dev/pts", "none", MS_BIND, NULL);
+ if (ret < 0)
+ exit(ret);
+ ret = virFileOpenTtyAt(devptmx, containerPty, containerPtyPath, rawmode);
+ if (ret < 0)
+ exit(ret);
+ send_pty(s[0], containerPty);
+ exit(ret);
+ }
+ close(s[0]);
+ ret = recv_pty(s[1], containerPty, containerPtyPath, devpts);
+ close(s[1]);
+ if (ret)
+ return ret;
+ waitpid(pid, &status, 0);
+ return WEXITSTATUS(status);
+}
+
static int
lxcControllerRun(virDomainDefPtr def,
unsigned int nveths,
@@ -894,12 +1001,12 @@ lxcControllerRun(virDomainDefPtr def,
if (devptmx) {
VIR_DEBUG("Opening tty on private %s", devptmx);
- if (virFileOpenTtyAt(devptmx,
- &containerPty,
- &containerPtyPath,
- 0) < 0) {
+ if (private_open_tty_at(devpts, devptmx,
+ &containerPty,
+ &containerPtyPath,
+ 0) < 0) {
virReportSystemError(errno, "%s",
- _("Failed to allocate tty"));
+ _("Failed to allocate tty"));
goto cleanup;
}
} else {
--
1.7.5.4
13 years, 2 months
[libvirt] [PATCH V2 00/10] Make inner workings of nwfilters more flexible + extensions
by Stefan Berger
The following series of patches re-does some of the inner workings
of nwfilters with the goal to enable users to write filters that have other
than the system-known chains supported right now ('root','arp','rarp','ipv4'
and 'ipv6'). Ideally users should be able to provide a chain name in the
chains XML attribute and either be able to jump to it as an 'action' or
have the chain created automatically as it is the case right now for those
chains enumerated before. The latter is now added in this patch series
as well.
I am first introducing internal priorities for the chains mentioned above so
that their creation can be made more flexible -- currently their creation and
the order in which they are accessed is hardcoded. This largely does away
with the hardcoded stuff. All assigned priorities have negative values.
Later on the priorities for the chains are made accessible via an XML
attribute.
Further, filters will be automatically accessed from the (ebtables)
interface 'root' chain using the prefix of the name of the chain. As an
example, the following filter will be accessed from the root chain for 'arp'
packets since its name 'arp-xyz' has the prefix 'arp'.
<filter name='test-arp-xyz' chain='arp-xyz' priority='-650'>
<uuid>94abeecc-c956-0ac8-1f49-a06ee8995688</uuid>
<rule action='accept' direction='out' priority='100'>
<arp opcode='Request_Reverse' arpsrcmacaddr='$MAC' arpdstmacaddr='$MAC'
arpsrcipaddr='0.0.0.0' arpdstipaddr='0.0.0.0'/>
</rule>
<rule action='accept' direction='inout' priority='500'/>
</filter>
In another step the priorities of rules is extended to also allow negativ
values. This then allows the creation of rules and chains in the interface
'root' chain to be mixed so that the following layout becomes possible:
Bridge chain: libvirt-I-vnet0, entries: 6, policy: ACCEPT
-p IPv4 -j I-vnet0-ipv4
-p ARP -j I-vnet0-arp
-p ARP -j ACCEPT
-p 0x8035 -j I-vnet0-rarp
-p 0x835 -j ACCEPT
-j DROP
In the above list of rules the '-p ARP -j ACCEPT' can now be found in
between the 'jumps' to protocol-specific chains, which allows for more
efficient rule evaluation.
I did testing with the test cases in libvirt-tck as well as those in
the tests/ directory and did not see any regressions.
Regards,
Stefan
13 years, 2 months
[libvirt] [PATCH] support setting bandwidth from virsh attach-interface
by Hu Tao
Adds two options, inbound and outbound, to attach-interface to set
bandwidth when attaching interfaces
---
tools/virsh.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
tools/virsh.pod | 5 ++-
2 files changed, 98 insertions(+), 3 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index bcf0603..d6c9450 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -59,6 +59,7 @@
#include "threads.h"
#include "command.h"
#include "virkeycode.h"
+#include "network.h"
static char *progname;
@@ -11225,15 +11226,49 @@ static const vshCmdOptDef opts_attach_interface[] = {
{"script", VSH_OT_DATA, 0, N_("script used to bridge network interface")},
{"model", VSH_OT_DATA, 0, N_("model type")},
{"persistent", VSH_OT_BOOL, 0, N_("persist interface attachment")},
+ {"inbound", VSH_OT_DATA, VSH_OFLAG_NONE, N_("control domain's incoming traffics")},
+ {"outbound", VSH_OT_DATA, VSH_OFLAG_NONE, N_("control domain's outgoing traffics")},
{NULL, 0, 0, NULL}
};
+/* parse inbound and outbound which are in the format of
+ * 'average,peak,burst', in which peak and burst are optional,
+ * thus 'average,,burst' and 'average,peak' are also legal. */
+static int parseRateStr(const char *rateStr, virRatePtr rate)
+{
+ char *average = NULL, *peak = NULL, *burst = NULL;
+
+ average = (char *)rateStr;
+ if (!average)
+ return -1;
+ rate->average = atol(average);
+
+ peak = strchr(average, ',');
+ if (peak) {
+ burst = strchr(peak + 1, ',');
+ if (!(burst && (burst - peak == 1))) {
+ if (virStrToLong_ull(peak + 1, &burst, 10, &rate->peak) < 0)
+ return -1;
+ }
+
+ if (burst) {
+ if (virStrToLong_ull(burst + 1, NULL, 10, &rate->burst) < 0)
+ return -1;
+ }
+ }
+
+
+ return 0;
+}
+
static bool
cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
const char *mac = NULL, *target = NULL, *script = NULL,
- *type = NULL, *source = NULL, *model = NULL;
+ *type = NULL, *source = NULL, *model = NULL,
+ *inboundStr = NULL, *outboundStr = NULL;
+ virRate inbound, outbound;
int typ;
int ret;
bool functionReturn = false;
@@ -11254,7 +11289,9 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
vshCommandOptString(cmd, "target", &target) < 0 ||
vshCommandOptString(cmd, "mac", &mac) < 0 ||
vshCommandOptString(cmd, "script", &script) < 0 ||
- vshCommandOptString(cmd, "model", &model) < 0) {
+ vshCommandOptString(cmd, "model", &model) < 0 ||
+ vshCommandOptString(cmd, "inbound", &inboundStr) < 0 ||
+ vshCommandOptString(cmd, "outbound", &outboundStr) < 0) {
vshError(ctl, "missing argument");
goto cleanup;
}
@@ -11270,6 +11307,29 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
}
+ if (inboundStr) {
+ memset(&inbound, 0, sizeof(inbound));
+ if (parseRateStr(inboundStr, &inbound) < 0) {
+ vshError(ctl, _("inbound format is incorrect"));
+ goto cleanup;
+ }
+ if (inbound.average == 0) {
+ vshError(ctl, _("inbound average is mandatory"));
+ goto cleanup;
+ }
+ }
+ if (outboundStr) {
+ memset(&outbound, 0, sizeof(outbound));
+ if (parseRateStr(outboundStr, &outbound) < 0) {
+ vshError(ctl, _("outbound format is incorrect"));
+ goto cleanup;
+ }
+ if (outbound.average == 0) {
+ vshError(ctl, _("outbound average is mandatory"));
+ goto cleanup;
+ }
+ }
+
/* Make XML of interface */
virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
@@ -11287,6 +11347,38 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
if (model != NULL)
virBufferAsprintf(&buf, " <model type='%s'/>\n", model);
+ if (inboundStr || outboundStr) {
+ virBufferAsprintf(&buf, " <bandwidth>\n");
+ if (inboundStr && inbound.average > 0) {
+ if (inbound.peak > 0 && inbound.burst > 0)
+ virBufferAsprintf(&buf, " <inbound average='%lld' peak='%lld' burst='%lld'/>\n",
+ inbound.average, inbound.peak, inbound.burst);
+ else if (inbound.peak > 0)
+ virBufferAsprintf(&buf, " <inbound average='%lld' peak='%lld'/>\n",
+ inbound.average, inbound.peak);
+ else if (inbound.burst > 0)
+ virBufferAsprintf(&buf, " <inbound average='%lld' burst='%lld'/>\n",
+ inbound.average, inbound.burst);
+ else
+ virBufferAsprintf(&buf, " <inbound average='%lld'/>\n", inbound.average);
+ }
+ if (outboundStr && outbound.average > 0) {
+ if (outbound.peak > 0 && outbound.burst > 0)
+ virBufferAsprintf(&buf, " <outbound average='%lld' peak='%lld' burst='%lld'/>\n",
+ outbound.average, outbound.peak, outbound.burst);
+ else if (outbound.peak > 0)
+ virBufferAsprintf(&buf, " <outbound average='%lld' peak='%lld'/>\n",
+ outbound.average, outbound.peak);
+ else if (outbound.burst > 0)
+ virBufferAsprintf(&buf, " <outbound average='%lld' burst='%lld'/>\n",
+ outbound.average, outbound.burst);
+ else
+ virBufferAsprintf(&buf, " <outbound average='%lld'/>\n", outbound.average);
+
+ }
+ virBufferAsprintf(&buf, " </bandwidth>\n");
+ }
+
virBufferAddLit(&buf, "</interface>\n");
if (virBufferError(&buf)) {
diff --git a/tools/virsh.pod b/tools/virsh.pod
index d0b7937..06dc06a 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1235,7 +1235,7 @@ scsi:controller.bus.unit or ide:controller.bus.unit.
=item B<attach-interface> I<domain-id> I<type> I<source>
[I<--target target>] [I<--mac mac>] [I<--script script>] [I<--model model>]
-[I<--persistent>]
+[I<--persistent>] [I<--inbound average,peak,burst>] [I<--outbound average,peak,burst>]
Attach a new network interface to the domain.
I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
@@ -1246,6 +1246,9 @@ I<script> allows to specify a path to a script handling a bridge instead of
the default one.
I<model> allows to specify the model type.
I<persistent> indicates the changes will affect the next boot of the domain.
+I<inbound> and I<outbound> control the bandwidth of the interface. I<peak>
+and I<burst> are optional, so "average,peak", "average,,burst" and
+"average" are also legal.
B<Note>: the optional target value is the name of a device to be created
as the back-end on the node. If not provided a device named "vnetN" or "vifN"
--
1.7.3.1
13 years, 2 months
[libvirt] Plan for the next release
by Daniel Veillard
Hello,
I think it's time to plan for the next release, it may be a bit late to
target the end of the month but I would think entering freeze around
Friday 28 allowing for a release of 0.9.7 around Nov 4th should give
people enough time to get reviews and push feeatures in,
so unless there is an objection, let's plan to enter feature freeze
at the end of next week !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
13 years, 2 months
[libvirt] [PATCH] pci address conflict when virtio disk with drive type address
by Xu He Jie
When using the xml as below:
-------------------------------
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/soulxu/VM/images/linux.img'/>
<target dev='hda' bus='virtio'/>
<address type='drive' controller='0' bus='0' unit='0'/>
</disk>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes'/>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
-----------------------------
Then can't statup qemu, the error message as below:
qemu-system-x86_64: -device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0: Device 'virtio-balloon-pci' could not be initialized
Adding check for bus type and address type. Only the address of pci type support by virtio bus.
Signed-off-by: Xu He Jie <xuhj(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5959593..b8aa1a2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2644,6 +2644,14 @@ virDomainDiskDefParseXML(virCapsPtr caps,
} else {
if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
goto error;
+
+ if ((def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) &&
+ (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
+ (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virtio only support device address type 'PCI' "));
+ goto error;
+ }
}
def->src = source;
--
1.7.5.4
13 years, 2 months
[libvirt] [PATCH] compile: fix undefined reference to gnutls_x509_crt_get_dn with gcc-4.6.1
by Xu He Jie
From: soulxu <soulxu(a)soulxu-ThinkPad-T410.(none)>
When I compile libvirt with gcc-4.6.1 in ubuntu 11.10, got error as below:
CCLD libvirtd
/usr/bin/ld: ../src/.libs/libvirt_driver_qemu.a(libvirt_driver_qemu_la-qemu_migration.o): undefined reference to symbol 'gnutls_x509_crt_get_dn@@GNUTLS_1_4'
/usr/bin/ld: note: 'gnutls_x509_crt_get_dn@@GNUTLS_1_4' is defined in DSO /usr/lib/x86_64-linux-gnu/libgnutls.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libgnutls.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[3]: *** [libvirtd] Error 1
It can compile with gcc-4.5.2 in ubuntu 11.04, but it can not compile with gcc-4.6.1 in ubuntu 11.10.
I didn't find reason. Does Anyone know the reason or the different between gcc-4.5.2 and gcc-4.6.1?
I still provide a patch for this. Just make it is working now.
Signed-off-by: soulxu <soulxu(a)soulxu-ThinkPad-T410.(none)>
---
src/Makefile.am | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 87d91ed..104efc6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -776,10 +776,14 @@ noinst_LTLIBRARIES += libvirt_driver_qemu.la
#libvirt_la_BUILT_LIBADD += libvirt_driver_qemu.la
endif
libvirt_driver_qemu_la_CFLAGS = $(NUMACTL_CFLAGS) \
+ $(GNUTLS_CFLAGS) \
+ $(LIBXML_CFLAGS) \
-I@top_srcdir@/src/conf $(AM_CFLAGS)
libvirt_driver_qemu_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_qemu_la_LIBADD = $(NUMACTL_LIBS) \
- $(CAPNG_LIBS)
+ $(CAPNG_LIBS) \
+ $(GNUTLS_LIBS) \
+ $(LIBXML_LIBS)
if WITH_DRIVER_MODULES
libvirt_driver_qemu_la_LIBADD += ../gnulib/lib/libgnu.la
libvirt_driver_qemu_la_LDFLAGS += -module -avoid-version
--
1.7.5.4
13 years, 2 months
[libvirt] [PATCH] build: ignore test executable
by Eric Blake
* .gitignore: Add exemption.
---
Pushing under the trivial rule (I almost did a 'git add' of the
test binary).
.gitignore | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index 41fa50f..b04db58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@
/tests/networkxml2argvtest
/tests/nwfilterxml2xmltest
/tests/openvzutilstest
+/tests/qemuxmlnstest
/tests/shunloadtest
/update.log
Makefile
--
1.7.4.4
13 years, 2 months
[libvirt] qemu-namespace handling?
by Philipp Hahn
Hello,
some time ago I hand to manipulate the domain XML description using Pythons
Elemtree XML implementation, which had problems generating the right format
for libvirt: elemtree just supports adding Qname elements (that
is "{http://libvirt.org/schemas/domain/qemu/1.0}commandline") which
internally would create a temporary binding of this namespace to the "ns0"
Prefix.
My work-around for Elemtree was the add the name-space mapping for "qemu"
to "http://libvirt.org/schemas/domain/qemu/1.0" to ETs internal mapping table
and add an "xmlns:qemu" attribute by hand:
ET._namespace_map[QEMU_URI] = 'qemu'
domain.attrib['xmlns:qemu'] = QEMU_URI
libvirt on the other hand expects the prefix to be "qemu" and only checks,
that this prefix is bound to the URI mentioned above at the root node).
The following examples would be XML valid, but are not accepted by libvirt:
<domain>...
<qemu:commandline xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
...</qemu:commandline>
</domain>
<domain xmlns:ns0="http://libvirt.org/schemas/domain/qemu/1.0">...
<ns0:commandline>
...</ns0:commandline>
</domain>
The following (esoteric) example might be wrongly accepted by libvirt
(untested):
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
<qemu:commandline xmlns:qemu="urn:foo">
...</qemu:commandline>
</domain>
I don't know if this is worth fixing, but I still encountered the first two
problems myself and had to spend some time to detecting what I did wrong. So
at least I want to share my finding with others, so they don't do the same
mistake.
Sincerely
Philipp Hahn
--
Philipp Hahn Open Source Software Engineer hahn(a)univention.de
Univention GmbH Linux for Your Business fon: +49 421 22 232- 0
Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99
http://www.univention.de/
13 years, 2 months