[libvirt PATCH v4 00/11] Add QEMU "-display dbus" support

From: Marc-André Lureau <marcandre.lureau@redhat.com> Hi, This series implements supports for the QEMU "-display dbus" support, available since 7.0. By default, libvirt will start a private VM bus (sharing and reusing the existing "vmstate" VM bus & code). The feature set should cover the needs to replace Spice as local client of choice, including 3daccel/dmabuf, audio, clipboard sharing, usb redirection, and arbitrary chardev/channels (for serial etc). The test Gtk4 client is also in progress, currently in development at https://gitlab.com/marcandre.lureau/qemu-display/. virt-viewer & boxes will need a port to Gtk4 to make use of the shared widget. thanks v4: - rebased, dropped some patches, updated versions in docs, code adjustments etc - dropped clipboard option, as standalone qemu-vdagent support landed v3: after QEMU 7.0 dev cycle opening and merge - rebased - add 7.0 x86-64 capabilities (instead of tweaking 6.2) - fix version annotations Marc-André Lureau (11): qemu: add -display dbus capability check conf: add <graphics type='dbus'> qemu: start the D-Bus daemon for the display qemu: add -display dbus support virsh: report the D-Bus bus URI for domdisplay conf: add <audio type='dbus'> support qemu: add audio type 'dbus' conf: add <serial type='dbus'> qemu: add -chardev dbus support qemu: add usbredir type 'dbus' docs: document <graphics> type dbus NEWS.rst | 5 + docs/formatdomain.rst | 43 +++++- src/bhyve/bhyve_command.c | 1 + src/conf/domain_conf.c | 129 +++++++++++++++++- src/conf/domain_conf.h | 14 ++ src/conf/domain_validate.c | 41 ++++-- src/conf/schemas/basictypes.rng | 7 + src/conf/schemas/domaincommon.rng | 63 +++++++++ src/libxl/libxl_conf.c | 1 + src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 1 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 65 ++++++++- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 10 +- src/qemu/qemu_extdevice.c | 13 ++ src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_monitor_json.c | 10 ++ src/qemu/qemu_process.c | 41 +++++- src/qemu/qemu_validate.c | 33 +++++ src/security/security_dac.c | 2 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../caps_7.0.0.x86_64.xml | 1 + .../caps_7.1.0.x86_64.xml | 1 + .../graphics-dbus-address.args | 30 ++++ .../graphics-dbus-address.xml | 35 +++++ .../qemuxml2argvdata/graphics-dbus-audio.args | 33 +++++ .../qemuxml2argvdata/graphics-dbus-audio.xml | 45 ++++++ .../graphics-dbus-chardev.args | 32 +++++ .../graphics-dbus-chardev.xml | 43 ++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 30 ++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 33 +++++ .../graphics-dbus-usbredir.args | 34 +++++ .../graphics-dbus-usbredir.xml | 30 ++++ tests/qemuxml2argvdata/graphics-dbus.args | 30 ++++ tests/qemuxml2argvdata/graphics-dbus.xml | 33 +++++ tests/qemuxml2argvtest.c | 17 +++ .../graphics-dbus-address.xml | 1 + .../graphics-dbus-audio.xml | 1 + .../graphics-dbus-chardev.xml | 1 + .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 1 + tests/qemuxml2xmloutdata/graphics-dbus.xml | 1 + tests/qemuxml2xmltest.c | 17 +++ tests/testutilsqemu.c | 1 + tools/virsh-domain.c | 24 +++- 52 files changed, 948 insertions(+), 20 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-address.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus-usbredir.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-usbredir.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-audio.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-chardev.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus.xml -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml | 1 + 4 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a59d839d85..5134f44aa2 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -675,6 +675,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 430 */ "chardev.qemu-vdagent", /* QEMU_CAPS_CHARDEV_QEMU_VDAGENT */ + "display-dbus", /* QEMU_CAPS_DISPLAY_DBUS */ ); @@ -1625,6 +1626,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, { "calc-dirty-rate/arg-type/mode", QEMU_CAPS_DIRTYRATE_MODE }, { "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_QEMU_VDAGENT }, + { "query-display-options/ret-type/+dbus", QEMU_CAPS_DISPLAY_DBUS }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 59c09903f3..26cd655db3 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -650,6 +650,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 430 */ QEMU_CAPS_CHARDEV_QEMU_VDAGENT, /* -chardev qemu-vdagent */ + QEMU_CAPS_DISPLAY_DBUS, /* -display dbus */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 7523b92e6b..05f844fd5b 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -242,6 +242,7 @@ <flag name='virtio-iommu.boot-bypass'/> <flag name='virtio-net.rss'/> <flag name='chardev.qemu-vdagent'/> + <flag name='display-dbus'/> <version>7000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml index f598950cc3..bdc613a54a 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.1.0.x86_64.xml @@ -242,6 +242,7 @@ <flag name='virtio-iommu.boot-bypass'/> <flag name='virtio-net.rss'/> <flag name='chardev.qemu-vdagent'/> + <flag name='display-dbus'/> <version>7000050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/conf/domain_conf.c | 78 ++++++++++++++++++- src/conf/domain_conf.h | 8 ++ src/conf/domain_validate.c | 9 ++- src/conf/schemas/basictypes.rng | 7 ++ src/conf/schemas/domaincommon.rng | 33 ++++++++ src/libxl/libxl_conf.c | 1 + src/libxl/libxl_domain.c | 1 + src/libxl/libxl_driver.c | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_command.c | 2 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 6 +- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_process.c | 4 + src/qemu/qemu_validate.c | 1 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 1 + .../graphics-dbus-address.xml | 35 +++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 33 ++++++++ tests/qemuxml2argvdata/graphics-dbus.xml | 33 ++++++++ .../graphics-dbus-address.xml | 1 + .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 1 + tests/qemuxml2xmloutdata/graphics-dbus.xml | 1 + tests/qemuxml2xmltest.c | 10 +++ 29 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d9b55c80aa..eb56974fbe 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -926,6 +926,7 @@ VIR_ENUM_IMPL(virDomainGraphics, "desktop", "spice", "egl-headless", + "dbus", ); VIR_ENUM_IMPL(virDomainGraphicsListen, @@ -1919,6 +1920,11 @@ void virDomainGraphicsDefFree(virDomainGraphicsDef *def) g_free(def->data.egl_headless.rendernode); break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + g_free(def->data.dbus.address); + g_free(def->data.dbus.rendernode); + break; + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -12773,6 +12779,39 @@ virDomainGraphicsDefParseXMLEGLHeadless(virDomainGraphicsDef *def, } +static int +virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def, + xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + VIR_XPATH_NODE_AUTORESTORE(ctxt) + xmlNodePtr cur; + virTristateBool p2p; + + if (virXMLPropTristateBool(node, "p2p", VIR_XML_PROP_NONE, + &p2p) < 0) + return -1; + def->data.dbus.p2p = p2p == VIR_TRISTATE_BOOL_YES; + + def->data.dbus.address = virXMLPropString(node, "address"); + def->data.dbus.fromConfig = def->data.dbus.address != NULL; + + ctxt->node = node; + + if ((cur = virXPathNode("./gl", ctxt))) { + def->data.dbus.rendernode = virXMLPropString(cur, + "rendernode"); + + if (virXMLPropTristateBool(cur, "enable", + VIR_XML_PROP_REQUIRED, + &def->data.dbus.gl) < 0) + return -1; + } + + return 0; +} + + virDomainGraphicsDef * virDomainGraphicsDefNew(virDomainXMLOption *xmlopt) { @@ -12845,6 +12884,10 @@ virDomainGraphicsDefParseXML(virDomainXMLOption *xmlopt, case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: virDomainGraphicsDefParseXMLEGLHeadless(def, node, ctxt); break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (virDomainGraphicsDefParseXMLDBus(def, node, ctxt) < 0) + goto error; + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -26594,6 +26637,27 @@ virDomainGraphicsDefFormat(virBuffer *buf, def->data.egl_headless.rendernode); virBufferAddLit(buf, "/>\n"); break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (def->data.dbus.p2p) + virBufferAddLit(buf, " p2p='yes'"); + if (def->data.dbus.address) + virBufferAsprintf(buf, " address='%s'", + def->data.dbus.address); + + if (!def->data.dbus.gl) + break; + + if (!children) { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + children = true; + } + + virBufferAsprintf(buf, "<gl enable='%s'", + virTristateBoolTypeToString(def->data.dbus.gl)); + virBufferEscapeString(buf, " rendernode='%s'", def->data.dbus.rendernode); + virBufferAddLit(buf, "/>\n"); + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -31320,6 +31384,11 @@ virDomainGraphicsDefHasOpenGL(const virDomainDef *def) case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: return true; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (graphics->data.dbus.gl == VIR_TRISTATE_BOOL_YES) + return true; + + continue; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -31335,7 +31404,8 @@ virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics) bool ret = false; if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE || - graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) + graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS || + graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS) ret = true; return ret; @@ -31354,6 +31424,9 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics) case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ret = graphics->data.egl_headless.rendernode; break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + ret = graphics->data.dbus.rendernode; + break; case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_VNC: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: @@ -31375,6 +31448,9 @@ virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics) if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE && graphics->data.spice.gl != VIR_TRISTATE_BOOL_YES) return false; + if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS && + graphics->data.dbus.gl != VIR_TRISTATE_BOOL_YES) + return false; if (virDomainGraphicsGetRenderNode(graphics)) return false; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2e2da0c69c..025ed55169 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1777,6 +1777,7 @@ typedef enum { VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP, VIR_DOMAIN_GRAPHICS_TYPE_SPICE, VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS, + VIR_DOMAIN_GRAPHICS_TYPE_DBUS, VIR_DOMAIN_GRAPHICS_TYPE_LAST } virDomainGraphicsType; @@ -1953,6 +1954,13 @@ struct _virDomainGraphicsDef { struct { char *rendernode; } egl_headless; + struct { + bool p2p; + char *address; + char *rendernode; + virTristateBool gl; + bool fromConfig; /* true if the @address is config file originated */ + } dbus; } data; /* nListens, listens, and *port are only useful if type is vnc, * rdp, or spice. They've been extracted from the union only to diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 18eb8d697d..ba474ee8c0 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2424,8 +2424,15 @@ virDomainGraphicsDefValidate(const virDomainDef *def, return -1; } - if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) + if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { return virDomainEnsureAudioID(def, graphics->data.vnc.audioId); + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS) { + if (graphics->data.dbus.p2p && graphics->data.dbus.address) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("D-Bus p2p with an address is not supported")); + return -1; + } + } return 0; } diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng index a221ff6295..ae4d568222 100644 --- a/src/conf/schemas/basictypes.rng +++ b/src/conf/schemas/basictypes.rng @@ -220,6 +220,13 @@ </define> <!--======================================================================--> + <!-- A D-Bus server address: https://dbus.freedesktop.org/doc/dbus-specification.html#addresses --> + <define name="dbusAddr"> + <data type="string"> + <param name="pattern">.+</param> + </data> + </define> + <!-- An ipv4 "dotted quad" address --> <define name="ipv4Addr"> <data type="string"> diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 2544864eb4..14b5955cad 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -4037,6 +4037,39 @@ </optional> </interleave> </group> + <group> + <attribute name="type"> + <value>dbus</value> + </attribute> + <optional> + <choice> + <group> + <attribute name="address"> + <ref name="dbusAddr"/> + </attribute> + </group> + <group> + <attribute name="p2p"> + <ref name="virYesNo"/> + </attribute> + </group> + </choice> + </optional> + <interleave> + <optional> + <element name="gl"> + <attribute name="enable"> + <ref name="virYesNo"/> + </attribute> + <optional> + <attribute name="rendernode"> + <ref name="absFilePath"/> + </attribute> + </optional> + </element> + </optional> + </interleave> + </group> <group> <attribute name="type"> <value>rdp</value> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index e5fe209718..f0f7dfaa07 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1537,6 +1537,7 @@ libxlMakeVfb(virPortAllocatorRange *graphicsports, case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index dbe44f4ffc..af938192a9 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -957,6 +957,7 @@ libxlDomainCleanup(libxlDriverPrivate *driver, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 9ffa20161d..d4ae875854 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -465,6 +465,7 @@ libxlReconnectDomain(virDomainObj *vm, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5134f44aa2..ce3e7d275a 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6226,6 +6226,8 @@ virQEMUCapsFillDomainDeviceGraphicsCaps(virQEMUCaps *qemuCaps, VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_SPICE); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS)) VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS); + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISPLAY_DBUS)) + VIR_DOMAIN_CAPS_ENUM_SET(dev->type, VIR_DOMAIN_GRAPHICS_TYPE_DBUS); } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8eac8edd79..7a9ea6ae41 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8620,6 +8620,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, graphics) < 0) return -1; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -10244,6 +10245,7 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++egl_headless; break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4d4be0683a..806de9f4b0 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3676,6 +3676,7 @@ qemuDomainDefSuggestDefaultAudioBackend(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: default: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 702fd0239c..ad6faf503c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15714,12 +15714,13 @@ qemuDomainOpenGraphics(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: protocol = "spice"; break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Can only open VNC or SPICE graphics backends, not %s"), + _("Can only open VNC, SPICE or D-Bus p2p graphics backends, not %s"), virDomainGraphicsTypeToString(vm->def->graphics[idx]->type)); goto endjob; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: @@ -15782,12 +15783,13 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: protocol = "spice"; break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Can only open VNC or SPICE graphics backends, not %s"), + _("Can only open VNC, SPICE or D-Bus p2p graphics backends, not %s"), virDomainGraphicsTypeToString(vm->def->graphics[idx]->type)); goto cleanup; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 274f47c25d..791d4e446a 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4420,6 +4420,7 @@ qemuDomainChangeGraphics(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to change config on '%s' graphics type"), type); break; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fd4db43a42..4924f8ea0b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4708,6 +4708,7 @@ qemuProcessGraphicsReservePorts(virDomainGraphicsDef *graphics, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -4747,6 +4748,7 @@ qemuProcessGraphicsAllocatePorts(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -4903,6 +4905,7 @@ qemuProcessGraphicsSetupListen(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -5195,6 +5198,7 @@ qemuProcessStartValidateGraphics(virDomainObj *vm) case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 6ff61d91fa..5a437562c2 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4254,6 +4254,7 @@ qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics, case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index 8150bbfaa9..c391caa910 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -3435,6 +3435,7 @@ virVMXFormatConfig(virVMXContext *ctx, virDomainXMLOption *xmlopt, virDomainDef case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported graphics type '%s'"), virDomainGraphicsTypeToString(def->graphics[i]->type)); diff --git a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml index 1f56616587..4e6ff06125 100644 --- a/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-q35.x86_64.xml @@ -155,6 +155,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml index 9ed9123f7d..ed80a7892f 100644 --- a/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0-tcg.x86_64.xml @@ -169,6 +169,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml index 71532ad0ed..a20395c6d4 100644 --- a/tests/domaincapsdata/qemu_7.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.x86_64.xml @@ -155,6 +155,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml index b6bb9e3ffe..c1df755463 100644 --- a/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-q35.x86_64.xml @@ -155,6 +155,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml index cd14a10f05..9cb254cac6 100644 --- a/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0-tcg.x86_64.xml @@ -169,6 +169,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml index 58bce4251e..dcadb1c279 100644 --- a/tests/domaincapsdata/qemu_7.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_7.1.0.x86_64.xml @@ -155,6 +155,7 @@ <value>vnc</value> <value>spice</value> <value>egl-headless</value> + <value>dbus</value> </enum> </graphics> <video supported='yes'> diff --git a/tests/qemuxml2argvdata/graphics-dbus-address.xml b/tests/qemuxml2argvdata/graphics-dbus-address.xml new file mode 100644 index 0000000000..1e8526b274 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.xml @@ -0,0 +1,35 @@ +<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'>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-system-i386</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus' address='unix:path=/tmp/foo'> + <gl enable='yes' rendernode='/dev/dri/foo'/> + </graphics> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.xml b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml new file mode 100644 index 0000000000..a99e695471 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml @@ -0,0 +1,33 @@ +<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'>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-system-i386</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus' p2p='yes'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus.xml b/tests/qemuxml2argvdata/graphics-dbus.xml new file mode 100644 index 0000000000..be8442b3cd --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.xml @@ -0,0 +1,33 @@ +<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'>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-system-i386</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-address.xml b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml new file mode 120000 index 0000000000..c2ff4590c1 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/graphics-dbus-address.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml b/tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml new file mode 120000 index 0000000000..8f705412b3 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/graphics-dbus-p2p.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/graphics-dbus.xml b/tests/qemuxml2xmloutdata/graphics-dbus.xml new file mode 120000 index 0000000000..e52af445d9 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/graphics-dbus.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 8b655874d1..6578a80213 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -400,6 +400,16 @@ mymain(void) QEMU_CAPS_VNC, QEMU_CAPS_EGL_HEADLESS); + DO_TEST("graphics-dbus", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-address", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-p2p", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS); + DO_TEST_CAPS_ARCH_LATEST("default-video-type-aarch64", "aarch64"); DO_TEST_CAPS_ARCH_LATEST("default-video-type-ppc64", "ppc64"); DO_TEST_CAPS_ARCH_LATEST("default-video-type-riscv64", "riscv64"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Start the daemon if necessary (it is already stopped in qemuProcessStop) Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_extdevice.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 537b130394..8ada8324be 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -201,6 +201,19 @@ qemuExtDevicesStart(virQEMUDriver *driver, } } + for (i = 0; i < def->ngraphics; i++) { + virDomainGraphicsDef *graphics = def->graphics[i]; + + if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_DBUS) + continue; + + if (graphics->data.dbus.p2p || graphics->data.dbus.fromConfig) + continue; + + if (qemuDBusStart(driver, vm) < 0) + return -1; + } + return 0; } -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> By default, libvirt will start a private bus and tell QEMU to connect to it. Instead, a D-Bus "address" to connect to can be specified, or the p2p mode enabled. D-Bus display works best with GL & a rendernode, which can be specified with <gl> child element. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_command.c | 41 ++++++++++++++++++- src/qemu/qemu_driver.c | 4 ++ src/qemu/qemu_process.c | 36 +++++++++++++++- .../graphics-dbus-address.args | 30 ++++++++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 30 ++++++++++++++ tests/qemuxml2argvdata/graphics-dbus.args | 30 ++++++++++++++ tests/qemuxml2argvtest.c | 7 ++++ 7 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-address.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7a9ea6ae41..5e10f522e5 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8585,6 +8585,36 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED, } +static int +qemuBuildGraphicsDBusCommandLine(virCommand *cmd, + virDomainGraphicsDef *graphics) +{ + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&opt, "dbus"); + + if (graphics->data.dbus.p2p) { + virBufferAddLit(&opt, ",p2p=on"); + } else { + virBufferAddLit(&opt, ",addr="); + virQEMUBuildBufferEscapeComma(&opt, graphics->data.dbus.address); + } + if (graphics->data.dbus.gl != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&opt, ",gl=%s", + virTristateSwitchTypeToString(graphics->data.dbus.gl)); + if (graphics->data.dbus.rendernode) { + virBufferAddLit(&opt, ",rendernode="); + virQEMUBuildBufferEscapeComma(&opt, + graphics->data.dbus.rendernode); + } + + virCommandAddArg(cmd, "-display"); + virCommandAddArgBuffer(cmd, &opt); + + return 0; +} + + static int qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, virCommand *cmd, @@ -8620,7 +8650,11 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, graphics) < 0) return -1; + break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (qemuBuildGraphicsDBusCommandLine(cmd, graphics) < 0) + return -1; + break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -10201,6 +10235,7 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, int vnc = 0; int spice = 0; int egl_headless = 0; + int dbus = 0; if (!driver->privileged) { /* If we have no cgroups then we can have no tunings that @@ -10246,6 +10281,8 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, ++egl_headless; break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + ++dbus; + break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: @@ -10253,10 +10290,10 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, } } - if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1) { + if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1 || dbus > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only 1 graphics device of each type " - "(sdl, vnc, spice, headless) is supported")); + "(sdl, vnc, spice, headless, dbus) is supported")); return -1; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ad6faf503c..f41e9b415e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15715,6 +15715,8 @@ qemuDomainOpenGraphics(virDomainPtr dom, protocol = "spice"; break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + protocol = "@dbus-display"; + break; case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -15784,6 +15786,8 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom, protocol = "spice"; break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + protocol = "@dbus-display"; + break; case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4924f8ea0b..4751f60d74 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4878,6 +4878,22 @@ qemuProcessGraphicsSetupNetworkAddress(virDomainGraphicsListenDef *glisten, } +static int +qemuProcessGraphicsSetupDBus(virQEMUDriver *driver, + virDomainGraphicsDef *graphics, + virDomainObj *vm) +{ + if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_DBUS) + return 0; + + if (!graphics->data.dbus.p2p && !graphics->data.dbus.address) { + graphics->data.dbus.address = qemuDBusGetAddress(driver, vm); + } + + return 0; +} + + static int qemuProcessGraphicsSetupListen(virQEMUDriver *driver, virDomainGraphicsDef *graphics, @@ -4969,16 +4985,29 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef *graphics, return 0; /* Don't bother picking a DRM node if QEMU doesn't support it. */ - if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + switch (graphics->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) return 0; rendernode = &graphics->data.spice.rendernode; - } else { + break; + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) return 0; rendernode = &graphics->data.egl_headless.rendernode; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + rendernode = &graphics->data.dbus.rendernode; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: + case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + virReportEnumRangeError(virDomainGraphicsType, graphics->type); + break; } if (!(*rendernode = virHostGetDRMRenderNode())) @@ -5006,6 +5035,9 @@ qemuProcessSetupGraphics(virQEMUDriver *driver, if (qemuProcessGraphicsSetupListen(driver, graphics, vm) < 0) return -1; + + if (qemuProcessGraphicsSetupDBus(driver, graphics, vm) < 0) + return -1; } if (allocate) { diff --git a/tests/qemuxml2argvdata/graphics-dbus-address.args b/tests/qemuxml2argvdata/graphics-dbus-address.args new file mode 100644 index 0000000000..4ed0b78f56 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.args @@ -0,0 +1,30 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-display dbus,addr=unix:path=/tmp/foo,gl=on,rendernode=/dev/dri/foo \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.args b/tests/qemuxml2argvdata/graphics-dbus-p2p.args new file mode 100644 index 0000000000..209623f80c --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.args @@ -0,0 +1,30 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-display dbus,p2p=on \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus.args b/tests/qemuxml2argvdata/graphics-dbus.args new file mode 100644 index 0000000000..a804ae06ee --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.args @@ -0,0 +1,30 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-display dbus,addr=unix:path=/bad-test-used-env-xdg-runtime-dir/libvirt/qemu/run/dbus/-1-QEMUGuest1-dbus.sock \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 829550fbfe..0d0c75b253 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1538,6 +1538,13 @@ mymain(void) DO_TEST_CAPS_LATEST_PARSE_ERROR("graphics-spice-invalid-egl-headless"); DO_TEST_CAPS_LATEST("graphics-spice-gl-auto-rendernode"); + DO_TEST("graphics-dbus", + QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-address", + QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-p2p", + QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST_NOCAPS("input-usbmouse"); DO_TEST_NOCAPS("input-usbtablet"); DO_TEST_NOCAPS("misc-acpi"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> This implementation reports only Unix bus address using the URI format proposed in https://gitlab.freedesktop.org/dbus/dbus/-/issues/348. We prefer a URI form over the D-Bus address form, since all other display protocols use a URI, allowing to distinguish between protocols and making client implementation simpler. Other transports (for example TCP) are not yet handled. The client is assumed to know what to lookup on the bus (the bus name, path & interface of the VM, eventually matching its UUID) P2P mode doesn't report any available URI. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- tools/virsh-domain.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index ba492e807e..bac4cc0fb6 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -11675,7 +11675,7 @@ static const vshCmdOptDef opts_domdisplay[] = { {.name = "type", .type = VSH_OT_STRING, .help = N_("select particular graphical display " - "(e.g. \"vnc\", \"spice\", \"rdp\")") + "(e.g. \"vnc\", \"spice\", \"rdp\", \"dbus\")") }, {.name = "all", .type = VSH_OT_BOOL, @@ -11684,6 +11684,23 @@ static const vshCmdOptDef opts_domdisplay[] = { {.name = NULL} }; +static char * +virshGetDBusDisplay(vshControl *ctl, xmlXPathContext *ctxt) +{ + g_autofree char *addr = NULL; + const char *xpath = "string(/domain/devices/graphics[@type='dbus']/@address)"; + + addr = virXPathString(xpath, ctxt); + if (!addr) + return false; + + if (STRPREFIX(addr, "unix:path=")) { + return g_strdup_printf("dbus+unix://%s", addr + 10); + } + + vshError(ctl, _("'%s' D-Bus address is not handled"), addr); + return NULL; +} static char * virshGetOneDisplay(vshControl *ctl, @@ -11704,6 +11721,9 @@ virshGetOneDisplay(vshControl *ctl, g_autofree char *sockpath = NULL; g_autofree char *passwd = NULL; + if (STREQ(scheme, "dbus")) + return virshGetDBusDisplay(ctl, ctxt); + /* Attempt to get the port number for the current graphics scheme */ xpathPort = g_strdup_printf(xpath_fmt, scheme, "@port"); @@ -11830,7 +11850,7 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd) g_autoptr(xmlXPathContext) ctxt = NULL; g_autoptr(virshDomain) dom = NULL; bool ret = false; - const char *scheme[] = { "vnc", "spice", "rdp", NULL }; + const char *scheme[] = { "vnc", "spice", "rdp", "dbus", NULL }; const char *type = NULL; int iter = 0; int flags = 0; -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/bhyve/bhyve_command.c | 1 + src/conf/domain_conf.c | 34 +++++++++++--- src/conf/domain_conf.h | 2 + src/conf/schemas/domaincommon.rng | 29 ++++++++++++ src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_validate.c | 3 ++ .../qemuxml2argvdata/graphics-dbus-audio.xml | 45 +++++++++++++++++++ .../graphics-dbus-audio.xml | 1 + tests/qemuxml2xmltest.c | 4 ++ 9 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-audio.xml diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index f0e47ce232..1c0f2e2bfb 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -551,6 +551,7 @@ bhyveBuildSoundArgStr(const virDomainDef *def G_GNUC_UNUSED, case VIR_DOMAIN_AUDIO_TYPE_SDL: case VIR_DOMAIN_AUDIO_TYPE_SPICE: case VIR_DOMAIN_AUDIO_TYPE_FILE: + case VIR_DOMAIN_AUDIO_TYPE_DBUS: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported audio backend '%s'"), virDomainAudioTypeTypeToString(audio->type)); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index eb56974fbe..fbefba6200 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -770,6 +770,7 @@ VIR_ENUM_IMPL(virDomainAudioType, "sdl", "spice", "file", + "dbus", ); VIR_ENUM_IMPL(virDomainAudioSDLDriver, @@ -3073,6 +3074,7 @@ virDomainAudioDefFree(virDomainAudioDef *def) g_free(def->backend.file.path); break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: case VIR_DOMAIN_AUDIO_TYPE_LAST: break; } @@ -12808,6 +12810,14 @@ virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def, return -1; } + cur = virXPathNode("./audio", ctxt); + if (cur) { + if (virXMLPropUInt(cur, "id", 10, + VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, + &def->data.dbus.audioId) < 0) + return -1; + } + return 0; } @@ -13295,6 +13305,9 @@ virDomainAudioDefParseXML(virDomainXMLOption *xmlopt G_GNUC_UNUSED, def->backend.file.path = virXMLPropString(node, "path"); break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: default: virReportEnumRangeError(virDomainAudioType, def->type); @@ -25706,6 +25719,9 @@ virDomainAudioDefFormat(virBuffer *buf, virBufferEscapeString(&attrBuf, " path='%s'", def->backend.file.path); break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: default: virReportEnumRangeError(virDomainAudioType, def->type); @@ -26644,7 +26660,7 @@ virDomainGraphicsDefFormat(virBuffer *buf, virBufferAsprintf(buf, " address='%s'", def->data.dbus.address); - if (!def->data.dbus.gl) + if (!def->data.dbus.gl && def->data.dbus.audioId <= 0) break; if (!children) { @@ -26653,10 +26669,17 @@ virDomainGraphicsDefFormat(virBuffer *buf, children = true; } - virBufferAsprintf(buf, "<gl enable='%s'", - virTristateBoolTypeToString(def->data.dbus.gl)); - virBufferEscapeString(buf, " rendernode='%s'", def->data.dbus.rendernode); - virBufferAddLit(buf, "/>\n"); + if (def->data.dbus.gl) { + virBufferAsprintf(buf, "<gl enable='%s'", + virTristateBoolTypeToString(def->data.dbus.gl)); + virBufferEscapeString(buf, " rendernode='%s'", def->data.dbus.rendernode); + virBufferAddLit(buf, "/>\n"); + } + + if (def->data.dbus.audioId > 0) + virBufferAsprintf(buf, "<audio id='%d'/>\n", + def->data.dbus.audioId); + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; @@ -29977,6 +30000,7 @@ virDomainAudioBackendIsEqual(virDomainAudioDef *this, case VIR_DOMAIN_AUDIO_TYPE_FILE: return STREQ_NULLABLE(this->backend.file.path, that->backend.file.path); + case VIR_DOMAIN_AUDIO_TYPE_DBUS: case VIR_DOMAIN_AUDIO_TYPE_LAST: default: return false; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 025ed55169..db50e552b0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1548,6 +1548,7 @@ typedef enum { VIR_DOMAIN_AUDIO_TYPE_SDL, VIR_DOMAIN_AUDIO_TYPE_SPICE, VIR_DOMAIN_AUDIO_TYPE_FILE, + VIR_DOMAIN_AUDIO_TYPE_DBUS, VIR_DOMAIN_AUDIO_TYPE_LAST } virDomainAudioType; @@ -1959,6 +1960,7 @@ struct _virDomainGraphicsDef { char *address; char *rendernode; virTristateBool gl; + unsigned int audioId; bool fromConfig; /* true if the @address is config file originated */ } dbus; } data; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 14b5955cad..6c210f6e78 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -4068,6 +4068,13 @@ </optional> </element> </optional> + <optional> + <element name="audio"> + <attribute name="id"> + <ref name="uint8"/> + </attribute> + </element> + </optional> </interleave> </group> <group> @@ -4910,6 +4917,11 @@ <ref name="audiocommonchild"/> </define> + <define name="audiodbus"> + <ref name="audiocommonattr"/> + <ref name="audiocommonchild"/> + </define> + <define name="audio"> <element name="audio"> <attribute name="id"> @@ -4938,6 +4950,23 @@ </optional> </interleave> </group> + <group> + <attribute name="type"> + <value>dbus</value> + </attribute> + <interleave> + <optional> + <element name="input"> + <ref name="audiodbus"/> + </element> + </optional> + <optional> + <element name="output"> + <ref name="audiodbus"/> + </element> + </optional> + </interleave> + </group> <group> <attribute name="type"> <value>alsa</value> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5e10f522e5..4ae946ec00 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -147,6 +147,7 @@ qemuAudioDriverTypeToString(virDomainAudioType type) case VIR_DOMAIN_AUDIO_TYPE_OSS: case VIR_DOMAIN_AUDIO_TYPE_SDL: case VIR_DOMAIN_AUDIO_TYPE_SPICE: + case VIR_DOMAIN_AUDIO_TYPE_DBUS: case VIR_DOMAIN_AUDIO_TYPE_LAST: break; } @@ -7986,6 +7987,9 @@ qemuBuildAudioCommandLineArg(virCommand *cmd, return -1; break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: default: virReportEnumRangeError(virDomainAudioType, def->type); @@ -8190,6 +8194,9 @@ qemuBuildAudioCommandLineEnv(virCommand *cmd, audio->backend.file.path); break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: default: virReportEnumRangeError(virDomainAudioType, audio->type); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 5a437562c2..5bfb9fd311 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4507,6 +4507,9 @@ qemuValidateDomainDeviceDefAudio(virDomainAudioDef *audio, case VIR_DOMAIN_AUDIO_TYPE_FILE: break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: + break; + case VIR_DOMAIN_AUDIO_TYPE_LAST: default: virReportEnumRangeError(virDomainAudioType, audio->type); diff --git a/tests/qemuxml2argvdata/graphics-dbus-audio.xml b/tests/qemuxml2argvdata/graphics-dbus-audio.xml new file mode 100644 index 0000000000..b1304e3f6f --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-audio.xml @@ -0,0 +1,45 @@ +<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'>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-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus' p2p='yes'> + <audio id='1'/> + </graphics> + <audio id='1' type='dbus'> + <input mixingEngine='no'/> + <output mixingEngine='no'/> + </audio> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-audio.xml b/tests/qemuxml2xmloutdata/graphics-dbus-audio.xml new file mode 120000 index 0000000000..fe0f4a81d9 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-audio.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/graphics-dbus-audio.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 6578a80213..eb4e070f9e 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -409,6 +409,10 @@ mymain(void) DO_TEST("graphics-dbus-p2p", QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-audio", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS, + QEMU_CAPS_AUDIODEV); DO_TEST_CAPS_ARCH_LATEST("default-video-type-aarch64", "aarch64"); DO_TEST_CAPS_ARCH_LATEST("default-video-type-ppc64", "ppc64"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_command.c | 12 +++++-- src/qemu/qemu_validate.c | 30 ++++++++++++++++- .../qemuxml2argvdata/graphics-dbus-audio.args | 33 +++++++++++++++++++ tests/qemuxml2argvtest.c | 2 ++ 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4ae946ec00..9367eb4dc6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8593,7 +8593,8 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED, static int -qemuBuildGraphicsDBusCommandLine(virCommand *cmd, +qemuBuildGraphicsDBusCommandLine(virDomainDef *def, + virCommand *cmd, virDomainGraphicsDef *graphics) { g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; @@ -8615,6 +8616,13 @@ qemuBuildGraphicsDBusCommandLine(virCommand *cmd, graphics->data.dbus.rendernode); } + if (graphics->data.dbus.audioId > 0) { + g_autofree char *audioid = qemuGetAudioIDString(def, graphics->data.dbus.audioId); + if (!audioid) + return -1; + virBufferAsprintf(&opt, ",audiodev=%s", audioid); + } + virCommandAddArg(cmd, "-display"); virCommandAddArgBuffer(cmd, &opt); @@ -8659,7 +8667,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: - if (qemuBuildGraphicsDBusCommandLine(cmd, graphics) < 0) + if (qemuBuildGraphicsDBusCommandLine(def, cmd, graphics) < 0) return -1; break; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 5bfb9fd311..be6b2c508b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4174,6 +4174,24 @@ qemuValidateDomainDeviceDefVNCGraphics(const virDomainGraphicsDef *graphics, } +static int +qemuValidateDomainDeviceDefDBusGraphics(const virDomainGraphicsDef *graphics, + const virDomainDef *def) +{ + if (graphics->data.dbus.audioId > 0) { + virDomainAudioDef *audio = virDomainDefFindAudioByID(def, graphics->data.dbus.audioId); + + if (audio && audio->type != VIR_DOMAIN_AUDIO_TYPE_DBUS) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The associated audio is not of 'dbus' kind.")); + return -1; + } + } + + return 0; +} + + static int qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics, const virDomainDef *def, @@ -4251,10 +4269,15 @@ qemuValidateDomainDeviceDefGraphics(const virDomainGraphicsDef *graphics, break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (qemuValidateDomainDeviceDefDBusGraphics(graphics, def) < 0) + return -1; + + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: - case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -4508,6 +4531,11 @@ qemuValidateDomainDeviceDefAudio(virDomainAudioDef *audio, break; case VIR_DOMAIN_AUDIO_TYPE_DBUS: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISPLAY_DBUS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("D-Bus audio is not supported with this QEMU")); + return -1; + } break; case VIR_DOMAIN_AUDIO_TYPE_LAST: diff --git a/tests/qemuxml2argvdata/graphics-dbus-audio.args b/tests/qemuxml2argvdata/graphics-dbus-audio.args new file mode 100644 index 0000000000..968dddfd89 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-audio.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ +-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \ +-audiodev '{"id":"audio1","driver":"dbus","in":{"mixing-engine":false},"out":{"mixing-engine":false}}' \ +-display dbus,p2p=on,audiodev=audio1 \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 0d0c75b253..c25290f55e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1544,6 +1544,8 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); DO_TEST("graphics-dbus-p2p", QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-audio", + QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS, QEMU_CAPS_AUDIODEV); DO_TEST_NOCAPS("input-usbmouse"); DO_TEST_NOCAPS("input-usbtablet"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Like a Spice port, a dbus serial must specify an associated channel name. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/conf/domain_conf.c | 25 +++++++++++ src/conf/domain_conf.h | 4 ++ src/conf/domain_validate.c | 32 ++++++++++---- src/conf/schemas/domaincommon.rng | 1 + src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_process.c | 1 + src/qemu/qemu_validate.c | 1 + src/security/security_dac.c | 2 + .../graphics-dbus-chardev.xml | 43 +++++++++++++++++++ .../graphics-dbus-chardev.xml | 1 + tests/qemuxml2xmltest.c | 3 ++ tests/testutilsqemu.c | 1 + 13 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.xml create mode 120000 tests/qemuxml2xmloutdata/graphics-dbus-chardev.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fbefba6200..bde39fd6b2 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -716,6 +716,7 @@ VIR_ENUM_IMPL(virDomainChr, "spiceport", "nmdm", "qemu-vdagent", + "dbus", ); VIR_ENUM_IMPL(virDomainChrTcpProtocol, @@ -2711,6 +2712,7 @@ virDomainChrSourceDefGetPath(virDomainChrSourceDef *chr) case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: return NULL; } @@ -2754,6 +2756,10 @@ virDomainChrSourceDefClear(virDomainChrSourceDef *def) case VIR_DOMAIN_CHR_TYPE_SPICEPORT: VIR_FREE(def->data.spiceport.channel); break; + + case VIR_DOMAIN_CHR_TYPE_DBUS: + VIR_FREE(def->data.dbus.channel); + break; } VIR_FREE(def->logfile); @@ -2825,6 +2831,10 @@ virDomainChrSourceDefCopy(virDomainChrSourceDef *dest, dest->data.qemuVdagent.mouse = src->data.qemuVdagent.mouse; break; + case VIR_DOMAIN_CHR_TYPE_DBUS: + dest->data.dbus.channel = g_strdup(src->data.dbus.channel); + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -2909,6 +2919,12 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: return src->data.qemuVdagent.clipboard == tgt->data.qemuVdagent.clipboard && src->data.qemuVdagent.mouse == tgt->data.qemuVdagent.mouse; + break; + + case VIR_DOMAIN_CHR_TYPE_DBUS: + return STREQ_NULLABLE(src->data.dbus.channel, + tgt->data.dbus.channel); + break; case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -11342,6 +11358,10 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDef *def, def->data.spiceport.channel = virXMLPropString(sources[0], "channel"); break; + case VIR_DOMAIN_CHR_TYPE_DBUS: + def->data.dbus.channel = virXMLPropString(sources[0], "channel"); + break; + case VIR_DOMAIN_CHR_TYPE_NMDM: def->data.nmdm.master = virXMLPropString(sources[0], "master"); def->data.nmdm.slave = virXMLPropString(sources[0], "slave"); @@ -25197,6 +25217,11 @@ virDomainChrSourceDefFormat(virBuffer *buf, virBufferEscapeString(buf, "<source channel='%s'/>\n", def->data.spiceport.channel); break; + + case VIR_DOMAIN_CHR_TYPE_DBUS: + virBufferEscapeString(buf, "<source channel='%s'/>\n", + def->data.dbus.channel); + break; } if (def->logfile) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index db50e552b0..92bab257fa 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1242,6 +1242,7 @@ typedef enum { VIR_DOMAIN_CHR_TYPE_SPICEPORT, VIR_DOMAIN_CHR_TYPE_NMDM, VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT, + VIR_DOMAIN_CHR_TYPE_DBUS, VIR_DOMAIN_CHR_TYPE_LAST } virDomainChrType; @@ -1321,6 +1322,9 @@ struct _virDomainChrSourceDef { virDomainMouseMode mouse; virTristateBool clipboard; } qemuVdagent; + struct { + char *channel; + } dbus; } data; char *logfile; virTristateSwitch logappend; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index ba474ee8c0..627c366fe9 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -909,6 +909,24 @@ virDomainDiskDefValidate(const virDomainDef *def, #define SERIAL_CHANNEL_NAME_CHARS \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-." + +static int +virDomainChrSourceDefValidateChannelName(const char *name) +{ + if (!name) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Missing source channel attribute for char device")); + return -1; + } + if (strspn(name, SERIAL_CHANNEL_NAME_CHARS) < strlen(name)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Invalid character in source channel for char device")); + return -1; + } + + return 0; +} + static int virDomainChrSourceDefValidate(const virDomainChrSourceDef *src_def, const virDomainChrDef *chr_def, @@ -995,17 +1013,13 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *src_def, break; case VIR_DOMAIN_CHR_TYPE_SPICEPORT: - if (!src_def->data.spiceport.channel) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Missing source channel attribute for char device")); + if (virDomainChrSourceDefValidateChannelName(src_def->data.spiceport.channel) < 0) return -1; - } - if (strspn(src_def->data.spiceport.channel, - SERIAL_CHANNEL_NAME_CHARS) < strlen(src_def->data.spiceport.channel)) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Invalid character in source channel for char device")); + break; + + case VIR_DOMAIN_CHR_TYPE_DBUS: + if (virDomainChrSourceDefValidateChannelName(src_def->data.dbus.channel) < 0) return -1; - } break; } diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 6c210f6e78..fc7c987af5 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -4561,6 +4561,7 @@ <value>spiceport</value> <value>nmdm</value> <value>qemu-vdagent</value> + <value>dbus</value> </choice> </define> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9367eb4dc6..9ff2d1b0e0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1443,6 +1443,7 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, } break; + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_LAST: default: @@ -1528,6 +1529,7 @@ qemuBuildChardevCommand(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: break; case VIR_DOMAIN_CHR_TYPE_NMDM: @@ -8713,6 +8715,7 @@ qemuInterfaceVhostuserConnect(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: virReportError(VIR_ERR_INTERNAL_ERROR, _("vhost-user type '%s' not supported"), diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index d9f93bd2fa..afa81d1b04 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6847,6 +6847,7 @@ qemuMonitorJSONAttachCharDevGetProps(const char *chrID, break; } + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4751f60d74..f4ffb51b27 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6867,6 +6867,7 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: break; case VIR_DOMAIN_CHR_TYPE_FILE: { diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index be6b2c508b..9b6245e6d7 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2015,6 +2015,7 @@ qemuValidateDomainChrSourceDef(const virDomainChrSourceDef *def, case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_UDP: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 5b840f4225..69c462de8b 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1556,6 +1556,7 @@ virSecurityDACSetChardevLabelHelper(virSecurityManager *mgr, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: break; } @@ -1641,6 +1642,7 @@ virSecurityDACRestoreChardevLabelHelper(virSecurityManager *mgr, case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/qemuxml2argvdata/graphics-dbus-chardev.xml b/tests/qemuxml2argvdata/graphics-dbus-chardev.xml new file mode 100644 index 0000000000..d2ca208bd9 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-chardev.xml @@ -0,0 +1,43 @@ +<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'>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-system-i386</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <serial type='dbus'> + <source channel='org.qemu.console.serial.0'/> + <target type='isa-serial' port='1'> + <model name='isa-serial'/> + </target> + </serial> + <console type='dbus'> + <source channel='org.qemu.console.serial.0'/> + <target type='serial' port='1'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus' p2p='yes'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-chardev.xml b/tests/qemuxml2xmloutdata/graphics-dbus-chardev.xml new file mode 120000 index 0000000000..85dabfad76 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-chardev.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/graphics-dbus-chardev.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index eb4e070f9e..c16ce75e14 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -413,6 +413,9 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS, QEMU_CAPS_AUDIODEV); + DO_TEST("graphics-dbus-chardev", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS); DO_TEST_CAPS_ARCH_LATEST("default-video-type-aarch64", "aarch64"); DO_TEST_CAPS_ARCH_LATEST("default-video-type-ppc64", "ppc64"); diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 7f6d9ee06f..5ae6daf053 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -1057,6 +1057,7 @@ testQemuPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + case VIR_DOMAIN_CHR_TYPE_DBUS: break; case VIR_DOMAIN_CHR_TYPE_FILE: -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_command.c | 4 +++ src/qemu/qemu_monitor_json.c | 9 ++++++ .../graphics-dbus-chardev.args | 32 +++++++++++++++++++ tests/qemuxml2argvtest.c | 4 +++ 4 files changed, 49 insertions(+) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9ff2d1b0e0..a9286d3233 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1444,6 +1444,10 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, break; case VIR_DOMAIN_CHR_TYPE_DBUS: + virBufferAsprintf(&buf, "dbus,id=%s,name=%s", charAlias, + dev->data.dbus.channel); + break; + case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_LAST: default: diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index afa81d1b04..52563f58f3 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6848,6 +6848,15 @@ qemuMonitorJSONAttachCharDevGetProps(const char *chrID, } case VIR_DOMAIN_CHR_TYPE_DBUS: + backendType = "dbus"; + + if (virJSONValueObjectAdd(&backendData, + "s:name", chr->data.dbus.channel, + NULL) < 0) + return NULL; + + break; + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: diff --git a/tests/qemuxml2argvdata/graphics-dbus-chardev.args b/tests/qemuxml2argvdata/graphics-dbus-chardev.args new file mode 100644 index 0000000000..b188a120c8 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-chardev.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-chardev dbus,id=charserial0,name=org.qemu.console.serial.0 \ +-device isa-serial,chardev=charserial0,id=serial0,index=1 \ +-display dbus,p2p=on \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c25290f55e..13b760b163 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1546,6 +1546,10 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); DO_TEST("graphics-dbus-audio", QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS, QEMU_CAPS_AUDIODEV); + DO_TEST("graphics-dbus-chardev", + QEMU_CAPS_DEVICE_ISA_SERIAL, + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS); DO_TEST_NOCAPS("input-usbmouse"); DO_TEST_NOCAPS("input-usbtablet"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> The USB device redirection works in a similar way as Spice. The underlying 'dbus' channel is set to "org.qemu.usbredir" by default for the client to identify the channel purpose (as specified in -display dbus documentation). Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/conf/domain_conf.c | 2 ++ .../graphics-dbus-usbredir.args | 34 +++++++++++++++++++ .../graphics-dbus-usbredir.xml | 30 ++++++++++++++++ tests/qemuxml2argvtest.c | 4 +++ 4 files changed, 70 insertions(+) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-usbredir.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-usbredir.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bde39fd6b2..504d4958c8 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14410,6 +14410,8 @@ virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt, if (def->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) def->source->data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_USBREDIR; + if (def->source->type == VIR_DOMAIN_CHR_TYPE_DBUS && !def->source->data.dbus.channel) + def->source->data.dbus.channel = g_strdup("org.qemu.usbredir"); if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT) < 0) diff --git a/tests/qemuxml2argvdata/graphics-dbus-usbredir.args b/tests/qemuxml2argvdata/graphics-dbus-usbredir.args new file mode 100644 index 0000000000..2e9ebb9463 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-usbredir.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,usb=off,dump-guest-core=off \ +-accel tcg \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-no-acpi \ +-boot strict=on \ +-usb \ +-display dbus,p2p=on \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-chardev dbus,id=charredir0,name=org.qemu.usbredir \ +-device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=1 \ +-chardev dbus,id=charredir1,name=org.qemu.usbredir \ +-device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-usbredir.xml b/tests/qemuxml2argvdata/graphics-dbus-usbredir.xml new file mode 100644 index 0000000000..fad6cd8b5f --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-usbredir.xml @@ -0,0 +1,30 @@ +<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'>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-system-i386</emulator> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='dbus' p2p='yes'/> + <redirdev bus='usb' type='dbus'/> + <redirdev bus='usb' type='dbus'/> + <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 13b760b163..2305ddbb2f 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1550,6 +1550,10 @@ mymain(void) QEMU_CAPS_DEVICE_ISA_SERIAL, QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS); + DO_TEST("graphics-dbus-usbredir", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS, + QEMU_CAPS_USB_REDIR); DO_TEST_NOCAPS("input-usbmouse"); DO_TEST_NOCAPS("input-usbtablet"); -- 2.36.1

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- NEWS.rst | 5 +++++ docs/formatdomain.rst | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/NEWS.rst b/NEWS.rst index 7903449f9b..b32fd26167 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,11 @@ v8.4.0 (unreleased) * **New features** + * qemu: D-Bus display + + Libvirt is now able to setup a D-Bus display export, either with a private + bus or in p2p mode. This display is available in QEMU 7.0.0. + * **Improvements** * **Bug fixes** diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index c1e99951a6..7e31c6b303 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6080,6 +6080,39 @@ interaction with the admin. <gl rendernode='/dev/dri/renderD128'/> </graphics> + ``dbus``:since:`Since 8.4.0` + Export the display over D-Bus. By default, it will use a private bus, + except when ``p2p`` or ``address`` are specified. + + :: + + <graphics type='dbus'/> + + ``p2p`` (accepts ``on`` or ``off``) enables peer-to-peer connections, + established through virDomainOpenGraphics() APIs. + + ``address`` (accepts a `D-Bus address + <https://dbus.freedesktop.org/doc/dbus-specification.html#addresses>`_), + will connect to the specified bus address. + + This element accepts a ``<gl/>`` sub-element with an optional attribute + ``rendernode`` which can be used to specify an absolute path to a host's + DRI device to be used for OpenGL rendering. + + Copy & Paste functionality is provided thanks to the QEMU clipboard + manager and the SPICE vdagent protocol. See ``qemu-vdagent`` for more + details. + + D-Bus can export an audio backend using the ``<audio>`` sub-element: + + :: + + <graphics type='dbus' ...> + <audio id='1'> + </graphics> + + Where ``1`` is an id of the `audio device <#elementsAudio>`__. + Graphics device uses a ``<listen>`` to set up where the device should listen for clients. It has a mandatory attribute ``type`` which specifies the listen type. Only ``vnc``, ``spice`` and ``rdp`` supports ``<listen>`` element. :since:`Since @@ -6996,7 +7029,7 @@ to the guest sound device. ``type`` The required ``type`` attribute specifies audio backend type. Currently, the supported values are 'none', 'alsa', 'coreaudio', - 'jack', 'oss', 'pulseaudio', 'sdl', 'spice', 'file'. + 'dbus', jack', 'oss', 'pulseaudio', 'sdl', 'spice', 'file'. ``id`` Integer id of the audio device. Must be greater than 0. @@ -7137,6 +7170,14 @@ and ``<output>`` elements :since:`Since 7.2.0, qemu` +D-Bus audio backend +^^^^^^^^^^^^^^^^^^^ + +The 'dbus' audio backend does not connect to any host audio framework. It +exports a D-Bus interface when associated with a D-Bus display. + +:since:`Since 8.4.0, qemu` + Jack audio backend ^^^^^^^^^^^^^^^^^^ -- 2.36.1

On 5/13/22 20:38, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
This series implements supports for the QEMU "-display dbus" support, available since 7.0.
By default, libvirt will start a private VM bus (sharing and reusing the existing "vmstate" VM bus & code).
The feature set should cover the needs to replace Spice as local client of choice, including 3daccel/dmabuf, audio, clipboard sharing, usb redirection, and arbitrary chardev/channels (for serial etc).
The test Gtk4 client is also in progress, currently in development at https://gitlab.com/marcandre.lureau/qemu-display/. virt-viewer & boxes will need a port to Gtk4 to make use of the shared widget.
thanks
v4: - rebased, dropped some patches, updated versions in docs, code adjustments etc - dropped clipboard option, as standalone qemu-vdagent support landed
v3: after QEMU 7.0 dev cycle opening and merge - rebased - add 7.0 x86-64 capabilities (instead of tweaking 6.2) - fix version annotations
Marc-André Lureau (11): qemu: add -display dbus capability check conf: add <graphics type='dbus'> qemu: start the D-Bus daemon for the display qemu: add -display dbus support virsh: report the D-Bus bus URI for domdisplay conf: add <audio type='dbus'> support qemu: add audio type 'dbus' conf: add <serial type='dbus'> qemu: add -chardev dbus support qemu: add usbredir type 'dbus' docs: document <graphics> type dbus
52 files changed, 948 insertions(+), 20 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> and pushed. Michal
participants (2)
-
marcandre.lureau@redhat.com
-
Michal Prívozník