On 3/22/22 3:47 PM, Jonathon Jongsma 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.
These features are configured with <source/> element.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
docs/formatdomain.rst | 17 +++++++++++
src/conf/domain_conf.c | 49 +++++++++++++++++++++++++++++--
src/conf/domain_conf.h | 7 +++++
src/conf/domain_validate.c | 1 +
src/conf/schemas/domaincommon.rng | 11 +++++++
5 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index d188de4858..e00015d93e 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -6660,6 +6660,23 @@ 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. The ``mouse`` attribute allows absolute mouse
+ events to go through the vdagent rather than using a usb or virito tablet
+ device. The ``clipboard`` attribute 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.
+ :since:`Since 8.2.0`
:anchor:`<a id="elementsCharHostInterface"/>`
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 153954a0b0..3b09b0389f 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:
@@ -11325,6 +11336,16 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDef *def,
def->data.nmdm.slave = virXMLPropString(sources[0], "slave");
break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT:
+ if (virXMLPropTristateSwitch(sources[0], "mouse",
VIR_XML_PROP_NONE,
+ &def->data.qemuVdagent.mouse) < 0)
+ goto error;
+
+ if (virXMLPropTristateSwitch(sources[0], "clipboard",
VIR_XML_PROP_NONE,
+ &def->data.qemuVdagent.clipboard) <
0)
+ goto error;
+ break;
+
case VIR_DOMAIN_CHR_TYPE_LAST:
case VIR_DOMAIN_CHR_TYPE_NULL:
case VIR_DOMAIN_CHR_TYPE_VC:
@@ -12418,6 +12439,7 @@ virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDef *def,
g_autofree char *websocketGenerated = virXMLPropString(node,
"websocketGenerated");
g_autofree char *autoport = virXMLPropString(node, "autoport");
xmlNodePtr audioNode;
+ xmlNodePtr clipboardNode;
VIR_XPATH_NODE_AUTORESTORE(ctxt)
if (virDomainGraphicsListensParseXML(def, node, ctxt, flags) < 0)
@@ -12479,6 +12501,13 @@ virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDef *def,
def->type) < 0)
return -1;
+ if ((clipboardNode = virXPathNode("./clipboard", ctxt))) {
+ if (virXMLPropTristateBool(clipboardNode, "copypaste",
+ VIR_XML_PROP_REQUIRED,
+ &def->data.vnc.copypaste) < 0)
+ return -1;
+ }
+
By the way, I'm not sure how this stuff got into the patch. It was from
an earlier experiment where I was exploring the <graphics> approach that
I mentioned in the cover letter. But it should have been removed.
Also, I'm aware that this patch creates some build warnings when
apparmor is enabled. Will be fixed in next version.
return 0;
}
@@ -24989,6 +25018,20 @@ virDomainChrSourceDefFormat(virBuffer *buf,
/* nada */
break;
+ case VIR_DOMAIN_CHR_TYPE_QEMU_VDAGENT:
+ if (def->data.qemuVdagent.mouse != VIR_TRISTATE_SWITCH_ABSENT ||
+ def->data.qemuVdagent.clipboard != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAddLit(buf, "<source");
+ if (def->data.qemuVdagent.clipboard != VIR_TRISTATE_SWITCH_ABSENT)
+ virBufferEscapeString(buf, " clipboard='%s'",
+
virTristateSwitchTypeToString(def->data.qemuVdagent.clipboard));
+ if (def->data.qemuVdagent.mouse != VIR_TRISTATE_SWITCH_ABSENT)
+ virBufferEscapeString(buf, " mouse='%s'",
+
virTristateSwitchTypeToString(def->data.qemuVdagent.mouse));
+ virBufferAddLit(buf, "/>\n");
+ }
+ break;
+
case VIR_DOMAIN_CHR_TYPE_PTY:
case VIR_DOMAIN_CHR_TYPE_DEV:
case VIR_DOMAIN_CHR_TYPE_FILE:
@@ -25074,7 +25117,6 @@ virDomainChrSourceDefFormat(virBuffer *buf,
virBufferEscapeString(buf, "<source channel='%s'/>\n",
def->data.spiceport.channel);
break;
-
}
if (def->logfile) {
@@ -25204,7 +25246,6 @@ virDomainChrTargetDefFormat(virBuffer *buf,
return 0;
}
-
static int
virDomainChrDefFormat(virBuffer *buf,
virDomainChrDef *def,
@@ -26630,6 +26671,10 @@ virDomainGraphicsDefFormat(virBuffer *buf,
if (def->data.vnc.audioId > 0)
virBufferAsprintf(buf, "<audio id='%d'/>\n",
def->data.vnc.audioId);
+
+ if (def->data.vnc.copypaste)
+ virBufferAsprintf(buf, "<clipboard
copypaste='%s'/>\n",
+ virTristateBoolTypeToString(def->data.vnc.copypaste));
same here
}
if (children) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b69abfa270..888698d226 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;
@@ -1307,6 +1308,10 @@ struct _virDomainChrSourceDef {
struct {
char *channel;
} spiceport;
+ struct {
+ virTristateSwitch mouse;
+ virTristateSwitch clipboard;
+ } qemuVdagent;
} data;
char *logfile;
virTristateSwitch logappend;
@@ -1905,6 +1910,8 @@ struct _virDomainGraphicsDef {
virDomainGraphicsVNCSharePolicy sharePolicy;
virTristateBool powerControl;
unsigned int audioId;
+ virTristateBool copypaste;
+ virTristateBool mousemode;
and here
} vnc;
struct {
char *display;
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 9c1b64a644..fc0da07f98 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -4463,6 +4463,7 @@
<value>spicevmc</value>
<value>spiceport</value>
<value>nmdm</value>
+ <value>qemu-vdagent</value>
</choice>
</define>
@@ -4551,6 +4552,16 @@
<zeroOrMore>
<ref name="devSeclabel"/>
</zeroOrMore>
+ <optional>
+ <attribute name="mouse">
+ <ref name="virOnOff"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="clipboard">
+ <ref name="virOnOff"/>
+ </attribute>
+ </optional>
</element>
</zeroOrMore>
<optional>