[libvirt PATCH v2 0/4] Enable copy/paste for vnc displays

This patch series enables support for the qemu-vdagent character device which enables copy/paste support between guest and client when using vnc graphics. The guest must be configured with something like the following: <channel type='qemu-vdagent'> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> <target type='virtio' name='com.redhat.spice.0'/> </channel> Copy/paste sync requires a vnc client that has support for copy/paste commands. Currently virt-viewer does not work, but the version of tigervnc provided by fedora (executable name 'vncviewer') does work. More details about this device on Gerd's blog: https://www.kraxel.org/blog/2021/05/qemu-cut-paste/ For now I have left the target to be configurable to match the spicevmc channel, although Marc-Andre has suggested to simply hard-code it to the virtio name com.redhat.spice.0 Changes in v2: - change xml syntax to use <clipboard> and <mouse> sub-elements of <source> defined in the same way as they are for the spice display. - fix a build failure when apparmor was enabled - Add another test for when features are turned off Jonathon Jongsma (4): qemu: add capability for qemu-vdagent chardev Rename virDomainGraphicsSpiceMouseMode to virDomainMouseMode conf: add qemu-vdagent channel qemu: add support for qemu-vdagent channel docs/formatdomain.rst | 23 ++++++ src/conf/domain_conf.c | 70 +++++++++++++++++-- src/conf/domain_conf.h | 24 ++++--- src/conf/domain_validate.c | 1 + src/conf/schemas/domaincommon.rng | 51 +++++++++----- src/libvirt_private.syms | 4 +- src/libxl/libxl_conf.c | 8 +-- src/libxl/xen_xl.c | 16 ++--- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 32 +++++++-- src/qemu/qemu_monitor_json.c | 27 +++++++ src/qemu/qemu_process.c | 1 + src/qemu/qemu_validate.c | 9 +++ src/security/security_apparmor.c | 2 + src/security/security_dac.c | 2 + .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.aarch64.xml | 1 + .../caps_6.2.0.x86_64.xml | 1 + .../caps_7.0.0.x86_64.xml | 1 + ...l-qemu-vdagent-features.x86_64-latest.args | 41 +++++++++++ .../channel-qemu-vdagent-features.xml | 37 ++++++++++ .../channel-qemu-vdagent.x86_64-latest.args | 41 +++++++++++ .../qemuxml2argvdata/channel-qemu-vdagent.xml | 37 ++++++++++ tests/qemuxml2argvtest.c | 2 + ...el-qemu-vdagent-features.x86_64-latest.xml | 58 +++++++++++++++ .../channel-qemu-vdagent.x86_64-latest.xml | 58 +++++++++++++++ tests/qemuxml2xmltest.c | 2 + tests/testutilsqemu.c | 1 + 29 files changed, 500 insertions(+), 54 deletions(-) create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml -- 2.35.1

Detect whether qemu supports the qemu-vdagent character device. This enables support for copy/paste with VNC graphics. Signed-off-by: Jonathon Jongsma <jjongsma@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 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + 6 files changed, 7 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 6b4ed08499..f31e7395c3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -669,6 +669,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 425 */ "blockdev.nbd.tls-hostname", /* QEMU_CAPS_BLOCKDEV_NBD_TLS_HOSTNAME */ "memory-backend-file.prealloc-threads", /* QEMU_CAPS_MEMORY_BACKEND_PREALLOC_THREADS */ + "chardev.qemu-vdagent", /* QEMU_CAPS_CHARDEV_QEMU_VDAGENT */ ); @@ -1629,6 +1630,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, { "calc-dirty-rate/arg-type/mode", QEMU_CAPS_DIRTYRATE_MODE }, + { "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_QEMU_VDAGENT }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 948029d60d..f5a9609b8c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -644,6 +644,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 425 */ QEMU_CAPS_BLOCKDEV_NBD_TLS_HOSTNAME, /* tls hostname can be overriden for NBD clients */ QEMU_CAPS_MEMORY_BACKEND_PREALLOC_THREADS, /* -object memory-backend-*.prealloc-threads */ + QEMU_CAPS_CHARDEV_QEMU_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 0b58210335..fceb7dbea6 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='sev-inject-launch-secret'/> <flag name='calc-dirty-rate'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-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 d08b2c0213..6a5c39a0de 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='rbd-encryption'/> <flag name='calc-dirty-rate'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-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 cdf72b9ebf..6f4fa26808 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -242,6 +242,7 @@ <flag name='calc-dirty-rate'/> <flag name='dirtyrate-param.mode'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-vdagent'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 5227e3ee0b..8219347f2a 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -245,6 +245,7 @@ <flag name='dirtyrate-param.mode'/> <flag name='blockdev.nbd.tls-hostname'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-vdagent'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 2.35.1

On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com> wrote:
Detect whether qemu supports the qemu-vdagent character device. This enables support for copy/paste with VNC graphics.
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-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 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + 6 files changed, 7 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 6b4ed08499..f31e7395c3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -669,6 +669,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 425 */ "blockdev.nbd.tls-hostname", /* QEMU_CAPS_BLOCKDEV_NBD_TLS_HOSTNAME */ "memory-backend-file.prealloc-threads", /* QEMU_CAPS_MEMORY_BACKEND_PREALLOC_THREADS */ + "chardev.qemu-vdagent", /* QEMU_CAPS_CHARDEV_QEMU_VDAGENT */ );
@@ -1629,6 +1630,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, { "calc-dirty-rate/arg-type/mode", QEMU_CAPS_DIRTYRATE_MODE }, + { "chardev-add/arg-type/backend/+qemu-vdagent", QEMU_CAPS_CHARDEV_QEMU_VDAGENT }, };
typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 948029d60d..f5a9609b8c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -644,6 +644,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 425 */ QEMU_CAPS_BLOCKDEV_NBD_TLS_HOSTNAME, /* tls hostname can be overriden for NBD clients */ QEMU_CAPS_MEMORY_BACKEND_PREALLOC_THREADS, /* -object memory-backend-*.prealloc-threads */ + QEMU_CAPS_CHARDEV_QEMU_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 0b58210335..fceb7dbea6 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='sev-inject-launch-secret'/> <flag name='calc-dirty-rate'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-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 d08b2c0213..6a5c39a0de 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='rbd-encryption'/> <flag name='calc-dirty-rate'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-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 cdf72b9ebf..6f4fa26808 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -242,6 +242,7 @@ <flag name='calc-dirty-rate'/> <flag name='dirtyrate-param.mode'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-vdagent'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 5227e3ee0b..8219347f2a 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -245,6 +245,7 @@ <flag name='dirtyrate-param.mode'/> <flag name='blockdev.nbd.tls-hostname'/> <flag name='memory-backend-file.prealloc-threads'/> + <flag name='chardev.qemu-vdagent'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 2.35.1

This enumeration will be useful for vnc with the upcoming qemu-vdagent device so make the name more generic. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/conf/domain_conf.c | 8 ++++---- src/conf/domain_conf.h | 14 +++++++------- src/libvirt_private.syms | 4 ++-- src/libxl/libxl_conf.c | 8 ++++---- src/libxl/xen_xl.c | 16 +++++++--------- src/qemu/qemu_command.c | 10 +++++----- 6 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 731139f80f..6f9954638c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -995,8 +995,8 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression, "always", ); -VIR_ENUM_IMPL(virDomainGraphicsSpiceMouseMode, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST, +VIR_ENUM_IMPL(virDomainMouseMode, + VIR_DOMAIN_MOUSE_MODE_LAST, "default", "server", "client", @@ -12727,7 +12727,7 @@ virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDef *def, if ((cur = virXPathNode("./mouse", ctxt))) { if (virXMLPropEnum(cur, "mode", - virDomainGraphicsSpiceMouseModeTypeFromString, + virDomainMouseModeTypeFromString, VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, &def->data.spice.mousemode) < 0) return -1; @@ -26616,7 +26616,7 @@ virDomainGraphicsDefFormat(virBuffer *buf, virDomainGraphicsSpiceStreamingModeTypeToString(def->data.spice.streaming)); if (def->data.spice.mousemode) virBufferAsprintf(buf, "<mouse mode='%s'/>\n", - virDomainGraphicsSpiceMouseModeTypeToString(def->data.spice.mousemode)); + virDomainMouseModeTypeToString(def->data.spice.mousemode)); if (def->data.spice.copypaste) virBufferAsprintf(buf, "<clipboard copypaste='%s'/>\n", virTristateBoolTypeToString(def->data.spice.copypaste)); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 49c964e6e1..2b00099431 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1844,12 +1844,12 @@ typedef enum { } virDomainGraphicsSpiceZlibCompression; typedef enum { - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT = 0, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT, + VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, + VIR_DOMAIN_MOUSE_MODE_SERVER, + VIR_DOMAIN_MOUSE_MODE_CLIENT, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST -} virDomainGraphicsSpiceMouseMode; + VIR_DOMAIN_MOUSE_MODE_LAST +} virDomainMouseMode; typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_DEFAULT = 0, @@ -1927,7 +1927,7 @@ struct _virDomainGraphicsDef { int tlsPort; bool portReserved; bool tlsPortReserved; - virDomainGraphicsSpiceMouseMode mousemode; + virDomainMouseMode mousemode; char *keymap; virDomainGraphicsAuthDef auth; bool autoport; @@ -3990,7 +3990,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); -VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); +VIR_ENUM_DECL(virDomainMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); VIR_ENUM_DECL(virDomainKVM); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 03697d81a8..400adf14b5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -444,8 +444,6 @@ virDomainGraphicsSpiceImageCompressionTypeFromString; virDomainGraphicsSpiceImageCompressionTypeToString; virDomainGraphicsSpiceJpegCompressionTypeFromString; virDomainGraphicsSpiceJpegCompressionTypeToString; -virDomainGraphicsSpiceMouseModeTypeFromString; -virDomainGraphicsSpiceMouseModeTypeToString; virDomainGraphicsSpiceStreamingModeTypeFromString; virDomainGraphicsSpiceStreamingModeTypeToString; virDomainGraphicsSpiceZlibCompressionTypeFromString; @@ -519,6 +517,8 @@ virDomainMemoryModelTypeToString; virDomainMemoryRemove; virDomainMemorySourceTypeFromString; virDomainMemorySourceTypeToString; +virDomainMouseModeTypeFromString; +virDomainMouseModeTypeToString; virDomainNetAllocateActualDevice; virDomainNetAppendIPAddress; virDomainNetARPInterfaces; diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a0fc51c74a..0b4662e6dc 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1645,14 +1645,14 @@ libxlMakeBuildInfoVfb(virPortAllocatorRange *graphicsports, switch (l_vfb->data.spice.mousemode) { /* client mouse mode is default in xl.cfg */ - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, true); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, false); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: break; } diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index 87194ccbd1..6b7f638783 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -361,11 +361,9 @@ xenParseXLSpice(virConf *conf, virDomainDef *def) &val, 0) < 0) goto cleanup; if (val) { - graphics->data.spice.mousemode = - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT; + graphics->data.spice.mousemode = VIR_DOMAIN_MOUSE_MODE_CLIENT; } else { - graphics->data.spice.mousemode = - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER; + graphics->data.spice.mousemode = VIR_DOMAIN_MOUSE_MODE_SERVER; } if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0) @@ -1691,11 +1689,11 @@ xenFormatXLSpice(virConf *conf, virDomainDef *def) if (graphics->data.spice.mousemode) { switch (graphics->data.spice.mousemode) { - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: if (xenConfigSetInt(conf, "spiceagent_mouse", 0) < 0) return -1; break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: if (xenConfigSetInt(conf, "spiceagent_mouse", 1) < 0) return -1; /* @@ -1705,11 +1703,11 @@ xenFormatXLSpice(virConf *conf, virDomainDef *def) if (xenConfigSetInt(conf, "spicevdagent", 1) < 0) return -1; break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: default: - virReportEnumRangeError(virDomainGraphicsSpiceMouseMode, + virReportEnumRangeError(virDomainMouseMode, graphics->data.spice.mousemode); return -1; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8246ab515a..7834aece35 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8377,17 +8377,17 @@ qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfig *cfg, if (graphics->data.spice.mousemode) { switch (graphics->data.spice.mousemode) { - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: virBufferAddLit(&opt, "agent-mouse=off,"); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: virBufferAddLit(&opt, "agent-mouse=on,"); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: default: - virReportEnumRangeError(virDomainGraphicsSpiceMouseMode, + virReportEnumRangeError(virDomainMouseMode, graphics->data.spice.mousemode); return -1; } -- 2.35.1

On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com> wrote:
This enumeration will be useful for vnc with the upcoming qemu-vdagent device so make the name more generic.
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--- src/conf/domain_conf.c | 8 ++++---- src/conf/domain_conf.h | 14 +++++++------- src/libvirt_private.syms | 4 ++-- src/libxl/libxl_conf.c | 8 ++++---- src/libxl/xen_xl.c | 16 +++++++--------- src/qemu/qemu_command.c | 10 +++++----- 6 files changed, 29 insertions(+), 31 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 731139f80f..6f9954638c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -995,8 +995,8 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression, "always", );
-VIR_ENUM_IMPL(virDomainGraphicsSpiceMouseMode, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST, +VIR_ENUM_IMPL(virDomainMouseMode, + VIR_DOMAIN_MOUSE_MODE_LAST, "default", "server", "client", @@ -12727,7 +12727,7 @@ virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDef *def,
if ((cur = virXPathNode("./mouse", ctxt))) { if (virXMLPropEnum(cur, "mode", - virDomainGraphicsSpiceMouseModeTypeFromString, + virDomainMouseModeTypeFromString, VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, &def->data.spice.mousemode) < 0) return -1; @@ -26616,7 +26616,7 @@ virDomainGraphicsDefFormat(virBuffer *buf, virDomainGraphicsSpiceStreamingModeTypeToString(def->data.spice.streaming)); if (def->data.spice.mousemode) virBufferAsprintf(buf, "<mouse mode='%s'/>\n", - virDomainGraphicsSpiceMouseModeTypeToString(def->data.spice.mousemode)); + virDomainMouseModeTypeToString(def->data.spice.mousemode)); if (def->data.spice.copypaste) virBufferAsprintf(buf, "<clipboard copypaste='%s'/>\n", virTristateBoolTypeToString(def->data.spice.copypaste)); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 49c964e6e1..2b00099431 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1844,12 +1844,12 @@ typedef enum { } virDomainGraphicsSpiceZlibCompression;
typedef enum { - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT = 0, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER, - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT, + VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, + VIR_DOMAIN_MOUSE_MODE_SERVER, + VIR_DOMAIN_MOUSE_MODE_CLIENT,
- VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST -} virDomainGraphicsSpiceMouseMode; + VIR_DOMAIN_MOUSE_MODE_LAST +} virDomainMouseMode;
typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_DEFAULT = 0, @@ -1927,7 +1927,7 @@ struct _virDomainGraphicsDef { int tlsPort; bool portReserved; bool tlsPortReserved; - virDomainGraphicsSpiceMouseMode mousemode; + virDomainMouseMode mousemode; char *keymap; virDomainGraphicsAuthDef auth; bool autoport; @@ -3990,7 +3990,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression); VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); -VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); +VIR_ENUM_DECL(virDomainMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); VIR_ENUM_DECL(virDomainKVM); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 03697d81a8..400adf14b5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -444,8 +444,6 @@ virDomainGraphicsSpiceImageCompressionTypeFromString; virDomainGraphicsSpiceImageCompressionTypeToString; virDomainGraphicsSpiceJpegCompressionTypeFromString; virDomainGraphicsSpiceJpegCompressionTypeToString; -virDomainGraphicsSpiceMouseModeTypeFromString; -virDomainGraphicsSpiceMouseModeTypeToString; virDomainGraphicsSpiceStreamingModeTypeFromString; virDomainGraphicsSpiceStreamingModeTypeToString; virDomainGraphicsSpiceZlibCompressionTypeFromString; @@ -519,6 +517,8 @@ virDomainMemoryModelTypeToString; virDomainMemoryRemove; virDomainMemorySourceTypeFromString; virDomainMemorySourceTypeToString; +virDomainMouseModeTypeFromString; +virDomainMouseModeTypeToString; virDomainNetAllocateActualDevice; virDomainNetAppendIPAddress; virDomainNetARPInterfaces; diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a0fc51c74a..0b4662e6dc 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1645,14 +1645,14 @@ libxlMakeBuildInfoVfb(virPortAllocatorRange *graphicsports,
switch (l_vfb->data.spice.mousemode) { /* client mouse mode is default in xl.cfg */ - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, true); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, false); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: break; }
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index 87194ccbd1..6b7f638783 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -361,11 +361,9 @@ xenParseXLSpice(virConf *conf, virDomainDef *def) &val, 0) < 0) goto cleanup; if (val) { - graphics->data.spice.mousemode = - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT; + graphics->data.spice.mousemode = VIR_DOMAIN_MOUSE_MODE_CLIENT; } else { - graphics->data.spice.mousemode = - VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER; + graphics->data.spice.mousemode = VIR_DOMAIN_MOUSE_MODE_SERVER; }
if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0) @@ -1691,11 +1689,11 @@ xenFormatXLSpice(virConf *conf, virDomainDef *def)
if (graphics->data.spice.mousemode) { switch (graphics->data.spice.mousemode) { - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: if (xenConfigSetInt(conf, "spiceagent_mouse", 0) < 0) return -1; break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: if (xenConfigSetInt(conf, "spiceagent_mouse", 1) < 0) return -1; /* @@ -1705,11 +1703,11 @@ xenFormatXLSpice(virConf *conf, virDomainDef *def) if (xenConfigSetInt(conf, "spicevdagent", 1) < 0) return -1; break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: default: - virReportEnumRangeError(virDomainGraphicsSpiceMouseMode, + virReportEnumRangeError(virDomainMouseMode, graphics->data.spice.mousemode); return -1; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8246ab515a..7834aece35 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8377,17 +8377,17 @@ qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfig *cfg,
if (graphics->data.spice.mousemode) { switch (graphics->data.spice.mousemode) { - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER: + case VIR_DOMAIN_MOUSE_MODE_SERVER: virBufferAddLit(&opt, "agent-mouse=off,"); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT: + case VIR_DOMAIN_MOUSE_MODE_CLIENT: virBufferAddLit(&opt, "agent-mouse=on,"); break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: break; - case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST: + case VIR_DOMAIN_MOUSE_MODE_LAST: default: - virReportEnumRangeError(virDomainGraphicsSpiceMouseMode, + virReportEnumRangeError(virDomainMouseMode, graphics->data.spice.mousemode); return -1; } -- 2.35.1

Add the ability to configure a qemu-vdagent in guest domains. This device is similar to the spice vdagent channel except that qemu handles the spice-vdagent protocol messages itself rather than routing them over a spice protocol channel. The qemu-vdagent device has two notable configuration options which determine whether qemu will handle particular vdagent features: 'clipboard' and 'mouse'. The 'clipboard' option allows qemu to synchronize its internal clipboard manager with the guest clipboard, which enables client<->guest clipboard synchronization for non-spice guests such as vnc. The 'mouse' option allows absolute mouse positioning to be sent over the vdagent channel rather than using a usb or virtio tablet device. Sample configuration: <channel type='qemu-vdagent'> <target type='virtio' name='com.redhat.spice.0'/> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> </channel> Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- docs/formatdomain.rst | 23 ++++++++++++ src/conf/domain_conf.c | 62 ++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 20 ++++++---- src/conf/domain_validate.c | 1 + src/conf/schemas/domaincommon.rng | 51 ++++++++++++++++--------- src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_process.c | 1 + src/qemu/qemu_validate.c | 1 + src/security/security_apparmor.c | 2 + src/security/security_dac.c | 2 + tests/testutilsqemu.c | 1 + 12 files changed, 140 insertions(+), 28 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index e492532004..75339c2fda 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6662,6 +6662,29 @@ types have different ``target`` attributes. ``name='com.redhat.spice.0'``. The optional ``address`` element can tie the channel to a particular ``type='virtio-serial'`` controller. :since:`Since 0.8.8` +``qemu-vdagent`` + Paravirtualized qemu vdagent channel. This channel implements the SPICE + vdagent protocol, but is handled internally by qemu and therefore does not + require a SPICE graphics device. Like the spicevmc channel, the ``target`` + element must be present, with attribute ``type='virtio'``; an optional + attribute ``name`` controls how the guest will have access to the channel, + and defaults to ``name='com.redhat.spice.0'``. The optional ``address`` + element can tie the channel to a particular ``type='virtio-serial'`` + controller. Certain vdagent protocol features can by enabled or disabled + using the ``source`` element. + + Copy & Paste functionality is set by the ``clipboard`` element. It is + disabled by default, and can be enabled by setting the ``copypaste`` + property to ``yes``. This allows the guest's clipboard to be synchronized + with the qemu clipboard manager. This can enable copy and paste between a + guest and a client when using a VNC `graphics device <#elementsGraphics>`__ + (when using a VNC client that supports the copy/paste feature) or other + graphics types that support the qemu clipboard manager. + + Mouse mode is set by the ``mouse`` element, setting its ``mode`` attribute + to one of ``server`` or ``client``. If no mode is specified, the qemu + default will be used (client mode). + :since:`Since 8.2.0` :anchor:`<a id="elementsCharHostInterface"/>` diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6f9954638c..3b97de89f4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -713,6 +713,7 @@ VIR_ENUM_IMPL(virDomainChr, "spicevmc", "spiceport", "nmdm", + "qemu-vdagent", ); VIR_ENUM_IMPL(virDomainChrTcpProtocol, @@ -2698,6 +2699,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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: return NULL; } @@ -2807,6 +2809,11 @@ virDomainChrSourceDefCopy(virDomainChrSourceDef *dest, dest->data.spiceport.channel = g_strdup(src->data.spiceport.channel); break; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + dest->data.qemuVdagent.clipboard = src->data.qemuVdagent.clipboard; + dest->data.qemuVdagent.mouse = src->data.qemuVdagent.mouse; + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -2888,6 +2895,10 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: return src->data.spicevmc == tgt->data.spicevmc; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + return src->data.qemuVdagent.clipboard == tgt->data.qemuVdagent.clipboard && + src->data.qemuVdagent.mouse == tgt->data.qemuVdagent.mouse; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -11244,6 +11255,33 @@ virDomainChrSourceDefParseLog(virDomainChrSourceDef *def, } +static int +virDomainChrSourceDefParseQemuVdagent(virDomainChrSourceDef *def, + xmlNodePtr source, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr cur; + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = source; + if ((cur = virXPathNode("./clipboard", ctxt))) { + if (virXMLPropTristateBool(cur, "copypaste", + VIR_XML_PROP_REQUIRED, + &def->data.qemuVdagent.clipboard) < 0) + return -1; + } + if ((cur = virXPathNode("./mouse", ctxt))) { + if (virXMLPropEnum(cur, "mode", + virDomainMouseModeTypeFromString, + VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, + &def->data.qemuVdagent.mouse) < 0) + return -1; + } + + return 0; +} + + /* Parse the source half of the XML definition for a character device, * where node is the first element of node->children of the parent * element. def->type must already be valid. @@ -11325,6 +11363,12 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDef *def, def->data.nmdm.slave = virXMLPropString(sources[0], "slave"); break; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (virDomainChrSourceDefParseQemuVdagent(def, sources[0], ctxt) < 0) + goto error; + + break; + case VIR_DOMAIN_CHR_TYPE_LAST: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -24996,6 +25040,22 @@ virDomainChrSourceDefFormat(virBuffer *buf, /* nada */ break; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (def->data.qemuVdagent.mouse != VIR_DOMAIN_MOUSE_MODE_DEFAULT || + def->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) { + virBufferAddLit(buf, "<source>\n"); + virBufferAdjustIndent(buf, 2); + if (def->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) + virBufferEscapeString(buf, "<clipboard copypaste='%s'/>\n", + virTristateBoolTypeToString(def->data.qemuVdagent.clipboard)); + if (def->data.qemuVdagent.mouse != VIR_DOMAIN_MOUSE_MODE_DEFAULT) + virBufferEscapeString(buf, "<mouse mode='%s'/>\n", + virDomainMouseModeTypeToString(def->data.qemuVdagent.mouse)); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</source>\n"); + } + break; + case VIR_DOMAIN_CHR_TYPE_PTY: case VIR_DOMAIN_CHR_TYPE_DEV: case VIR_DOMAIN_CHR_TYPE_FILE: @@ -25081,7 +25141,6 @@ virDomainChrSourceDefFormat(virBuffer *buf, virBufferEscapeString(buf, "<source channel='%s'/>\n", def->data.spiceport.channel); break; - } if (def->logfile) { @@ -25211,7 +25270,6 @@ virDomainChrTargetDefFormat(virBuffer *buf, return 0; } - static int virDomainChrDefFormat(virBuffer *buf, virDomainChrDef *def, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2b00099431..484fc08f81 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1239,6 +1239,7 @@ typedef enum { VIR_DOMAIN_CHR_TYPE_SPICEVMC, VIR_DOMAIN_CHR_TYPE_SPICEPORT, VIR_DOMAIN_CHR_TYPE_NMDM, + VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT, VIR_DOMAIN_CHR_TYPE_LAST } virDomainChrType; @@ -1266,6 +1267,13 @@ struct _virDomainChrSourceReconnectDef { unsigned int timeout; }; +typedef enum { + VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, + VIR_DOMAIN_MOUSE_MODE_SERVER, + VIR_DOMAIN_MOUSE_MODE_CLIENT, + + VIR_DOMAIN_MOUSE_MODE_LAST +} virDomainMouseMode; /* The host side information for a character device. */ struct _virDomainChrSourceDef { @@ -1307,6 +1315,10 @@ struct _virDomainChrSourceDef { struct { char *channel; } spiceport; + struct { + virDomainMouseMode mouse; + virTristateBool clipboard; + } qemuVdagent; } data; char *logfile; virTristateSwitch logappend; @@ -1843,14 +1855,6 @@ typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST } virDomainGraphicsSpiceZlibCompression; -typedef enum { - VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, - VIR_DOMAIN_MOUSE_MODE_SERVER, - VIR_DOMAIN_MOUSE_MODE_CLIENT, - - VIR_DOMAIN_MOUSE_MODE_LAST -} virDomainMouseMode; - typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_DEFAULT = 0, VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_FILTER, diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index d6869e8fd8..c0eb2490a8 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -849,6 +849,7 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *src_def, case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 34bccee2f5..60aad8cabe 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -3965,23 +3965,10 @@ </element> </optional> <optional> - <element name="clipboard"> - <attribute name="copypaste"> - <ref name="virYesNo"/> - </attribute> - <empty/> - </element> + <ref name="clipboard"/> </optional> <optional> - <element name="mouse"> - <attribute name="mode"> - <choice> - <value>server</value> - <value>client</value> - </choice> - </attribute> - <empty/> - </element> + <ref name="mousemode"/> </optional> <optional> <element name="filetransfer"> @@ -4070,6 +4057,25 @@ </element> </define> + <define name="clipboard"> + <element name="clipboard"> + <attribute name="copypaste"> + <ref name="virYesNo"/> + </attribute> + <empty/> + </element> + </define> + <define name="mousemode"> + <element name="mouse"> + <attribute name="mode"> + <choice> + <value>server</value> + <value>client</value> + </choice> + </attribute> + <empty/> + </element> + </define> <define name="listenElements"> <zeroOrMore> <element name="listen"> @@ -4470,6 +4476,7 @@ <value>spicevmc</value> <value>spiceport</value> <value>nmdm</value> + <value>qemu-vdagent</value> </choice> </define> @@ -4555,9 +4562,17 @@ <optional> <ref name="reconnect"/> </optional> - <zeroOrMore> - <ref name="devSeclabel"/> - </zeroOrMore> + <interleave> + <zeroOrMore> + <ref name="devSeclabel"/> + </zeroOrMore> + <optional> + <ref name="clipboard"/> + </optional> + <optional> + <ref name="mousemode"/> + </optional> + </interleave> </element> </zeroOrMore> <optional> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7834aece35..1eef9fb6d0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1390,6 +1390,7 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, break; case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: default: break; @@ -1473,6 +1474,7 @@ qemuBuildChardevCommand(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_UDP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break; case VIR_DOMAIN_CHR_TYPE_NMDM: @@ -8613,6 +8615,7 @@ qemuInterfaceVhostuserConnect(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: 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 d5622bd6d9..1ac5377449 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6818,6 +6818,7 @@ qemuMonitorJSONAttachCharDevGetProps(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_QEMU_VDAGENT: virReportError(VIR_ERR_OPERATION_FAILED, _("Hotplug unsupported for char device type '%s'"), virDomainChrTypeToString(chr->type)); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1ed60917ea..423a10738d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6834,6 +6834,7 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break; case VIR_DOMAIN_CHR_TYPE_FILE: { diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e0708b8a76..5ad3d914dc 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1991,6 +1991,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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 8f7acba980..55c0193940 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -1021,6 +1021,7 @@ AppArmorSetChardevLabel(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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: ret = 0; break; @@ -1083,6 +1084,7 @@ AppArmorSetNetdevLabel(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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: ret = 0; break; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index e9e316551e..5b840f4225 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_QEMU_VDAGENT: 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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index fe8908f533..10fdeacaa2 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -1042,6 +1042,7 @@ testQemuPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break; case VIR_DOMAIN_CHR_TYPE_FILE: -- 2.35.1

Hi On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com> wrote:
Add the ability to configure a qemu-vdagent in guest domains. This device is similar to the spice vdagent channel except that qemu handles the spice-vdagent protocol messages itself rather than routing them over a spice protocol channel.
The qemu-vdagent device has two notable configuration options which determine whether qemu will handle particular vdagent features: 'clipboard' and 'mouse'.
The 'clipboard' option allows qemu to synchronize its internal clipboard manager with the guest clipboard, which enables client<->guest clipboard synchronization for non-spice guests such as vnc.
The 'mouse' option allows absolute mouse positioning to be sent over the vdagent channel rather than using a usb or virtio tablet device.
Sample configuration: <channel type='qemu-vdagent'> <target type='virtio' name='com.redhat.spice.0'/> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> </channel>
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
I guess you could have added some domain XML tests here, but the next patch covers it, so Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--- docs/formatdomain.rst | 23 ++++++++++++ src/conf/domain_conf.c | 62 ++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 20 ++++++---- src/conf/domain_validate.c | 1 + src/conf/schemas/domaincommon.rng | 51 ++++++++++++++++--------- src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_process.c | 1 + src/qemu/qemu_validate.c | 1 + src/security/security_apparmor.c | 2 + src/security/security_dac.c | 2 + tests/testutilsqemu.c | 1 + 12 files changed, 140 insertions(+), 28 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index e492532004..75339c2fda 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6662,6 +6662,29 @@ types have different ``target`` attributes. ``name='com.redhat.spice.0'``. The optional ``address`` element can tie the channel to a particular ``type='virtio-serial'`` controller. :since:`Since 0.8.8` +``qemu-vdagent`` + Paravirtualized qemu vdagent channel. This channel implements the SPICE + vdagent protocol, but is handled internally by qemu and therefore does not + require a SPICE graphics device. Like the spicevmc channel, the ``target`` + element must be present, with attribute ``type='virtio'``; an optional + attribute ``name`` controls how the guest will have access to the channel, + and defaults to ``name='com.redhat.spice.0'``. The optional ``address`` + element can tie the channel to a particular ``type='virtio-serial'`` + controller. Certain vdagent protocol features can by enabled or disabled + using the ``source`` element. + + Copy & Paste functionality is set by the ``clipboard`` element. It is + disabled by default, and can be enabled by setting the ``copypaste`` + property to ``yes``. This allows the guest's clipboard to be synchronized + with the qemu clipboard manager. This can enable copy and paste between a + guest and a client when using a VNC `graphics device <#elementsGraphics>`__ + (when using a VNC client that supports the copy/paste feature) or other + graphics types that support the qemu clipboard manager. + + Mouse mode is set by the ``mouse`` element, setting its ``mode`` attribute + to one of ``server`` or ``client``. If no mode is specified, the qemu + default will be used (client mode). + :since:`Since 8.2.0`
:anchor:`<a id="elementsCharHostInterface"/>`
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6f9954638c..3b97de89f4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -713,6 +713,7 @@ VIR_ENUM_IMPL(virDomainChr, "spicevmc", "spiceport", "nmdm", + "qemu-vdagent", );
VIR_ENUM_IMPL(virDomainChrTcpProtocol, @@ -2698,6 +2699,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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: return NULL; } @@ -2807,6 +2809,11 @@ virDomainChrSourceDefCopy(virDomainChrSourceDef *dest, dest->data.spiceport.channel = g_strdup(src->data.spiceport.channel); break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + dest->data.qemuVdagent.clipboard = src->data.qemuVdagent.clipboard; + dest->data.qemuVdagent.mouse = src->data.qemuVdagent.mouse; + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -2888,6 +2895,10 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: return src->data.spicevmc == tgt->data.spicevmc;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + return src->data.qemuVdagent.clipboard == tgt->data.qemuVdagent.clipboard && + src->data.qemuVdagent.mouse == tgt->data.qemuVdagent.mouse; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -11244,6 +11255,33 @@ virDomainChrSourceDefParseLog(virDomainChrSourceDef *def, }
+static int +virDomainChrSourceDefParseQemuVdagent(virDomainChrSourceDef *def, + xmlNodePtr source, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr cur; + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = source; + if ((cur = virXPathNode("./clipboard", ctxt))) { + if (virXMLPropTristateBool(cur, "copypaste", + VIR_XML_PROP_REQUIRED, + &def->data.qemuVdagent.clipboard) < 0) + return -1; + } + if ((cur = virXPathNode("./mouse", ctxt))) { + if (virXMLPropEnum(cur, "mode", + virDomainMouseModeTypeFromString, + VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, + &def->data.qemuVdagent.mouse) < 0) + return -1; + } + + return 0; +} + + /* Parse the source half of the XML definition for a character device, * where node is the first element of node->children of the parent * element. def->type must already be valid. @@ -11325,6 +11363,12 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDef *def, def->data.nmdm.slave = virXMLPropString(sources[0], "slave"); break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (virDomainChrSourceDefParseQemuVdagent(def, sources[0], ctxt) < 0) + goto error; + + break; + case VIR_DOMAIN_CHR_TYPE_LAST: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -24996,6 +25040,22 @@ virDomainChrSourceDefFormat(virBuffer *buf, /* nada */ break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (def->data.qemuVdagent.mouse != VIR_DOMAIN_MOUSE_MODE_DEFAULT || + def->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) { + virBufferAddLit(buf, "<source>\n"); + virBufferAdjustIndent(buf, 2); + if (def->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) + virBufferEscapeString(buf, "<clipboard copypaste='%s'/>\n", + virTristateBoolTypeToString(def->data.qemuVdagent.clipboard)); + if (def->data.qemuVdagent.mouse != VIR_DOMAIN_MOUSE_MODE_DEFAULT) + virBufferEscapeString(buf, "<mouse mode='%s'/>\n", + virDomainMouseModeTypeToString(def->data.qemuVdagent.mouse)); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</source>\n"); + } + break; + case VIR_DOMAIN_CHR_TYPE_PTY: case VIR_DOMAIN_CHR_TYPE_DEV: case VIR_DOMAIN_CHR_TYPE_FILE: @@ -25081,7 +25141,6 @@ virDomainChrSourceDefFormat(virBuffer *buf, virBufferEscapeString(buf, "<source channel='%s'/>\n", def->data.spiceport.channel); break; - }
if (def->logfile) { @@ -25211,7 +25270,6 @@ virDomainChrTargetDefFormat(virBuffer *buf, return 0; }
- static int virDomainChrDefFormat(virBuffer *buf, virDomainChrDef *def, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2b00099431..484fc08f81 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1239,6 +1239,7 @@ typedef enum { VIR_DOMAIN_CHR_TYPE_SPICEVMC, VIR_DOMAIN_CHR_TYPE_SPICEPORT, VIR_DOMAIN_CHR_TYPE_NMDM, + VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT,
VIR_DOMAIN_CHR_TYPE_LAST } virDomainChrType; @@ -1266,6 +1267,13 @@ struct _virDomainChrSourceReconnectDef { unsigned int timeout; };
+typedef enum { + VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, + VIR_DOMAIN_MOUSE_MODE_SERVER, + VIR_DOMAIN_MOUSE_MODE_CLIENT, + + VIR_DOMAIN_MOUSE_MODE_LAST +} virDomainMouseMode;
/* The host side information for a character device. */ struct _virDomainChrSourceDef { @@ -1307,6 +1315,10 @@ struct _virDomainChrSourceDef { struct { char *channel; } spiceport; + struct { + virDomainMouseMode mouse; + virTristateBool clipboard; + } qemuVdagent; } data; char *logfile; virTristateSwitch logappend; @@ -1843,14 +1855,6 @@ typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST } virDomainGraphicsSpiceZlibCompression;
-typedef enum { - VIR_DOMAIN_MOUSE_MODE_DEFAULT = 0, - VIR_DOMAIN_MOUSE_MODE_SERVER, - VIR_DOMAIN_MOUSE_MODE_CLIENT, - - VIR_DOMAIN_MOUSE_MODE_LAST -} virDomainMouseMode; - typedef enum { VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_DEFAULT = 0, VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_FILTER, diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index d6869e8fd8..c0eb2490a8 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -849,6 +849,7 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *src_def, case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 34bccee2f5..60aad8cabe 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -3965,23 +3965,10 @@ </element> </optional> <optional> - <element name="clipboard"> - <attribute name="copypaste"> - <ref name="virYesNo"/> - </attribute> - <empty/> - </element> + <ref name="clipboard"/> </optional> <optional> - <element name="mouse"> - <attribute name="mode"> - <choice> - <value>server</value> - <value>client</value> - </choice> - </attribute> - <empty/> - </element> + <ref name="mousemode"/> </optional> <optional> <element name="filetransfer"> @@ -4070,6 +4057,25 @@ </element> </define>
+ <define name="clipboard"> + <element name="clipboard"> + <attribute name="copypaste"> + <ref name="virYesNo"/> + </attribute> + <empty/> + </element> + </define> + <define name="mousemode"> + <element name="mouse"> + <attribute name="mode"> + <choice> + <value>server</value> + <value>client</value> + </choice> + </attribute> + <empty/> + </element> + </define> <define name="listenElements"> <zeroOrMore> <element name="listen"> @@ -4470,6 +4476,7 @@ <value>spicevmc</value> <value>spiceport</value> <value>nmdm</value> + <value>qemu-vdagent</value> </choice> </define>
@@ -4555,9 +4562,17 @@ <optional> <ref name="reconnect"/> </optional> - <zeroOrMore> - <ref name="devSeclabel"/> - </zeroOrMore> + <interleave> + <zeroOrMore> + <ref name="devSeclabel"/> + </zeroOrMore> + <optional> + <ref name="clipboard"/> + </optional> + <optional> + <ref name="mousemode"/> + </optional> + </interleave> </element> </zeroOrMore> <optional> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7834aece35..1eef9fb6d0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1390,6 +1390,7 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, break;
case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: default: break; @@ -1473,6 +1474,7 @@ qemuBuildChardevCommand(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_UDP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break;
case VIR_DOMAIN_CHR_TYPE_NMDM: @@ -8613,6 +8615,7 @@ qemuInterfaceVhostuserConnect(virCommand *cmd, case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NMDM: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: 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 d5622bd6d9..1ac5377449 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6818,6 +6818,7 @@ qemuMonitorJSONAttachCharDevGetProps(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_QEMU_VDAGENT: virReportError(VIR_ERR_OPERATION_FAILED, _("Hotplug unsupported for char device type '%s'"), virDomainChrTypeToString(chr->type)); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1ed60917ea..423a10738d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6834,6 +6834,7 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break;
case VIR_DOMAIN_CHR_TYPE_FILE: { diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e0708b8a76..5ad3d914dc 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1991,6 +1991,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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 8f7acba980..55c0193940 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -1021,6 +1021,7 @@ AppArmorSetChardevLabel(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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: ret = 0; break; @@ -1083,6 +1084,7 @@ AppArmorSetNetdevLabel(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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: ret = 0; break; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index e9e316551e..5b840f4225 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_QEMU_VDAGENT: 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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index fe8908f533..10fdeacaa2 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -1042,6 +1042,7 @@ testQemuPrepareHostBackendChardevOne(virDomainDeviceDef *dev, case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: break;
case VIR_DOMAIN_CHR_TYPE_FILE: -- 2.35.1

Implement the qemu-vdagent channel introduced in the previous commit. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> --- src/qemu/qemu_command.c | 21 ++++++- src/qemu/qemu_monitor_json.c | 28 ++++++++- src/qemu/qemu_validate.c | 10 +++- ...l-qemu-vdagent-features.x86_64-latest.args | 41 +++++++++++++ .../channel-qemu-vdagent-features.xml | 37 ++++++++++++ .../channel-qemu-vdagent.x86_64-latest.args | 41 +++++++++++++ .../qemuxml2argvdata/channel-qemu-vdagent.xml | 37 ++++++++++++ tests/qemuxml2argvtest.c | 2 + ...el-qemu-vdagent-features.x86_64-latest.xml | 58 +++++++++++++++++++ .../channel-qemu-vdagent.x86_64-latest.xml | 58 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 11 files changed, 332 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 1eef9fb6d0..67921229dd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1389,8 +1389,27 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, dev->data.spiceport.channel); break; - case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + virBufferAsprintf(&buf, "qemu-vdagent,id=%s,name=vdagent", + charAlias); + if (dev->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&buf, ",clipboard=%s", + virTristateSwitchTypeToString(dev->data.qemuVdagent.clipboard)); + switch (dev->data.qemuVdagent.mouse) { + case VIR_DOMAIN_MOUSE_MODE_CLIENT: + virBufferAddLit(&buf, ",mouse=on"); + break; + case VIR_DOMAIN_MOUSE_MODE_SERVER: + virBufferAddLit(&buf, ",mouse=off"); + break; + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_LAST: + default: + break; + } + break; + + case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_LAST: default: break; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 1ac5377449..c7e18073c2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6814,11 +6814,37 @@ qemuMonitorJSONAttachCharDevGetProps(const char *chrID, break; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: { + virTristateBool mouse = VIR_TRISTATE_BOOL_ABSENT; + switch (chr->data.qemuVdagent.mouse) { + case VIR_DOMAIN_MOUSE_MODE_CLIENT: + mouse = VIR_TRISTATE_BOOL_YES; + break; + case VIR_DOMAIN_MOUSE_MODE_SERVER: + mouse = VIR_TRISTATE_BOOL_NO; + break; + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + break; + case VIR_DOMAIN_MOUSE_MODE_LAST: + default: + virReportEnumRangeError(virDomainMouseMode, + chr->data.qemuVdagent.mouse); + return NULL; + } + backendType = "qemu-vdagent"; + + if (virJSONValueObjectAdd(&backendData, + "T:clipboard", chr->data.qemuVdagent.clipboard, + "T:mouse", mouse, + NULL) < 0) + return NULL; + break; + } + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_NMDM: - case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: virReportError(VIR_ERR_OPERATION_FAILED, _("Hotplug unsupported for char device type '%s'"), virDomainChrTypeToString(chr->type)); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 5ad3d914dc..2b60e63a2b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1981,6 +1981,15 @@ qemuValidateDomainChrSourceDef(const virDomainChrSourceDef *def, } break; + case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_QEMU_VDAGENT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("chardev '%s' not supported in this QEMU binary"), + virDomainChrTypeToString(def->type)); + return -1; + } + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_PTY: @@ -1991,7 +2000,6 @@ 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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args new file mode 100644 index 0000000000..651246bdfd --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args @@ -0,0 +1,41 @@ +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-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"virtio-serial-pci","id":"virtio-serial1","bus":"pci.0","addr":"0xa"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-chardev qemu-vdagent,id=charchannel0,name=vdagent,clipboard=on,mouse=on \ +-device '{"driver":"virtserialport","bus":"virtio-serial1.0","nr":3,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-vnc 127.0.0.1:3,audiodev=audio1 \ +-device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml new file mode 100644 index 0000000000..2d8afe3d33 --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <channel type='qemu-vdagent'> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + <source> + <mouse mode='client'/> + <clipboard copypaste='yes'/> + </source> + </channel> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args b/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args new file mode 100644 index 0000000000..0f49b48ca8 --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args @@ -0,0 +1,41 @@ +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-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"virtio-serial-pci","id":"virtio-serial1","bus":"pci.0","addr":"0xa"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-chardev qemu-vdagent,id=charchannel0,name=vdagent,clipboard=off,mouse=off \ +-device '{"driver":"virtserialport","bus":"virtio-serial1.0","nr":3,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-vnc 127.0.0.1:3,audiodev=audio1 \ +-device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent.xml b/tests/qemuxml2argvdata/channel-qemu-vdagent.xml new file mode 100644 index 0000000000..91a62888df --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='x86_64' 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-x86_64</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <channel type='qemu-vdagent'> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + <source> + <clipboard copypaste='no'/> + <mouse mode='server'/> + </source> + </channel> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e7fecb24d3..a20dec1d25 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1726,6 +1726,8 @@ mymain(void) DO_TEST("channel-spicevmc", QEMU_CAPS_SPICE, QEMU_CAPS_DEVICE_CIRRUS_VGA); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); DO_TEST("channel-virtio-default", QEMU_CAPS_SPICE); DO_TEST_NOCAPS("channel-virtio-unix"); diff --git a/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml b/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml new file mode 100644 index 0000000000..66a9135fc7 --- /dev/null +++ b/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml @@ -0,0 +1,58 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='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' model='piix3-uhci'> + <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='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <channel type='qemu-vdagent'> + <source> + <clipboard copypaste='yes'/> + <mouse mode='client'/> + </source> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + </channel> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <audio id='1' type='none'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml b/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml new file mode 100644 index 0000000000..c85acce85d --- /dev/null +++ b/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml @@ -0,0 +1,58 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='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' model='piix3-uhci'> + <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='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <channel type='qemu-vdagent'> + <source> + <clipboard copypaste='no'/> + <mouse mode='server'/> + </source> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + </channel> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <audio id='1' type='none'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 31917e5238..2718b1e365 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1464,6 +1464,8 @@ mymain(void) QEMU_CAPS_DEVICE_PL011, QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); cleanup: if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) -- 2.35.1

Hi, On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com> wrote:
Implement the qemu-vdagent channel introduced in the previous commit.
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
lgtm, Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--- src/qemu/qemu_command.c | 21 ++++++- src/qemu/qemu_monitor_json.c | 28 ++++++++- src/qemu/qemu_validate.c | 10 +++- ...l-qemu-vdagent-features.x86_64-latest.args | 41 +++++++++++++ .../channel-qemu-vdagent-features.xml | 37 ++++++++++++ .../channel-qemu-vdagent.x86_64-latest.args | 41 +++++++++++++ .../qemuxml2argvdata/channel-qemu-vdagent.xml | 37 ++++++++++++ tests/qemuxml2argvtest.c | 2 + ...el-qemu-vdagent-features.x86_64-latest.xml | 58 +++++++++++++++++++ .../channel-qemu-vdagent.x86_64-latest.xml | 58 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 11 files changed, 332 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 1eef9fb6d0..67921229dd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1389,8 +1389,27 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev, dev->data.spiceport.channel); break;
- case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + virBufferAsprintf(&buf, "qemu-vdagent,id=%s,name=vdagent", + charAlias); + if (dev->data.qemuVdagent.clipboard != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&buf, ",clipboard=%s", + virTristateSwitchTypeToString(dev->data.qemuVdagent.clipboard)); + switch (dev->data.qemuVdagent.mouse) { + case VIR_DOMAIN_MOUSE_MODE_CLIENT: + virBufferAddLit(&buf, ",mouse=on"); + break; + case VIR_DOMAIN_MOUSE_MODE_SERVER: + virBufferAddLit(&buf, ",mouse=off"); + break; + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + case VIR_DOMAIN_MOUSE_MODE_LAST: + default: + break; + } + break; + + case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_LAST: default: break; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 1ac5377449..c7e18073c2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6814,11 +6814,37 @@ qemuMonitorJSONAttachCharDevGetProps(const char *chrID,
break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: { + virTristateBool mouse = VIR_TRISTATE_BOOL_ABSENT; + switch (chr->data.qemuVdagent.mouse) { + case VIR_DOMAIN_MOUSE_MODE_CLIENT: + mouse = VIR_TRISTATE_BOOL_YES; + break; + case VIR_DOMAIN_MOUSE_MODE_SERVER: + mouse = VIR_TRISTATE_BOOL_NO; + break; + case VIR_DOMAIN_MOUSE_MODE_DEFAULT: + break; + case VIR_DOMAIN_MOUSE_MODE_LAST: + default: + virReportEnumRangeError(virDomainMouseMode, + chr->data.qemuVdagent.mouse); + return NULL; + } + backendType = "qemu-vdagent"; + + if (virJSONValueObjectAdd(&backendData, + "T:clipboard", chr->data.qemuVdagent.clipboard, + "T:mouse", mouse, + NULL) < 0) + return NULL; + break; + } + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_NMDM: - case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: virReportError(VIR_ERR_OPERATION_FAILED, _("Hotplug unsupported for char device type '%s'"), virDomainChrTypeToString(chr->type)); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 5ad3d914dc..2b60e63a2b 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1981,6 +1981,15 @@ qemuValidateDomainChrSourceDef(const virDomainChrSourceDef *def, } break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_QEMU_VDAGENT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("chardev '%s' not supported in this QEMU binary"), + virDomainChrTypeToString(def->type)); + return -1; + } + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_PTY: @@ -1991,7 +2000,6 @@ 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_QEMU_VDAGENT: case VIR_DOMAIN_CHR_TYPE_LAST: break; } diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args new file mode 100644 index 0000000000..651246bdfd --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args @@ -0,0 +1,41 @@ +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-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"virtio-serial-pci","id":"virtio-serial1","bus":"pci.0","addr":"0xa"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-chardev qemu-vdagent,id=charchannel0,name=vdagent,clipboard=on,mouse=on \ +-device '{"driver":"virtserialport","bus":"virtio-serial1.0","nr":3,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-vnc 127.0.0.1:3,audiodev=audio1 \ +-device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml new file mode 100644 index 0000000000..2d8afe3d33 --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <channel type='qemu-vdagent'> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + <source> + <mouse mode='client'/> + <clipboard copypaste='yes'/> + </source> + </channel> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args b/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args new file mode 100644 index 0000000000..0f49b48ca8 --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args @@ -0,0 +1,41 @@ +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-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"virtio-serial-pci","id":"virtio-serial1","bus":"pci.0","addr":"0xa"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-chardev qemu-vdagent,id=charchannel0,name=vdagent,clipboard=off,mouse=off \ +-device '{"driver":"virtserialport","bus":"virtio-serial1.0","nr":3,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-vnc 127.0.0.1:3,audiodev=audio1 \ +-device '{"driver":"cirrus-vga","id":"video0","bus":"pci.0","addr":"0x2"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/channel-qemu-vdagent.xml b/tests/qemuxml2argvdata/channel-qemu-vdagent.xml new file mode 100644 index 0000000000..91a62888df --- /dev/null +++ b/tests/qemuxml2argvdata/channel-qemu-vdagent.xml @@ -0,0 +1,37 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='x86_64' 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-x86_64</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'/> + <channel type='qemu-vdagent'> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + <source> + <clipboard copypaste='no'/> + <mouse mode='server'/> + </source> + </channel> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e7fecb24d3..a20dec1d25 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1726,6 +1726,8 @@ mymain(void) DO_TEST("channel-spicevmc", QEMU_CAPS_SPICE, QEMU_CAPS_DEVICE_CIRRUS_VGA); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); DO_TEST("channel-virtio-default", QEMU_CAPS_SPICE); DO_TEST_NOCAPS("channel-virtio-unix"); diff --git a/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml b/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml new file mode 100644 index 0000000000..66a9135fc7 --- /dev/null +++ b/tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml @@ -0,0 +1,58 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='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' model='piix3-uhci'> + <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='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <channel type='qemu-vdagent'> + <source> + <clipboard copypaste='yes'/> + <mouse mode='client'/> + </source> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + </channel> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <audio id='1' type='none'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml b/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml new file mode 100644 index 0000000000..c85acce85d --- /dev/null +++ b/tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml @@ -0,0 +1,58 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static' cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='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' model='piix3-uhci'> + <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='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <channel type='qemu-vdagent'> + <source> + <clipboard copypaste='no'/> + <mouse mode='server'/> + </source> + <target type='virtio' name='com.redhat.spice.0'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + </channel> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='5903' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <audio id='1' type='none'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 31917e5238..2718b1e365 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1464,6 +1464,8 @@ mymain(void) QEMU_CAPS_DEVICE_PL011, QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_RANDOM); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); + DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features");
cleanup: if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) -- 2.35.1

Hi Jonathon On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com> wrote:
This patch series enables support for the qemu-vdagent character device which enables copy/paste support between guest and client when using vnc graphics.
The guest must be configured with something like the following:
<channel type='qemu-vdagent'> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> <target type='virtio' name='com.redhat.spice.0'/> </channel>
Copy/paste sync requires a vnc client that has support for copy/paste commands. Currently virt-viewer does not work, but the version of tigervnc provided by fedora (executable name 'vncviewer') does work.
More details about this device on Gerd's blog: https://www.kraxel.org/blog/2021/05/qemu-cut-paste/
For now I have left the target to be configurable to match the spicevmc channel, although Marc-Andre has suggested to simply hard-code it to the virtio name com.redhat.spice.0
Changes in v2: - change xml syntax to use <clipboard> and <mouse> sub-elements of <source> defined in the same way as they are for the spice display. - fix a build failure when apparmor was enabled - Add another test for when features are turned off
Is there anything missing to merge this? thanks
Jonathon Jongsma (4): qemu: add capability for qemu-vdagent chardev Rename virDomainGraphicsSpiceMouseMode to virDomainMouseMode conf: add qemu-vdagent channel qemu: add support for qemu-vdagent channel
docs/formatdomain.rst | 23 ++++++ src/conf/domain_conf.c | 70 +++++++++++++++++-- src/conf/domain_conf.h | 24 ++++--- src/conf/domain_validate.c | 1 + src/conf/schemas/domaincommon.rng | 51 +++++++++----- src/libvirt_private.syms | 4 +- src/libxl/libxl_conf.c | 8 +-- src/libxl/xen_xl.c | 16 ++--- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 32 +++++++-- src/qemu/qemu_monitor_json.c | 27 +++++++ src/qemu/qemu_process.c | 1 + src/qemu/qemu_validate.c | 9 +++ src/security/security_apparmor.c | 2 + src/security/security_dac.c | 2 + .../caps_6.1.0.x86_64.xml | 1 + .../caps_6.2.0.aarch64.xml | 1 + .../caps_6.2.0.x86_64.xml | 1 + .../caps_7.0.0.x86_64.xml | 1 + ...l-qemu-vdagent-features.x86_64-latest.args | 41 +++++++++++ .../channel-qemu-vdagent-features.xml | 37 ++++++++++ .../channel-qemu-vdagent.x86_64-latest.args | 41 +++++++++++ .../qemuxml2argvdata/channel-qemu-vdagent.xml | 37 ++++++++++ tests/qemuxml2argvtest.c | 2 + ...el-qemu-vdagent-features.x86_64-latest.xml | 58 +++++++++++++++ .../channel-qemu-vdagent.x86_64-latest.xml | 58 +++++++++++++++ tests/qemuxml2xmltest.c | 2 + tests/testutilsqemu.c | 1 + 29 files changed, 500 insertions(+), 54 deletions(-) create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent-features.xml create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/channel-qemu-vdagent.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent-features.x86_64-latest.xml create mode 100644 tests/qemuxml2xmloutdata/channel-qemu-vdagent.x86_64-latest.xml
-- 2.35.1
-- Marc-André Lureau

On 5/9/22 11:06 AM, Marc-André Lureau wrote:
Hi Jonathon
On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com <mailto:jjongsma@redhat.com>> wrote:
This patch series enables support for the qemu-vdagent character device which enables copy/paste support between guest and client when using vnc graphics.
The guest must be configured with something like the following:
<channel type='qemu-vdagent'> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> <target type='virtio' name='com.redhat.spice.0'/> </channel>
Copy/paste sync requires a vnc client that has support for copy/paste commands. Currently virt-viewer does not work, but the version of tigervnc provided by fedora (executable name 'vncviewer') does work.
More details about this device on Gerd's blog: https://www.kraxel.org/blog/2021/05/qemu-cut-paste/ <https://www.kraxel.org/blog/2021/05/qemu-cut-paste/>
For now I have left the target to be configurable to match the spicevmc channel, although Marc-Andre has suggested to simply hard-code it to the virtio name com.redhat.spice.0
Changes in v2: - change xml syntax to use <clipboard> and <mouse> sub-elements of <source> defined in the same way as they are for the spice display. - fix a build failure when apparmor was enabled - Add another test for when features are turned off
Is there anything missing to merge this? thanks
Thanks for the ping on this. I suppose I was waiting to see if anybody else had any opinions on whether the virtio name should be configurable or not (which you had recommended against), and then it fell off my radar for a little bit. I will push it tomorrow if nobody speaks up before then. Jonathon

On 5/9/22 20:53, Jonathon Jongsma wrote:
On 5/9/22 11:06 AM, Marc-André Lureau wrote:
Hi Jonathon
On Thu, Mar 24, 2022 at 11:26 PM Jonathon Jongsma <jjongsma@redhat.com <mailto:jjongsma@redhat.com>> wrote:
This patch series enables support for the qemu-vdagent character device which enables copy/paste support between guest and client when using vnc graphics.
The guest must be configured with something like the following:
<channel type='qemu-vdagent'> <source> <clipboard copypaste='yes'/> <mouse mode='client'/> </source> <target type='virtio' name='com.redhat.spice.0'/> </channel>
Copy/paste sync requires a vnc client that has support for copy/paste commands. Currently virt-viewer does not work, but the version of tigervnc provided by fedora (executable name 'vncviewer') does work.
More details about this device on Gerd's blog: https://www.kraxel.org/blog/2021/05/qemu-cut-paste/ <https://www.kraxel.org/blog/2021/05/qemu-cut-paste/>
For now I have left the target to be configurable to match the spicevmc channel, although Marc-Andre has suggested to simply hard-code it to the virtio name com.redhat.spice.0
Changes in v2: - change xml syntax to use <clipboard> and <mouse> sub-elements of <source> defined in the same way as they are for the spice display. - fix a build failure when apparmor was enabled - Add another test for when features are turned off
Is there anything missing to merge this? thanks
Thanks for the ping on this. I suppose I was waiting to see if anybody else had any opinions on whether the virtio name should be configurable or not (which you had recommended against), and then it fell off my radar for a little bit. I will push it tomorrow if nobody speaks up before then.
Yeah, sorry. I had this on my review radar but then got side tracked terribly. Patches look good so go ahead and push. Michal
participants (4)
-
Jonathon Jongsma
-
Marc-André Lureau
-
Marc-André Lureau
-
Michal Prívozník