Since the APIs support just one element per namespace and while modifying an element all duplicates would be removed, let's do this right away in the post parse callback. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1190590 --- src/conf/domain_conf.c | 42 ++++++++++++++++++++++ .../qemuxml2argv-metadata-duplicate.xml | 34 ++++++++++++++++++ .../qemuxml2xmlout-metadata-duplicate.xml | 31 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 4 files changed, 108 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-metadata-duplicate.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-metadata-duplicate.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6da02b0..5467bef 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3148,6 +3148,45 @@ virDomainDefRejectDuplicateControllers(virDomainDefPtr def) } +/** + * virDomainDefRemoveDuplicateMetadata: + * @def: Remove duplicate metadata for this def + * + * This function removes metadata elements in @def that share the namespace. + * The first metadata entry of every duplicate namespace is kept. + */ +static void +virDomainDefRemoveDuplicateMetadata(virDomainDefPtr def) +{ + xmlNodePtr child; + xmlNodePtr next; + + if (!def || !def->metadata) + return; + + for (child = def->metadata->children; child; child = child->next) { + /* check that every other child of @root doesn't share the namespace of + * the current one and delete them possibly */ + next = child->next; + while (next) { + xmlNodePtr dupl = NULL; + + if (child->ns && next->ns && + STREQ_NULLABLE((const char *) child->ns->href, + (const char *) next->ns->href)) + dupl = next; + + next = next->next; + + if (dupl) { + xmlUnlinkNode(dupl); + xmlFreeNode(dupl); + } + } + } +} + + static int virDomainDefPostParseInternal(virDomainDefPtr def, virCapsPtr caps ATTRIBUTE_UNUSED) @@ -3316,6 +3355,9 @@ virDomainDefPostParseInternal(virDomainDefPtr def, } } + /* clean up possibly duplicated metadata entries */ + virDomainDefRemoveDuplicateMetadata(def); + return 0; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-metadata-duplicate.xml b/tests/qemuxml2argvdata/qemuxml2argv-metadata-duplicate.xml new file mode 100644 index 0000000..13fb449 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-metadata-duplicate.xml @@ -0,0 +1,34 @@ +<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'/> + <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> + <!-- intentional mis-indentation --> + <metadata> + <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo> + <app3:foo xmlns:app3="http://foo.org/">fooish</app3:foo> + <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo> + <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar> + <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo> + <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar> + </metadata> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-metadata-duplicate.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-metadata-duplicate.xml new file mode 100644 index 0000000..e32fb67 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-metadata-duplicate.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <metadata> + <app1:foo xmlns:app1="http://foo.org/">fooish</app1:foo> + <app2:bar xmlns:app2="http://bar.com/" maman="baz">barish</app2:bar> + </metadata> + <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'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 58917c3..2bec2b2 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -367,6 +367,7 @@ mymain(void) DO_TEST_DIFFERENT("usb-ich9-ehci-addr"); DO_TEST_DIFFERENT("metadata"); + DO_TEST_DIFFERENT("metadata-duplicate"); DO_TEST("tpm-passthrough"); DO_TEST("pci-bridge"); -- 2.2.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list