[libvirt PATCH 2/3] conf: add qemu-vdagent channel

Jonathon Jongsma jjongsma at redhat.com
Wed Mar 23 16:18:50 UTC 2022


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 at 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>



More information about the libvir-list mailing list