1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-20 06:50:22 +03:00

schema: fix <interleave> errors when validating <domain> subelements

I first noticed a problem when I added a <memoryBacking> element at an
unusual (but still correct) place in the domain XML, and validation
failed. Then I tried adding that element in several different places
and it failed in many, but not all of them.

(NB: from here on, I will use '' for the names of attributes in the
domain XML, <> for elements in the domain XML, and "" for the names of
grammar rule definitions in the RNG file, and "<>" for the names of
elements in the RNG file's own XML. Confused yet? If so, please tell
me a better way - everything I know about RNG I've picked up
informally by looking at examples in already existing RNG files)

Starting from the top level of the grammar for <domain>
("domaincontents" in domaincommon.rng), I noticed that

1) the "<attribute>" for the 'id' attribute of <domain> is defined
   inside an "<interleave>" down in the definition of "ids" (which is
   referenced from "domaincontents") (I'm not familiar with the
   nomenclature - does that make it a "sub-grammer", "child-grammar",
   ???)

2) although the definition of "ids", had all of its
   "<attribute>"s/"<element>"s inside an "<interleave>",
   "domaincontents" already had the reference to "ids" inside an
   "<interleave>", so there were nested "<interleave>"s.

It's not clear to me how an "<attribute>" or "<interleave>" inside
another "<interleave>" is supposed to behave, but they both seemed a
bit suspicious.

I tried all of the below modifications:

1) moving the grammar for the 'id' attribute out of the "<interleave>"
   but still inside "ids"

2) moving the grammer for the 'id' attribute directly into
   "domaincontents" (and outside of its "interleave"

3) removing the "<interleave>" that was inside "ids"

4) (2) + (3)

5) move the entire grammar rule "ids" up directly in place of <ref
   name="ids"> in "domaincontents".

6) (5), but with the grammar for the 'id' attribute moved outside of
   the "<interleave>"

(6) was the only change that allowed all of the following (using
modifications to the subelements of <domain> in
net-vhostuser-passt.xml as example):

a) a <memoryBacking> element in between *any* two existing elements

b) moving <name> in between any two elements

c) oddly, in addition to the problem with putting <memoryBacking> in
   odd places, I also found that the original RNG did not allow the
   <clock> element to be placed in between <on_poweroff> and
   <on_reboot>, but once I'd made the change in (6), this was no
   longer problematic. Why should this have any effect? No idea, but
   it works :-/

(NB: there are many other cases of referencing "sub-grammar" from
inside an "<interleave>", and they all seem to work just fine;
possibly in this case it was problematic because the sub-grammar a)
also contained an "<interleave>", b) had an "<attribute>" at its
toplevel, or c) had multiple "<element>"s.)

(inexplicably (to me) at one point during my experimentation, I tried
reordering the references to "clock", "resources", "features", and
"events", and that *also* made it legal to put a <clock> element in
between the <on_*> elements:-O)

Since I was no longer able to reproduce the error described in (c)
once I had made mod (6) (move all of "ids" directly into
"domaincontent", I decided it was pointless for me to spend any more
time randomly poking and just add that to the new test case for that
in case some other random change to the RNG causes it to start failing
again.

(I thought of writing a test program that would try all possible
orderings of the subelements of <domain>, but since doing that for
even 10 subelements would mean testing > 3.2 million different XML
documents, I decided we could continue in this adhoc manner, just
adding a single new test case if/when a new validation failure is
found.)

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Laine Stump 2025-02-20 20:13:06 -05:00
parent 6f70da39c1
commit be5332c81d
5 changed files with 187 additions and 32 deletions

View File

@ -32,8 +32,28 @@
<define name="domaincontents">
<ref name="hvs"/>
<optional>
<attribute name="id">
<ref name="unsignedInt"/>
</attribute>
</optional>
<interleave>
<ref name="ids"/>
<element name="name">
<ref name="objectNameWithSlash"/>
</element>
<optional>
<element name="uuid">
<ref name="UUID"/>
</element>
</optional>
<optional>
<element name="genid">
<choice>
<ref name="UUID"/>
<empty/>
</choice>
</element>
</optional>
<optional>
<ref name="title"/>
</optional>
@ -679,37 +699,6 @@
</element>
</define>
<!--
The Identifiers can be:
- an optional id attribute with a number on the domain element
- a mandatory name
- an optional uuid
-->
<define name="ids">
<optional>
<attribute name="id">
<ref name="unsignedInt"/>
</attribute>
</optional>
<interleave>
<element name="name">
<ref name="objectNameWithSlash"/>
</element>
<optional>
<element name="uuid">
<ref name="UUID"/>
</element>
</optional>
<optional>
<element name="genid">
<choice>
<ref name="UUID"/>
<empty/>
</choice>
</element>
</optional>
</interleave>
</define>
<define name="idmap">
<element name="idmap">
<interleave>

View File

@ -0,0 +1,40 @@
LC_ALL=C \
PATH=/bin \
HOME=/var/lib/libvirt/qemu/domain--1-passtvhostuu \
USER=test \
LOGNAME=test \
XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-passtvhostuu/.local/share \
XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-passtvhostuu/.cache \
XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-passtvhostuu/.config \
/usr/bin/qemu-system-x86_64 \
-name guest=passtvhostuu,debug-threads=on \
-S \
-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-passtvhostuu/master-key.aes"}' \
-machine pc-i440fx-7.2,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \
-accel kvm \
-cpu qemu64 \
-m size=16777216k \
-object '{"qom-type":"memory-backend-file","id":"pc.ram","mem-path":"/var/lib/libvirt/qemu/ram/-1-passtvhostuu/pc.ram","share":true,"x-use-canonical-path-for-ramblock-id":false,"size":17179869184}' \
-overcommit mem-lock=off \
-smp 16,sockets=16,cores=1,threads=1 \
-uuid d79698e0-46b2-4459-87ee-7c762990dd6e \
-display none \
-no-user-config \
-nodefaults \
-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
-mon chardev=charmonitor,id=monitor,mode=control \
-rtc base=utc \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-blockdev '{"driver":"file","filename":"/home/laine/libvirt/images/fedora-34.img","node-name":"libvirt-1-storage","read-only":false}' \
-device '{"driver":"virtio-blk-pci","bus":"pci.0","multifunction":true,"addr":"0x3","drive":"libvirt-1-storage","id":"virtio-disk0","bootindex":1}' \
-chardev socket,id=charnet0,path=/var/run/libvirt/qemu/passt/-1-passtvhostuu-net0.socket \
-netdev '{"type":"vhost-user","chardev":"charnet0","id":"hostnet0"}' \
-device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:21:de:6c","bus":"pci.0","addr":"0x2"}' \
-chardev pty,id=charserial0 \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
-msg timestamp=on

View File

@ -0,0 +1,62 @@
<domain type='kvm'>
<name>passtvhostuu</name>
<uuid>d79698e0-46b2-4459-87ee-7c762990dd6e</uuid>
<memory unit='KiB'>16777216</memory>
<currentMemory unit='KiB'>16777216</currentMemory>
<memoryBacking>
<access mode='shared'/>
</memoryBacking>
<vcpu placement='static'>16</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-7.2'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='custom' match='exact' check='none'>
<model fallback='forbid'>qemu64</model>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/laine/libvirt/images/fedora-34.img'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' multifunction='on'/>
</disk>
<controller type='pci' index='0' model='pci-root'/>
<controller type='usb' index='0' model='piix3-uhci'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<interface type='vhostuser'>
<mac address='52:54:00:21:de:6c'/>
<ip address='10.30.0.5' family='ipv4' prefix='24'/>
<model type='virtio'/>
<backend type='passt'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<audio id='1' type='none'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -0,0 +1,62 @@
<domain type='kvm'>
<uuid>d79698e0-46b2-4459-87ee-7c762990dd6e</uuid>
<memoryBacking>
<access mode='shared'/>
</memoryBacking>
<name>passtvhostuu</name>
<memory unit='KiB'>16777216</memory>
<currentMemory unit='KiB'>16777216</currentMemory>
<vcpu placement='static'>16</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-7.2'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='custom' match='exact' check='none'>
<model fallback='forbid'>qemu64</model>
</cpu>
<on_poweroff>destroy</on_poweroff>
<clock offset='utc'/>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/laine/libvirt/images/fedora-34.img'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' multifunction='on'/>
</disk>
<controller type='pci' index='0' model='pci-root'/>
<controller type='usb' index='0' model='piix3-uhci'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<interface type='vhostuser'>
<mac address='52:54:00:21:de:6c'/>
<ip address='10.30.0.5' family='ipv4' prefix='24'/>
<model type='virtio'/>
<backend type='passt'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<audio id='1' type='none'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
</domain>

View File

@ -3029,6 +3029,8 @@ mymain(void)
DO_TEST_CAPS_LATEST_PARSE_ERROR("hostdev-scsi-vhost-sgio-invalid");
DO_TEST_CAPS_LATEST("disk-startuppolicy-optional-drop");
DO_TEST_CAPS_LATEST("schema-reorder-domain-subelements");
/* check that all input files were actually used here */
if (testConfXMLCheck(existingTestCases) < 0)
ret = -1;