mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
conf: add qemu-vdagent channel
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> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
f135fdabab
commit
05b09f039e
@ -6608,6 +6608,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"/>`
|
||||
|
||||
|
@ -715,6 +715,7 @@ VIR_ENUM_IMPL(virDomainChr,
|
||||
"spicevmc",
|
||||
"spiceport",
|
||||
"nmdm",
|
||||
"qemu-vdagent",
|
||||
);
|
||||
|
||||
VIR_ENUM_IMPL(virDomainChrTcpProtocol,
|
||||
@ -2702,6 +2703,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;
|
||||
}
|
||||
@ -2811,6 +2813,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:
|
||||
@ -2892,6 +2899,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:
|
||||
@ -11220,6 +11231,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.
|
||||
@ -11301,6 +11339,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,
|
||||
|
@ -1241,6 +1241,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;
|
||||
@ -1268,6 +1269,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 {
|
||||
@ -1309,6 +1317,10 @@ struct _virDomainChrSourceDef {
|
||||
struct {
|
||||
char *channel;
|
||||
} spiceport;
|
||||
struct {
|
||||
virDomainMouseMode mouse;
|
||||
virTristateBool clipboard;
|
||||
} qemuVdagent;
|
||||
} data;
|
||||
char *logfile;
|
||||
virTristateSwitch logappend;
|
||||
@ -1845,14 +1857,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,
|
||||
|
@ -920,6 +920,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;
|
||||
|
||||
|
@ -4009,23 +4009,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">
|
||||
@ -4114,6 +4101,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">
|
||||
@ -4514,6 +4520,7 @@
|
||||
<value>spicevmc</value>
|
||||
<value>spiceport</value>
|
||||
<value>nmdm</value>
|
||||
<value>qemu-vdagent</value>
|
||||
</choice>
|
||||
</define>
|
||||
|
||||
@ -4599,9 +4606,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>
|
||||
|
@ -1423,6 +1423,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;
|
||||
@ -1506,6 +1507,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:
|
||||
@ -8641,6 +8643,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"),
|
||||
|
@ -6824,6 +6824,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));
|
||||
|
@ -6826,6 +6826,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: {
|
||||
|
@ -1997,6 +1997,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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1056,6 +1056,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:
|
||||
|
Loading…
Reference in New Issue
Block a user