[libvirt PATCH 0/9] WIP/RFC: add QEMU "-display dbus" support

From: Marc-André Lureau <marcandre.lureau@redhat.com> Hi, This series implements supports for the upcoming QEMU "-display dbus" support. Development is still in progress, but I hope to land the QEMU support early in 6.3 (last version posted: https://patchew.org/QEMU/20211009210838.2219430-1-marcandre.lureau@redhat.co...). By default, libvirt will start a private VM bus (sharing and reusing the existing "vmstate" code). A client will need the address of the bus and access to it. Since D-Bus addresses are not URIs unfortunately, I am not sure yet what should "virsh domdisplay" return. 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/. A few dependencies, such as zbus, require an upcoming release. virt-viewer & boxes will need a port to Gtk4 to make use of the shared widget. Comments welcome, as we can still adjust the QEMU side etc. thanks Marc-André Lureau (9): qemu: start the D-Bus daemon as needed qemu: add chardev-vdagent capability check qemu: add -display dbus capability check (to update to 6.3) qemu: add -display dbus support qemu: add audio type 'dbus' qemu: add dbus clipboard sharing qemu: add -chardev dbus qemu: add usbredir type 'dbus' docs: document <graphics> type dbus docs/formatdomain.rst | 24 ++++ docs/schemas/basictypes.rng | 7 ++ docs/schemas/domaincommon.rng | 71 +++++++++++ src/bhyve/bhyve_command.c | 1 + src/conf/domain_conf.c | 116 +++++++++++++++++- src/conf/domain_conf.h | 14 +++ src/conf/domain_validate.c | 32 +++-- src/libxl/libxl_conf.c | 1 + src/qemu/qemu_capabilities.c | 6 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 94 +++++++++++++- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 10 +- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_process.c | 15 ++- src/qemu/qemu_validate.c | 33 +++++ src/security/security_dac.c | 2 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.aarch64.xml | 1 + .../caps_6.2.0.x86_64.replies | 10 +- .../caps_6.2.0.x86_64.xml | 2 + .../graphics-dbus-address.args | 31 +++++ .../graphics-dbus-address.xml | 34 +++++ .../qemuxml2argvdata/graphics-dbus-audio.args | 32 +++++ .../qemuxml2argvdata/graphics-dbus-audio.xml | 40 ++++++ .../graphics-dbus-chardev.args | 33 +++++ .../graphics-dbus-chardev.xml | 38 ++++++ .../graphics-dbus-clipboard.args | 32 +++++ .../graphics-dbus-clipboard.xml | 36 ++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 31 +++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 36 ++++++ .../graphics-dbus-usbredir.args | 35 ++++++ .../graphics-dbus-usbredir.xml | 36 ++++++ tests/qemuxml2argvdata/graphics-dbus.args | 31 +++++ tests/qemuxml2argvdata/graphics-dbus.xml | 34 +++++ tests/qemuxml2argvtest.c | 21 ++++ .../graphics-dbus-address.xml | 39 ++++++ .../graphics-dbus-audio.xml | 43 +++++++ .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 39 ++++++ tests/qemuxml2xmloutdata/graphics-dbus.xml | 39 ++++++ tests/qemuxml2xmltest.c | 14 +++ 47 files changed, 1106 insertions(+), 18 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-clipboard.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-clipboard.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 100644 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-audio.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus.xml -- 2.33.0.721.g106298f7f9

From: Marc-André Lureau <marcandre.lureau@redhat.com> The daemon is started on daemon in external devices and hotplug code. Add a mechanism to start it before qemu, if qemu itself needs it. (it is already stopped in qemuProcessStop) Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_process.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 6728ab047ed0..575fb8393b83 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -237,6 +237,7 @@ struct _qemuDomainObjPrivate { /* running backup job */ virDomainBackupDef *backup; + bool dbusDaemonWanted; bool dbusDaemonRunning; /* list of Ids to migrate */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5f8a47ac293..4ca9b100a802 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7284,6 +7284,10 @@ qemuProcessLaunch(virConnectPtr conn, &nnicindexes, &nicindexes, 0))) goto cleanup; + if (QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted && + qemuDBusStart(driver, vm) < 0) + goto cleanup; + if (incoming && incoming->fd != -1) virCommandPassFD(cmd, incoming->fd, 0); -- 2.33.0.721.g106298f7f9

On 11/5/21 11:51, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The daemon is started on daemon in external devices and hotplug code. Add a mechanism to start it before qemu, if qemu itself needs it. (it is already stopped in qemuProcessStop)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_process.c | 4 ++++ 2 files changed, 5 insertions(+)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 6728ab047ed0..575fb8393b83 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -237,6 +237,7 @@ struct _qemuDomainObjPrivate { /* running backup job */ virDomainBackupDef *backup;
+ bool dbusDaemonWanted; bool dbusDaemonRunning;
/* list of Ids to migrate */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5f8a47ac293..4ca9b100a802 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7284,6 +7284,10 @@ qemuProcessLaunch(virConnectPtr conn, &nnicindexes, &nicindexes, 0))) goto cleanup;
+ if (QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted && + qemuDBusStart(driver, vm) < 0) + goto cleanup; +
We already have priv variable, so s/QEMU_DOMAIN_PRIVATE(vm)/priv/. However, we already have qemuExtDevicesStart() which I believe can be used to check whether dbus graphics was defined and thus whether dbus daemon needs to be started.
if (incoming && incoming->fd != -1) virCommandPassFD(cmd, incoming->fd, 0);
Michal

On Mon, Nov 29, 2021 at 9:20 PM Michal Prívozník <mprivozn@redhat.com> wrote:
On 11/5/21 11:51, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The daemon is started on daemon in external devices and hotplug code. Add a mechanism to start it before qemu, if qemu itself needs it. (it is already stopped in qemuProcessStop)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_process.c | 4 ++++ 2 files changed, 5 insertions(+)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 6728ab047ed0..575fb8393b83 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -237,6 +237,7 @@ struct _qemuDomainObjPrivate { /* running backup job */ virDomainBackupDef *backup;
+ bool dbusDaemonWanted; bool dbusDaemonRunning;
/* list of Ids to migrate */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d5f8a47ac293..4ca9b100a802 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7284,6 +7284,10 @@ qemuProcessLaunch(virConnectPtr conn, &nnicindexes, &nicindexes, 0))) goto cleanup;
+ if (QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted && + qemuDBusStart(driver, vm) < 0) + goto cleanup; +
We already have priv variable, so s/QEMU_DOMAIN_PRIVATE(vm)/priv/. However, we already have qemuExtDevicesStart() which I believe can be used to check whether dbus graphics was defined and thus whether dbus daemon needs to be started.
indeed, done. thanks
if (incoming && incoming->fd != -1) virCommandPassFD(cmd, incoming->fd, 0);
Michal

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_6.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + 5 files changed, 6 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index e4fdd9a1ebe9..b5e893f66656 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -651,6 +651,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "device.json", /* QEMU_CAPS_DEVICE_JSON */ "query-dirty-rate", /* QEMU_CAPS_QUERY_DIRTY_RATE */ "rbd-encryption", /* QEMU_CAPS_RBD_ENCRYPTION */ + "chardev-vdagent", /* QEMU_CAPS_CHARDEV_VDAGENT */ ); @@ -1569,6 +1570,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "query-named-block-nodes/arg-type/flat", QEMU_CAPS_QMP_QUERY_NAMED_BLOCK_NODES_FLAT }, { "screendump/arg-type/device", QEMU_CAPS_SCREENDUMP_DEVICE }, { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, + { "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_VDAGENT }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 61bdbdb2ac2b..493a1eb1a283 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -631,6 +631,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON */ QEMU_CAPS_QUERY_DIRTY_RATE, /* accepts query-dirty-rate */ QEMU_CAPS_RBD_ENCRYPTION, /* Ceph RBD encryption support */ + QEMU_CAPS_CHARDEV_VDAGENT, /* -chardev qemu-vdagent */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml index 1f4f49eb34ad..75cf496e7712 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -239,6 +239,7 @@ <flag name='piix4.acpi-root-pci-hotplug'/> <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> + <flag name='chardev-vdagent'/> <version>6001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml index 9662214cd882..032776706d7e 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml @@ -204,6 +204,7 @@ <flag name='device.json'/> <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> + <flag name='chardev-vdagent'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index 39179916c5d3..145137ddfa08 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='device.json'/> <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> + <flag name='chardev-vdagent'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> -- 2.33.0.721.g106298f7f9

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_6.2.0.x86_64.replies | 10 +++++++++- tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b5e893f66656..c1579a2bf4b3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -652,6 +652,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "query-dirty-rate", /* QEMU_CAPS_QUERY_DIRTY_RATE */ "rbd-encryption", /* QEMU_CAPS_RBD_ENCRYPTION */ "chardev-vdagent", /* QEMU_CAPS_CHARDEV_VDAGENT */ + "display-dbus", /* QEMU_CAPS_DISPLAY_DBUS */ ); @@ -1571,6 +1572,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "screendump/arg-type/device", QEMU_CAPS_SCREENDUMP_DEVICE }, { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_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 493a1eb1a283..b15139537841 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -632,6 +632,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_QUERY_DIRTY_RATE, /* accepts query-dirty-rate */ QEMU_CAPS_RBD_ENCRYPTION, /* Ceph RBD encryption support */ QEMU_CAPS_CHARDEV_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_6.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies index 69d3b1b12a6e..e823ad1188b8 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies @@ -5000,6 +5000,10 @@ { "case": "spice-app", "type": "0" + }, + { + "case": "dbus", + "type": "0" } ], "members": [ @@ -11456,6 +11460,9 @@ }, { "name": "spice-app" + }, + { + "name": "dbus" } ], "meta-type": "enum", @@ -11465,7 +11472,8 @@ "sdl", "egl-headless", "curses", - "spice-app" + "spice-app", + "dbus" ] }, { diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index 145137ddfa08..8001ddde8887 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -241,6 +241,7 @@ <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> <flag name='chardev-vdagent'/> + <flag name='display-dbus'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> -- 2.33.0.721.g106298f7f9

On Fri, Nov 05, 2021 at 14:51:13 +0400, marcandre.lureau@redhat.com wrote:
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_6.2.0.x86_64.replies | 10 +++++++++- tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + 4 files changed, 13 insertions(+), 1 deletion(-)
[...]
diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies index 69d3b1b12a6e..e823ad1188b8 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies @@ -5000,6 +5000,10 @@ { "case": "spice-app", "type": "0" + }, + { + "case": "dbus", + "type": "0" } ], "members": [ @@ -11456,6 +11460,9 @@ }, { "name": "spice-app" + }, + { + "name": "dbus" } ], "meta-type": "enum", @@ -11465,7 +11472,8 @@ "sdl", "egl-headless", "curses", - "spice-app" + "spice-app", + "dbus"
I didn't find this one in my latest re-generation of the capabilities from the current master. Do I need to enable/add some dependencies, or is this something that is not upstream yet? In case if it isn't upstream, these hunks are obviously not acceptable.

Hi On Tue, Nov 30, 2021 at 12:41 AM Peter Krempa <pkrempa@redhat.com> wrote:
On Fri, Nov 05, 2021 at 14:51:13 +0400, marcandre.lureau@redhat.com wrote:
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_6.2.0.x86_64.replies | 10 +++++++++- tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + 4 files changed, 13 insertions(+), 1 deletion(-)
[...]
diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies index 69d3b1b12a6e..e823ad1188b8 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.replies @@ -5000,6 +5000,10 @@ { "case": "spice-app", "type": "0" + }, + { + "case": "dbus", + "type": "0" } ], "members": [ @@ -11456,6 +11460,9 @@ }, { "name": "spice-app" + }, + { + "name": "dbus" } ], "meta-type": "enum", @@ -11465,7 +11472,8 @@ "sdl", "egl-headless", "curses", - "spice-app" + "spice-app", + "dbus"
I didn't find this one in my latest re-generation of the capabilities from the current master. Do I need to enable/add some dependencies, or is this something that is not upstream yet? In case if it isn't upstream, these hunks are obviously not acceptable.
As explained on the cover letter, this series is WIP/RFC before I propose a MR for qemu in early 6.3 (this month). thanks

From: Marc-André Lureau <marcandre.lureau@redhat.com> Without any extra option, libvirt will start and tell QEMU to connect to the private VM bus. Instead, a D-Bus "address" to connect to can be specified. Or the p2p mode enabled. D-Bus display best works with GL & a rendernode, which can be specified with <gl> child element. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/basictypes.rng | 7 ++ docs/schemas/domaincommon.rng | 33 ++++++++++ src/conf/domain_conf.c | 65 ++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_command.c | 57 ++++++++++++++-- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 10 ++- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_process.c | 11 +++- src/qemu/qemu_validate.c | 1 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../graphics-dbus-address.args | 31 +++++++++ .../graphics-dbus-address.xml | 34 ++++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 36 ++++++++++ tests/qemuxml2argvdata/graphics-dbus.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus.xml | 34 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ .../graphics-dbus-address.xml | 39 +++++++++++ .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 39 +++++++++++ tests/qemuxml2xmloutdata/graphics-dbus.xml | 39 +++++++++++ tests/qemuxml2xmltest.c | 10 +++ 27 files changed, 523 insertions(+), 8 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-p2p.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus.xml diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a221ff6295c0..ae4d5682229c 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/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/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f01b7a64704b..1dba199db7ec 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3996,6 +3996,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/conf/domain_conf.c b/src/conf/domain_conf.c index da0c64b46009..8a2f3c4115e0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -911,6 +911,7 @@ VIR_ENUM_IMPL(virDomainGraphics, "desktop", "spice", "egl-headless", + "dbus", ); VIR_ENUM_IMPL(virDomainGraphicsListen, @@ -1891,6 +1892,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; } @@ -12896,6 +12902,38 @@ 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"); + + 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) { @@ -12970,6 +13008,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; } @@ -26661,6 +26703,15 @@ 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.rendernode) + break; + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -31231,6 +31282,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; } @@ -31246,7 +31302,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; @@ -31265,6 +31322,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: @@ -31286,6 +31346,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 ab9a7d66f86d..42fe583418a6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1733,6 +1733,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; @@ -1916,6 +1917,12 @@ struct _virDomainGraphicsDef { struct { char *rendernode; } egl_headless; + struct { + bool p2p; + char *address; + char *rendernode; + virTristateBool gl; + } 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/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 9f0739e1faff..b19009f270aa 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1551,6 +1551,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/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c1579a2bf4b3..2c3a81eda245 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6021,6 +6021,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 483041f584d8..1960861015c6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8601,7 +8601,46 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED, static int -qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, +qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, + virDomainObj *vm, + virCommand *cmd, + virDomainGraphicsDef *graphics) +{ + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + + if (!graphics->data.dbus.p2p && !graphics->data.dbus.address) { + graphics->data.dbus.address = qemuDBusGetAddress(driver, vm); + QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted = true; + } + + 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(virQEMUDriver *driver, + virDomainObj *vm, + virQEMUDriverConfig *cfg, virCommand *cmd, virDomainDef *def, virQEMUCaps *qemuCaps) @@ -8635,6 +8674,12 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, graphics) < 0) return -1; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (qemuBuildGraphicsDBusCommandLine(driver, vm, cmd, + graphics) < 0) + return -1; + break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -10363,6 +10408,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 @@ -10407,6 +10453,9 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++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: @@ -10414,10 +10463,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; } @@ -10789,7 +10838,7 @@ qemuBuildCommandLine(virQEMUDriver *driver, if (qemuBuildAudioCommandLine(cmd, def, qemuCaps) < 0) return NULL; - if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0) + if (qemuBuildGraphicsCommandLine(driver, vm, cfg, cmd, def, qemuCaps) < 0) return NULL; if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index fb203bc83085..b027443ca346 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3453,6 +3453,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 7d13ae9754b4..d7cf7d43b267 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15741,12 +15741,15 @@ qemuDomainOpenGraphics(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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: @@ -15810,12 +15813,15 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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 328b06245f42..6037b4b92c34 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4451,6 +4451,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 4ca9b100a802..2a413d602a10 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4784,6 +4784,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; } @@ -4823,6 +4824,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; } @@ -4979,6 +4981,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; } @@ -5047,11 +5050,16 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef *graphics, return 0; rendernode = &graphics->data.spice.rendernode; - } else { + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) return 0; rendernode = &graphics->data.egl_headless.rendernode; + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS) { + rendernode = &graphics->data.dbus.rendernode; + } else { + g_warn_if_reached(); + return -1; } if (!(*rendernode = virHostGetDRMRenderNode())) @@ -5284,6 +5292,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 397eea5edeaa..23c7e9f94cd0 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4168,6 +4168,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 d3540acd84a8..2c48bbc5e812 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -3446,6 +3446,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_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index df8bdae10227..ce3577f582d4 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -154,6 +154,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_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 4d1210565968..c553d8d0b245 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -160,6 +160,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_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index c382ec462ca6..214285c958bc 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -154,6 +154,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.args b/tests/qemuxml2argvdata/graphics-dbus-address.args new file mode 100644 index 000000000000..12a5fadca782 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,addr=unix:path=/tmp/foo \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-address.xml b/tests/qemuxml2argvdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..958e6a6a4059 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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'/> + <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' address='unix:path=/tmp/foo'/> + <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.args b/tests/qemuxml2argvdata/graphics-dbus-p2p.args new file mode 100644 index 000000000000..c3b1cc0c12cf --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,p2p=on,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.xml b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml new file mode 100644 index 000000000000..80c2e42b4dc8 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml @@ -0,0 +1,36 @@ +<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'/> + <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'> + <gl enable='yes' rendernode='/dev/dri/foo'/> + </graphics> + <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus.args b/tests/qemuxml2argvdata/graphics-dbus.args new file mode 100644 index 000000000000..7149e0177671 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-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/qemuxml2argvdata/graphics-dbus.xml b/tests/qemuxml2argvdata/graphics-dbus.xml new file mode 100644 index 000000000000..ab0dcf1187af --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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'/> + <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'/> + <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 a0498a0d9201..4345ab47e053 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1518,6 +1518,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"); diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-address.xml b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..8ead97baacd4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml @@ -0,0 +1,39 @@ +<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' address='unix:path=/tmp/foo'/> + <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-p2p.xml b/tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml new file mode 100644 index 000000000000..9e3b76349c13 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml @@ -0,0 +1,39 @@ +<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'/> + <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.xml b/tests/qemuxml2xmloutdata/graphics-dbus.xml new file mode 100644 index 000000000000..51e98323f045 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus.xml @@ -0,0 +1,39 @@ +<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'/> + <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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7ea066fcda36..92d1c02fd3e8 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -373,6 +373,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.33.0.721.g106298f7f9

On 11/5/21 11:51, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Without any extra option, libvirt will start and tell QEMU to connect to the private VM bus.
Instead, a D-Bus "address" to connect to can be specified. Or the p2p mode enabled.
D-Bus display best works with GL & a rendernode, which can be specified with <gl> child element.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/basictypes.rng | 7 ++ docs/schemas/domaincommon.rng | 33 ++++++++++ src/conf/domain_conf.c | 65 ++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_command.c | 57 ++++++++++++++-- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 10 ++- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_process.c | 11 +++- src/qemu/qemu_validate.c | 1 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../graphics-dbus-address.args | 31 +++++++++ .../graphics-dbus-address.xml | 34 ++++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 36 ++++++++++ tests/qemuxml2argvdata/graphics-dbus.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus.xml | 34 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ .../graphics-dbus-address.xml | 39 +++++++++++ .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 39 +++++++++++ tests/qemuxml2xmloutdata/graphics-dbus.xml | 39 +++++++++++ tests/qemuxml2xmltest.c | 10 +++ 27 files changed, 523 insertions(+), 8 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-p2p.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus.xml
We like to separate changes to public structures (like XML and/or APIs) and changes to drviers. IOW, this should be split into two patches, in the first you include all XML related changes (parsing, formatting) can even introduce those .args files so that xml2xmltest can check XML parsing & formatting. In here, you can put 'case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:' just next to 'VIR_DOMAIN_GRAPHICS_TYPE_LAST' so that using dbus type errors out. And then in the second patch you provide the qemu implementation. Oh, and don't forget to document your changes in docs/formatdomain.rst so that users know there's a new type and what attributes they can set.
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a221ff6295c0..ae4d5682229c 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/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>
Or use "filePath" type. They are the same.
+ <!-- An ipv4 "dotted quad" address --> <define name="ipv4Addr"> <data type="string"> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f01b7a64704b..1dba199db7ec 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3996,6 +3996,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/conf/domain_conf.c b/src/conf/domain_conf.c index da0c64b46009..8a2f3c4115e0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -911,6 +911,7 @@ VIR_ENUM_IMPL(virDomainGraphics, "desktop", "spice", "egl-headless", + "dbus", );
VIR_ENUM_IMPL(virDomainGraphicsListen, @@ -1891,6 +1892,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; } @@ -12896,6 +12902,38 @@ 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)
Any reason for not passing def->data.dbus.p2p directly?
+ return -1; + def->data.dbus.p2p = p2p == VIR_TRISTATE_BOOL_YES; + + def->data.dbus.address = virXMLPropString(node, "address");
So here p2p and address attributes are parsed, but later when generating cmd line you treat them as mutually exclusive. I think we could have a validate callback that does the exclusivity check. virDomainGraphicsDefValidate() looks like a good candidate.
+ + 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) { @@ -12970,6 +13008,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; } @@ -26661,6 +26703,15 @@ 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.rendernode) + break; + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -31231,6 +31282,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; } @@ -31246,7 +31302,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; @@ -31265,6 +31322,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: @@ -31286,6 +31346,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 ab9a7d66f86d..42fe583418a6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1733,6 +1733,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; @@ -1916,6 +1917,12 @@ struct _virDomainGraphicsDef { struct { char *rendernode; } egl_headless; + struct { + bool p2p; + char *address; + char *rendernode; + virTristateBool gl; + } 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/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 9f0739e1faff..b19009f270aa 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1551,6 +1551,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/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c1579a2bf4b3..2c3a81eda245 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6021,6 +6021,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 483041f584d8..1960861015c6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8601,7 +8601,46 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
static int -qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, +qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, + virDomainObj *vm, + virCommand *cmd, + virDomainGraphicsDef *graphics) +{ + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + + if (!graphics->data.dbus.p2p && !graphics->data.dbus.address) { + graphics->data.dbus.address = qemuDBusGetAddress(driver, vm);
Ideally, building a cmd line wouldn't change domain definition (my dream is to have qemuBuildCommandLine() accept 'const virDomainDef *' one day), but we are far from it. So if you think this could be moved somewhere under qemuProcessSetupGraphics() (trainsitionally even) then you'll make me happy :-)
+ QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted = true; + } + + virBufferAddLit(&opt, "dbus"); + + if (graphics->data.dbus.p2p) { + virBufferAddLit(&opt, ",p2p=on"); + } else { + virBufferAddLit(&opt, ",addr="); + virQEMUBuildBufferEscapeComma(&opt, graphics->data.dbus.address); + }
This is the exclusivity I had on mind above.
+ 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(virQEMUDriver *driver, + virDomainObj *vm, + virQEMUDriverConfig *cfg, virCommand *cmd, virDomainDef *def, virQEMUCaps *qemuCaps) @@ -8635,6 +8674,12 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, graphics) < 0) return -1;
+ break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (qemuBuildGraphicsDBusCommandLine(driver, vm, cmd, + graphics) < 0) + return -1; + break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -10363,6 +10408,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 @@ -10407,6 +10453,9 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++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: @@ -10414,10 +10463,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; }
@@ -10789,7 +10838,7 @@ qemuBuildCommandLine(virQEMUDriver *driver, if (qemuBuildAudioCommandLine(cmd, def, qemuCaps) < 0) return NULL;
- if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0) + if (qemuBuildGraphicsCommandLine(driver, vm, cfg, cmd, def, qemuCaps) < 0) return NULL;
if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index fb203bc83085..b027443ca346 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3453,6 +3453,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 7d13ae9754b4..d7cf7d43b267 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15741,12 +15741,15 @@ qemuDomainOpenGraphics(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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: @@ -15810,12 +15813,15 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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 328b06245f42..6037b4b92c34 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4451,6 +4451,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 4ca9b100a802..2a413d602a10 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4784,6 +4784,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; } @@ -4823,6 +4824,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; } @@ -4979,6 +4981,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; } @@ -5047,11 +5050,16 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef *graphics, return 0;
rendernode = &graphics->data.spice.rendernode; - } else { + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) return 0;
rendernode = &graphics->data.egl_headless.rendernode; + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS) { + rendernode = &graphics->data.dbus.rendernode; + } else { + g_warn_if_reached(); + return -1;
Right, in such cases we tend to switch if-else to switch() and call virReportEnumRangeError(); or just 'break' (we are inconsistent, yes) or do nothing at all.
}
if (!(*rendernode = virHostGetDRMRenderNode())) @@ -5284,6 +5292,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 397eea5edeaa..23c7e9f94cd0 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4168,6 +4168,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 d3540acd84a8..2c48bbc5e812 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -3446,6 +3446,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_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index df8bdae10227..ce3577f582d4 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -154,6 +154,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_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 4d1210565968..c553d8d0b245 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -160,6 +160,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_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index c382ec462ca6..214285c958bc 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -154,6 +154,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.args b/tests/qemuxml2argvdata/graphics-dbus-address.args new file mode 100644 index 000000000000..12a5fadca782 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,addr=unix:path=/tmp/foo \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-address.xml b/tests/qemuxml2argvdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..958e6a6a4059 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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>
I guess this <disk/> can be dropped as the test doesn't aim on testing it anyway.
+ <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' address='unix:path=/tmp/foo'/>
This is weird. adress is set, p2p is not but ...
+ <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.args b/tests/qemuxml2argvdata/graphics-dbus-p2p.args new file mode 100644 index 000000000000..c3b1cc0c12cf --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,p2p=on,gl=on,rendernode=/dev/dri/foo \
... here p2p is set and address is not.
+-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.xml b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml new file mode 100644 index 000000000000..80c2e42b4dc8 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml @@ -0,0 +1,36 @@ +<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'/> + <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'> + <gl enable='yes' rendernode='/dev/dri/foo'/> + </graphics> + <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus.args b/tests/qemuxml2argvdata/graphics-dbus.args new file mode 100644 index 000000000000..7149e0177671 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-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/qemuxml2argvdata/graphics-dbus.xml b/tests/qemuxml2argvdata/graphics-dbus.xml new file mode 100644 index 000000000000..ab0dcf1187af --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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'/> + <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'/> + <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 a0498a0d9201..4345ab47e053 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1518,6 +1518,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"); diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-address.xml b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..8ead97baacd4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml
This file is not that much different to its image (tests/qemuxml2argvdata/graphics-dbus-address.xml). What we tend to do in theses cases is to make xml2xmlout/ file a symlink to the xml2argv file. It allows us to bring the size of tests/ down.
@@ -0,0 +1,39 @@ +<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' address='unix:path=/tmp/foo'/> + <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>
This is where I stop my review. I skimmed throuh the rest of patches and if you apply my comments to them too they will look okay. Michal

Hi On Mon, Nov 29, 2021 at 9:20 PM Michal Prívozník <mprivozn@redhat.com> wrote:
On 11/5/21 11:51, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Without any extra option, libvirt will start and tell QEMU to connect to the private VM bus.
Instead, a D-Bus "address" to connect to can be specified. Or the p2p mode enabled.
D-Bus display best works with GL & a rendernode, which can be specified with <gl> child element.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/basictypes.rng | 7 ++ docs/schemas/domaincommon.rng | 33 ++++++++++ src/conf/domain_conf.c | 65 ++++++++++++++++++- src/conf/domain_conf.h | 7 ++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_command.c | 57 ++++++++++++++-- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 10 ++- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_process.c | 11 +++- src/qemu/qemu_validate.c | 1 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../graphics-dbus-address.args | 31 +++++++++ .../graphics-dbus-address.xml | 34 ++++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 36 ++++++++++ tests/qemuxml2argvdata/graphics-dbus.args | 31 +++++++++ tests/qemuxml2argvdata/graphics-dbus.xml | 34 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ .../graphics-dbus-address.xml | 39 +++++++++++ .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 39 +++++++++++ tests/qemuxml2xmloutdata/graphics-dbus.xml | 39 +++++++++++ tests/qemuxml2xmltest.c | 10 +++ 27 files changed, 523 insertions(+), 8 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-p2p.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2argvdata/graphics-dbus.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus.xml
We like to separate changes to public structures (like XML and/or APIs) and changes to drviers. IOW, this should be split into two patches, in the first you include all XML related changes (parsing, formatting) can even introduce those .args files so that xml2xmltest can check XML parsing & formatting. In here, you can put 'case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:' just next to 'VIR_DOMAIN_GRAPHICS_TYPE_LAST' so that using dbus type errors out. And then in the second patch you provide the qemu implementation.
Ok
Oh, and don't forget to document your changes in docs/formatdomain.rst so that users know there's a new type and what attributes they can set.
It's the last patch. It can be squashed.
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a221ff6295c0..ae4d5682229c 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/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>
Or use "filePath" type. They are the same.
I would rather have a specific type. Some day, it could receive a better pattern.
+ <!-- An ipv4 "dotted quad" address --> <define name="ipv4Addr"> <data type="string"> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f01b7a64704b..1dba199db7ec 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3996,6 +3996,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/conf/domain_conf.c b/src/conf/domain_conf.c index da0c64b46009..8a2f3c4115e0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -911,6 +911,7 @@ VIR_ENUM_IMPL(virDomainGraphics, "desktop", "spice", "egl-headless", + "dbus", );
VIR_ENUM_IMPL(virDomainGraphicsListen, @@ -1891,6 +1892,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; } @@ -12896,6 +12902,38 @@ 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)
Any reason for not passing def->data.dbus.p2p directly?
It's not a tristate. There are other similar cases in the file. We could make it if it helps. (?)
+ return -1; + def->data.dbus.p2p = p2p == VIR_TRISTATE_BOOL_YES; + + def->data.dbus.address = virXMLPropString(node, "address");
So here p2p and address attributes are parsed, but later when generating cmd line you treat them as mutually exclusive. I think we could have a validate callback that does the exclusivity check. virDomainGraphicsDefValidate() looks like a good candidate.
Ack
+ + 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) { @@ -12970,6 +13008,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; } @@ -26661,6 +26703,15 @@ 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.rendernode) + break; + break; case VIR_DOMAIN_GRAPHICS_TYPE_LAST: break; } @@ -31231,6 +31282,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; } @@ -31246,7 +31302,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; @@ -31265,6 +31322,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: @@ -31286,6 +31346,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 ab9a7d66f86d..42fe583418a6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1733,6 +1733,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; @@ -1916,6 +1917,12 @@ struct _virDomainGraphicsDef { struct { char *rendernode; } egl_headless; + struct { + bool p2p; + char *address; + char *rendernode; + virTristateBool gl; + } 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/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 9f0739e1faff..b19009f270aa 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1551,6 +1551,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/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c1579a2bf4b3..2c3a81eda245 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6021,6 +6021,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 483041f584d8..1960861015c6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8601,7 +8601,46 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
static int -qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, +qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, + virDomainObj *vm, + virCommand *cmd, + virDomainGraphicsDef *graphics) +{ + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + + if (!graphics->data.dbus.p2p && !graphics->data.dbus.address) { + graphics->data.dbus.address = qemuDBusGetAddress(driver, vm);
Ideally, building a cmd line wouldn't change domain definition (my dream is to have qemuBuildCommandLine() accept 'const virDomainDef *' one day), but we are far from it. So if you think this could be moved somewhere under qemuProcessSetupGraphics() (trainsitionally even) then you'll make me happy :-)
ok
+ QEMU_DOMAIN_PRIVATE(vm)->dbusDaemonWanted = true; + } + + virBufferAddLit(&opt, "dbus"); + + if (graphics->data.dbus.p2p) { + virBufferAddLit(&opt, ",p2p=on"); + } else { + virBufferAddLit(&opt, ",addr="); + virQEMUBuildBufferEscapeComma(&opt, graphics->data.dbus.address); + }
This is the exclusivity I had on mind above.
+ 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(virQEMUDriver *driver, + virDomainObj *vm, + virQEMUDriverConfig *cfg, virCommand *cmd, virDomainDef *def, virQEMUCaps *qemuCaps) @@ -8635,6 +8674,12 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg, graphics) < 0) return -1;
+ break; + case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: + if (qemuBuildGraphicsDBusCommandLine(driver, vm, cmd, + graphics) < 0) + return -1; + break; case VIR_DOMAIN_GRAPHICS_TYPE_RDP: case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: @@ -10363,6 +10408,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 @@ -10407,6 +10453,9 @@ qemuBuildCommandLineValidate(virQEMUDriver *driver, case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++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: @@ -10414,10 +10463,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; }
@@ -10789,7 +10838,7 @@ qemuBuildCommandLine(virQEMUDriver *driver, if (qemuBuildAudioCommandLine(cmd, def, qemuCaps) < 0) return NULL;
- if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0) + if (qemuBuildGraphicsCommandLine(driver, vm, cfg, cmd, def, qemuCaps) < 0) return NULL;
if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index fb203bc83085..b027443ca346 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3453,6 +3453,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 7d13ae9754b4..d7cf7d43b267 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -15741,12 +15741,15 @@ qemuDomainOpenGraphics(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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: @@ -15810,12 +15813,15 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom, case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: 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: 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 328b06245f42..6037b4b92c34 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4451,6 +4451,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 4ca9b100a802..2a413d602a10 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4784,6 +4784,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; } @@ -4823,6 +4824,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; } @@ -4979,6 +4981,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; } @@ -5047,11 +5050,16 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef *graphics, return 0;
rendernode = &graphics->data.spice.rendernode; - } else { + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) return 0;
rendernode = &graphics->data.egl_headless.rendernode; + } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS) { + rendernode = &graphics->data.dbus.rendernode; + } else { + g_warn_if_reached(); + return -1;
Right, in such cases we tend to switch if-else to switch() and call virReportEnumRangeError(); or just 'break' (we are inconsistent, yes) or do nothing at all.
ok
}
if (!(*rendernode = virHostGetDRMRenderNode())) @@ -5284,6 +5292,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 397eea5edeaa..23c7e9f94cd0 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4168,6 +4168,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 d3540acd84a8..2c48bbc5e812 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -3446,6 +3446,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_6.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml index df8bdae10227..ce3577f582d4 100644 --- a/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-q35.x86_64.xml @@ -154,6 +154,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_6.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml index 4d1210565968..c553d8d0b245 100644 --- a/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0-tcg.x86_64.xml @@ -160,6 +160,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_6.2.0.x86_64.xml b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml index c382ec462ca6..214285c958bc 100644 --- a/tests/domaincapsdata/qemu_6.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.x86_64.xml @@ -154,6 +154,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.args b/tests/qemuxml2argvdata/graphics-dbus-address.args new file mode 100644 index 000000000000..12a5fadca782 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,addr=unix:path=/tmp/foo \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-address.xml b/tests/qemuxml2argvdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..958e6a6a4059 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-address.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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>
I guess this <disk/> can be dropped as the test doesn't aim on testing it anyway.
yes
+ <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' address='unix:path=/tmp/foo'/>
This is weird. adress is set, p2p is not but ...
this is -address test
+ <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.args b/tests/qemuxml2argvdata/graphics-dbus-p2p.args new file mode 100644 index 000000000000..c3b1cc0c12cf --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,p2p=on,gl=on,rendernode=/dev/dri/foo \
... here p2p is set and address is not.
And this is p2p test. Seems ok to me.
+-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-p2p.xml b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml new file mode 100644 index 000000000000..80c2e42b4dc8 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-p2p.xml @@ -0,0 +1,36 @@ +<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'/> + <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'> + <gl enable='yes' rendernode='/dev/dri/foo'/> + </graphics> + <video> + <model type='cirrus' vram='16384' heads='1'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/graphics-dbus.args b/tests/qemuxml2argvdata/graphics-dbus.args new file mode 100644 index 000000000000..7149e0177671 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.args @@ -0,0 +1,31 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-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/qemuxml2argvdata/graphics-dbus.xml b/tests/qemuxml2argvdata/graphics-dbus.xml new file mode 100644 index 000000000000..ab0dcf1187af --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>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'/> + <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'/> + <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 a0498a0d9201..4345ab47e053 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1518,6 +1518,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"); diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-address.xml b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml new file mode 100644 index 000000000000..8ead97baacd4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-address.xml
This file is not that much different to its image (tests/qemuxml2argvdata/graphics-dbus-address.xml). What we tend to do in theses cases is to make xml2xmlout/ file a symlink to the xml2argv file. It allows us to bring the size of tests/ down.
ok
@@ -0,0 +1,39 @@ +<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' address='unix:path=/tmp/foo'/> + <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>
This is where I stop my review. I skimmed throuh the rest of patches and if you apply my comments to them too they will look okay.
Michal

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/domaincommon.rng | 29 +++++++++++++ src/bhyve/bhyve_command.c | 1 + src/conf/domain_conf.c | 16 +++++++ src/conf/domain_conf.h | 2 + src/qemu/qemu_command.c | 17 +++++++- src/qemu/qemu_validate.c | 33 +++++++++++++- .../qemuxml2argvdata/graphics-dbus-audio.args | 32 ++++++++++++++ .../qemuxml2argvdata/graphics-dbus-audio.xml | 40 +++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../graphics-dbus-audio.xml | 43 +++++++++++++++++++ tests/qemuxml2xmltest.c | 4 ++ 11 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-audio.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-audio.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 1dba199db7ec..fcd14162bc9a 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4027,6 +4027,13 @@ </optional> </element> </optional> + <optional> + <element name="audio"> + <attribute name="id"> + <ref name="uint8"/> + </attribute> + </element> + </optional> </interleave> </group> <group> @@ -4839,6 +4846,11 @@ <ref name="audiocommonchild"/> </define> + <define name="audiodbus"> + <ref name="audiocommonattr"/> + <ref name="audiocommonchild"/> + </define> + <define name="audio"> <element name="audio"> <attribute name="id"> @@ -4867,6 +4879,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/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index ab9d3026cc8c..17712c1e6e69 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 8a2f3c4115e0..82f5e44951d5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virDomainAudioType, "sdl", "spice", "file", + "dbus", ); VIR_ENUM_IMPL(virDomainAudioSDLDriver, @@ -3023,6 +3024,7 @@ virDomainAudioDefFree(virDomainAudioDef *def) g_free(def->backend.file.path); break; + case VIR_DOMAIN_AUDIO_TYPE_DBUS: case VIR_DOMAIN_AUDIO_TYPE_LAST: break; } @@ -12930,6 +12932,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; } @@ -13420,6 +13430,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); @@ -25776,6 +25789,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); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 42fe583418a6..6eec4230fab5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1504,6 +1504,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; @@ -1922,6 +1923,7 @@ struct _virDomainGraphicsDef { char *address; char *rendernode; virTristateBool gl; + unsigned int audioId; } dbus; } data; /* nListens, listens, and *port are only useful if type is vnc, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 1960861015c6..20cafa1abb0e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -152,6 +152,7 @@ VIR_ENUM_IMPL(qemuAudioDriver, "sdl", "spice", "wav", + "dbus", ); @@ -8010,6 +8011,9 @@ qemuBuildAudioCommandLineArg(virCommand *cmd, virBufferEscapeString(&buf, ",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); @@ -8205,6 +8209,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); @@ -8603,6 +8610,7 @@ qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED, static int qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, virDomainObj *vm, + virDomainDef *def, virCommand *cmd, virDomainGraphicsDef *graphics) { @@ -8630,6 +8638,13 @@ qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, 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); @@ -8676,7 +8691,7 @@ qemuBuildGraphicsCommandLine(virQEMUDriver *driver, break; case VIR_DOMAIN_GRAPHICS_TYPE_DBUS: - if (qemuBuildGraphicsDBusCommandLine(driver, vm, cmd, + if (qemuBuildGraphicsDBusCommandLine(driver, vm, def, cmd, graphics) < 0) return -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 23c7e9f94cd0..56949775a3e6 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4088,6 +4088,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, @@ -4165,10 +4183,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; } @@ -4415,6 +4438,14 @@ qemuValidateDomainDeviceDefAudio(virDomainAudioDef *audio, case VIR_DOMAIN_AUDIO_TYPE_FILE: 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: default: virReportEnumRangeError(virDomainAudioType, audio->type); diff --git a/tests/qemuxml2argvdata/graphics-dbus-audio.args b/tests/qemuxml2argvdata/graphics-dbus-audio.args new file mode 100644 index 000000000000..83f7d3f6a5a9 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-audio.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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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=off,out.mixing-engine=off \ +-display dbus,p2p=on,audiodev=audio1 \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-audio.xml b/tests/qemuxml2argvdata/graphics-dbus-audio.xml new file mode 100644 index 000000000000..592e3d535d91 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-audio.xml @@ -0,0 +1,40 @@ +<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'/> + <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'> + <audio id='1'/> + </graphics> + <audio id='1' type='dbus'> + <input mixingEngine='no'/> + <output mixingEngine='no'/> + </audio> + <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 4345ab47e053..e5454f03eccf 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1524,6 +1524,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"); diff --git a/tests/qemuxml2xmloutdata/graphics-dbus-audio.xml b/tests/qemuxml2xmloutdata/graphics-dbus-audio.xml new file mode 100644 index 000000000000..16c37a34c6d5 --- /dev/null +++ b/tests/qemuxml2xmloutdata/graphics-dbus-audio.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> + <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' 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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 92d1c02fd3e8..ee3677ec5c38 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -382,6 +382,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.33.0.721.g106298f7f9

From: Marc-André Lureau <marcandre.lureau@redhat.com> This feature requires to setup a "-chardev qemu-vdagent,clipboard=on". "qemu-vdagent" is not a typical chardev that you can connect to another end, so it doesn't map to a <serial> or <channel>. Set it up along with "-display dbus" code instead. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/domaincommon.rng | 8 +++++ src/conf/domain_conf.c | 7 ++++ src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 12 +++++++ .../graphics-dbus-clipboard.args | 32 +++++++++++++++++ .../graphics-dbus-clipboard.xml | 36 +++++++++++++++++++ tests/qemuxml2argvtest.c | 4 +++ 7 files changed, 100 insertions(+) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-clipboard.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-clipboard.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index fcd14162bc9a..a8777acf9ea8 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4034,6 +4034,14 @@ </attribute> </element> </optional> + <optional> + <element name="clipboard"> + <attribute name="copypaste"> + <ref name="virYesNo"/> + </attribute> + <empty/> + </element> + </optional> </interleave> </group> <group> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 82f5e44951d5..e249781ce027 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12940,6 +12940,13 @@ virDomainGraphicsDefParseXMLDBus(virDomainGraphicsDef *def, return -1; } + if ((cur = virXPathNode("./clipboard", ctxt))) { + if (virXMLPropTristateBool(cur, "copypaste", + VIR_XML_PROP_REQUIRED, + &def->data.dbus.copypaste) < 0) + return -1; + } + return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6eec4230fab5..cc81dbd4a9db 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1924,6 +1924,7 @@ struct _virDomainGraphicsDef { char *rendernode; virTristateBool gl; unsigned int audioId; + virTristateBool copypaste; } dbus; } data; /* nListens, listens, and *port are only useful if type is vnc, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 20cafa1abb0e..377e7e6f7623 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8614,6 +8614,7 @@ qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, virCommand *cmd, virDomainGraphicsDef *graphics) { + g_autofree char *charAlias = NULL; g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; if (!graphics->data.dbus.p2p && !graphics->data.dbus.address) { @@ -8648,6 +8649,17 @@ qemuBuildGraphicsDBusCommandLine(virQEMUDriver *driver, virCommandAddArg(cmd, "-display"); virCommandAddArgBuffer(cmd, &opt); + + if (graphics->data.dbus.copypaste == VIR_TRISTATE_BOOL_YES) { + if (!(charAlias = qemuAliasChardevFromDevAlias("qemu-vdagent"))) + return -1; + + virBufferAsprintf(&opt, "qemu-vdagent,id=%s", charAlias); + virBufferAddLit(&opt, ",clipboard=on"); + virCommandAddArg(cmd, "-chardev"); + virCommandAddArgBuffer(cmd, &opt); + } + return 0; } diff --git a/tests/qemuxml2argvdata/graphics-dbus-clipboard.args b/tests/qemuxml2argvdata/graphics-dbus-clipboard.args new file mode 100644 index 000000000000..a2de21f73130 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-clipboard.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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-display dbus,p2p=on \ +-chardev qemu-vdagent,id=charqemu-vdagent,clipboard=on \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-clipboard.xml b/tests/qemuxml2argvdata/graphics-dbus-clipboard.xml new file mode 100644 index 000000000000..e6bf7c6b88a1 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-clipboard.xml @@ -0,0 +1,36 @@ +<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'/> + <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'> + <clipboard copypaste='yes'/> + </graphics> + <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 e5454f03eccf..e1f032fe8a79 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1526,6 +1526,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-clipboard", + QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_DISPLAY_DBUS, + QEMU_CAPS_CHARDEV_VDAGENT); DO_TEST_NOCAPS("input-usbmouse"); DO_TEST_NOCAPS("input-usbtablet"); -- 2.33.0.721.g106298f7f9

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 26 +++++++++++++ src/conf/domain_conf.h | 4 ++ src/conf/domain_validate.c | 32 +++++++++++----- src/qemu/qemu_command.c | 10 +++++ src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_validate.c | 1 + src/security/security_dac.c | 2 + .../graphics-dbus-chardev.args | 33 ++++++++++++++++ .../graphics-dbus-chardev.xml | 38 +++++++++++++++++++ tests/qemuxml2argvtest.c | 4 ++ 11 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-chardev.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a8777acf9ea8..2499b71c59dc 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4506,6 +4506,7 @@ <value>spicevmc</value> <value>spiceport</value> <value>nmdm</value> + <value>dbus</value> </choice> </define> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e249781ce027..1fbbcb33d0ca 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -701,6 +701,7 @@ VIR_ENUM_IMPL(virDomainChr, "spicevmc", "spiceport", "nmdm", + "dbus", ); VIR_ENUM_IMPL(virDomainChrTcpProtocol, @@ -2681,6 +2682,7 @@ virDomainChrSourceDefGetPath(virDomainChrSourceDef *chr) case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: return NULL; } @@ -2724,6 +2726,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); @@ -2778,7 +2784,14 @@ virDomainChrSourceDefCopy(virDomainChrSourceDef *dest, case VIR_DOMAIN_CHR_TYPE_NMDM: dest->data.nmdm.master = g_strdup(src->data.nmdm.master); dest->data.nmdm.slave = g_strdup(src->data.nmdm.slave); + break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + dest->data.spiceport.channel = g_strdup(src->data.spiceport.channel); + break; + case VIR_DOMAIN_CHR_TYPE_DBUS: + dest->data.dbus.channel = g_strdup(src->data.dbus.channel); break; } @@ -2860,6 +2873,11 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: return src->data.spicevmc == tgt->data.spicevmc; + 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: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -11408,6 +11426,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"); @@ -25262,6 +25284,10 @@ virDomainChrSourceDefFormat(virBuffer *buf, 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 cc81dbd4a9db..f70aaa2c1d65 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1209,6 +1209,7 @@ typedef enum { VIR_DOMAIN_CHR_TYPE_SPICEVMC, VIR_DOMAIN_CHR_TYPE_SPICEPORT, VIR_DOMAIN_CHR_TYPE_NMDM, + VIR_DOMAIN_CHR_TYPE_DBUS, VIR_DOMAIN_CHR_TYPE_LAST } virDomainChrType; @@ -1277,6 +1278,9 @@ struct _virDomainChrSourceDef { struct { char *channel; } spiceport; + struct { + char *channel; + } dbus; } data; char *logfile; virTristateSwitch logappend; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 80401cf8c737..176b7f675933 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -832,6 +832,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, @@ -917,17 +935,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/qemu/qemu_command.c b/src/qemu/qemu_command.c index 377e7e6f7623..c369e55969c2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5290,6 +5290,15 @@ qemuBuildChrChardevStr(virLogManager *logManager, dev->data.spiceport.channel); break; + case VIR_DOMAIN_CHR_TYPE_DBUS: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISPLAY_DBUS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("D-Bus chardev is not supported")); + } + virBufferAsprintf(&buf, "dbus,id=%s,name=%s", charAlias, + dev->data.dbus.channel); + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported chardev '%s'"), @@ -8754,6 +8763,7 @@ qemuInterfaceVhostuserConnect(virQEMUDriver *driver, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: + 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 9186d59ca2e5..b9c8e3472ce9 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6715,6 +6715,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: if (virDomainChrTypeToString(chr->type)) { virReportError(VIR_ERR_OPERATION_FAILED, diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 56949775a3e6..64fa0d5dd00b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1953,6 +1953,7 @@ qemuValidateDomainChrSourceDef(const virDomainChrSourceDef *def, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: 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 1733d63410b3..649d86049b61 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1555,6 +1555,7 @@ virSecurityDACSetChardevLabelHelper(virSecurityManager *mgr, case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: break; } @@ -1639,6 +1640,7 @@ virSecurityDACRestoreChardevLabelHelper(virSecurityManager *mgr, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_DBUS: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/qemuxml2argvdata/graphics-dbus-chardev.args b/tests/qemuxml2argvdata/graphics-dbus-chardev.args new file mode 100644 index 000000000000..c2b3718d8315 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-chardev.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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-chardev dbus,id=charserial0,name=org.qemu.console.serial.0 \ +-device isa-serial,chardev=charserial0,id=serial0 \ +-display dbus,p2p=on \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/graphics-dbus-chardev.xml b/tests/qemuxml2argvdata/graphics-dbus-chardev.xml new file mode 100644 index 000000000000..69925d4d0611 --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-chardev.xml @@ -0,0 +1,38 @@ +<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'/> + <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'/> + <serial type="dbus"> + <source channel="org.qemu.console.serial.0"/> + <target port="1"/> + </serial> + <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 e1f032fe8a79..828c0ed77cfe 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1530,6 +1530,10 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DISPLAY_DBUS, QEMU_CAPS_CHARDEV_VDAGENT); + 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.33.0.721.g106298f7f9

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 | 35 ++++++++++++++++++ .../graphics-dbus-usbredir.xml | 36 +++++++++++++++++++ tests/qemuxml2argvtest.c | 4 +++ 4 files changed, 77 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 1fbbcb33d0ca..3385b7960a43 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14556,6 +14556,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 000000000000..71574512fbaa --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-usbredir.args @@ -0,0 +1,35 @@ +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,accel=tcg,usb=off,dump-guest-core=off \ +-m 214 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,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 \ +-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 000000000000..08a6011902fc --- /dev/null +++ b/tests/qemuxml2argvdata/graphics-dbus-usbredir.xml @@ -0,0 +1,36 @@ +<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'/> + <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 828c0ed77cfe..8c1ba2a6427f 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1534,6 +1534,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.33.0.721.g106298f7f9

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- docs/formatdomain.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index eb8c973cf1fc..b477aec65f5c 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6060,6 +6060,30 @@ interaction with the admin. <gl rendernode='/dev/dri/renderD128'/> </graphics> + ``dbus``:since:`Since X.X.X` + 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 (via Spice agent) is set by the ``clipboard`` + element. It is disabled by default, and can be disabled by setting the + ``copypaste`` property to ``yes``. + + 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 -- 2.33.0.721.g106298f7f9

Hi On Fri, Nov 5, 2021 at 2:51 PM <marcandre.lureau@redhat.com> wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
This series implements supports for the upcoming QEMU "-display dbus" support. Development is still in progress, but I hope to land the QEMU support early in 6.3 (last version posted: https://patchew.org/QEMU/20211009210838.2219430-1-marcandre.lureau@redhat.co...).
By default, libvirt will start a private VM bus (sharing and reusing the existing "vmstate" code). A client will need the address of the bus and access to it. Since D-Bus addresses are not URIs unfortunately, I am not sure yet what should "virsh domdisplay" return.
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/. A few dependencies, such as zbus, require an upcoming release. virt-viewer & boxes will need a port to Gtk4 to make use of the shared widget.
Comments welcome, as we can still adjust the QEMU side etc.
No comments? thanks
thanks
Marc-André Lureau (9): qemu: start the D-Bus daemon as needed qemu: add chardev-vdagent capability check qemu: add -display dbus capability check (to update to 6.3) qemu: add -display dbus support qemu: add audio type 'dbus' qemu: add dbus clipboard sharing qemu: add -chardev dbus qemu: add usbredir type 'dbus' docs: document <graphics> type dbus
docs/formatdomain.rst | 24 ++++ docs/schemas/basictypes.rng | 7 ++ docs/schemas/domaincommon.rng | 71 +++++++++++ src/bhyve/bhyve_command.c | 1 + src/conf/domain_conf.c | 116 +++++++++++++++++- src/conf/domain_conf.h | 14 +++ src/conf/domain_validate.c | 32 +++-- src/libxl/libxl_conf.c | 1 + src/qemu/qemu_capabilities.c | 6 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 94 +++++++++++++- src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 10 +- src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_process.c | 15 ++- src/qemu/qemu_validate.c | 33 +++++ src/security/security_dac.c | 2 + src/vmx/vmx.c | 1 + .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 1 + .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 1 + tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 1 + .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.aarch64.xml | 1 + .../caps_6.2.0.x86_64.replies | 10 +- .../caps_6.2.0.x86_64.xml | 2 + .../graphics-dbus-address.args | 31 +++++ .../graphics-dbus-address.xml | 34 +++++ .../qemuxml2argvdata/graphics-dbus-audio.args | 32 +++++ .../qemuxml2argvdata/graphics-dbus-audio.xml | 40 ++++++ .../graphics-dbus-chardev.args | 33 +++++ .../graphics-dbus-chardev.xml | 38 ++++++ .../graphics-dbus-clipboard.args | 32 +++++ .../graphics-dbus-clipboard.xml | 36 ++++++ tests/qemuxml2argvdata/graphics-dbus-p2p.args | 31 +++++ tests/qemuxml2argvdata/graphics-dbus-p2p.xml | 36 ++++++ .../graphics-dbus-usbredir.args | 35 ++++++ .../graphics-dbus-usbredir.xml | 36 ++++++ tests/qemuxml2argvdata/graphics-dbus.args | 31 +++++ tests/qemuxml2argvdata/graphics-dbus.xml | 34 +++++ tests/qemuxml2argvtest.c | 21 ++++ .../graphics-dbus-address.xml | 39 ++++++ .../graphics-dbus-audio.xml | 43 +++++++ .../qemuxml2xmloutdata/graphics-dbus-p2p.xml | 39 ++++++ tests/qemuxml2xmloutdata/graphics-dbus.xml | 39 ++++++ tests/qemuxml2xmltest.c | 14 +++ 47 files changed, 1106 insertions(+), 18 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-clipboard.args create mode 100644 tests/qemuxml2argvdata/graphics-dbus-clipboard.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 100644 tests/qemuxml2xmloutdata/graphics-dbus-address.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-audio.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus-p2p.xml create mode 100644 tests/qemuxml2xmloutdata/graphics-dbus.xml
-- 2.33.0.721.g106298f7f9
participants (4)
-
Marc-André Lureau
-
marcandre.lureau@redhat.com
-
Michal Prívozník
-
Peter Krempa