On 5/11/21 12:16 PM, Kristina Hanicova wrote: > Signed-off-by: Kristina Hanicova <khanicov@xxxxxxxxxx> > --- > docs/formatdomain.rst | 37 ++++++++----- > docs/schemas/domaincommon.rng | 20 +++++++ > src/conf/domain_audit.c | 1 + > src/conf/domain_conf.c | 66 ++++++++++++++++++++---- > src/conf/domain_conf.h | 12 +++++ > src/conf/domain_validate.c | 8 +++ > src/libvirt_private.syms | 2 + > src/qemu/qemu_cgroup.c | 2 + > src/qemu/qemu_command.c | 1 + > src/qemu/qemu_domain_address.c | 1 + > src/qemu/qemu_hotplug.c | 1 + > src/qemu/qemu_validate.c | 6 +++ > src/security/security_apparmor.c | 1 + > src/security/security_dac.c | 2 + > src/security/security_selinux.c | 2 + > src/security/virt-aa-helper.c | 3 +- > tests/qemuxml2argvdata/input-linux.xml | 24 +++++++++ > tests/qemuxml2xmloutdata/input-linux.xml | 1 + > 18 files changed, 167 insertions(+), 23 deletions(-) > create mode 100644 tests/qemuxml2argvdata/input-linux.xml > create mode 120000 tests/qemuxml2xmloutdata/input-linux.xml > > index e8632e4d73..299b600e24 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -12021,12 +12032,36 @@ virDomainInputDefParseXML(virDomainXMLOption *xmlopt, > goto error; > } > > - if ((evdev = virXPathString("string(./source/@evdev)", ctxt))) > - def->source.evdev = virFileSanitizePath(evdev); > - if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH && !def->source.evdev) { > - virReportError(VIR_ERR_XML_ERROR, "%s", > - _("Missing evdev path for input device passthrough")); > - goto error; > + if ((source = virXPathNode("./source", ctxt))) { > + g_autofree char *evdev = NULL; > + > + if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH) > + evdev = virXMLPropString(source, "evdev"); > + else if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) > + evdev = virXMLPropString(source, "dev"); So here you parse <source dev=... /> > + > + if (evdev) > + def->source.evdev = virFileSanitizePath(evdev); > + > + if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH || > + def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) { > + if (!def->source.evdev) { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("Missing evdev path for input device")); > + goto error; > + } > + } > + > + if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) { > + if (virXMLPropEnum(source, "grab", > + virDomainInputSourceGrabTypeFromString, > + VIR_XML_PROP_NONZERO, &def->source.grab) < 0) > + goto error; > + > + if (virXMLPropTristateSwitch(source, "repeat", > + VIR_XML_PROP_NONE, &def->source.repeat) < 0) > + goto error; > + } > } > > if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt), > @@ -26076,9 +26111,12 @@ virDomainInputDefFormat(virBuffer *buf, > { > const char *type = virDomainInputTypeToString(def->type); > const char *bus = virDomainInputBusTypeToString(def->bus); > + const char *grab = virDomainInputSourceGrabTypeToString(def->source.grab); > + const char *repeat = virTristateSwitchTypeToString(def->source.repeat); > g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; > g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); > g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; > + g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER; > > /* don't format keyboard into migratable XML for backward compatibility */ > if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE && > @@ -26098,7 +26136,9 @@ virDomainInputDefFormat(virBuffer *buf, > return -1; > } > > - virBufferAsprintf(&attrBuf, " type='%s' bus='%s'", type, bus); > + virBufferAsprintf(&attrBuf, " type='%s'", type); > + if (def->bus != VIR_DOMAIN_INPUT_BUS_NONE) > + virBufferAsprintf(&attrBuf, " bus='%s'", bus); > > if (def->model) { > const char *model = virDomainInputModelTypeToString(def->model); > @@ -26116,7 +26156,15 @@ virDomainInputDefFormat(virBuffer *buf, > > virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL); > > - virBufferEscapeString(&childBuf, "<source evdev='%s'/>\n", def->source.evdev); > + virBufferEscapeString(&sourceAttrBuf, " evdev='%s'", def->source.evdev); But here you format <source evdev=... />. What you can do is to format dev=... here if def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV, and format evdev=... otherwise. Alternatively, you can stick with 'evdev' name even for _TYPE_EVDEV (will require slightly more changes - to docs, RNG, XML, ...). Your call. > + > + if (def->source.grab) > + virBufferAsprintf(&sourceAttrBuf, " grab='%s'", grab); > + if (def->source.repeat) > + virBufferAsprintf(&sourceAttrBuf, " repeat='%s'", repeat); > + > + virXMLFormatElement(&childBuf, "source", &sourceAttrBuf, NULL); > + > virDomainDeviceInfoFormat(&childBuf, &def->info, flags); > > virXMLFormatElement(buf, "input", &attrBuf, &childBuf); Also, you are introducing qemuxml2xml test case file but not modifying qemuxml2xmltest.c itself. Michal