[libvirt] [PATCH RFC] Allow a client to connect to QEMU's VNC by passing an FD via libvirt

Eric Blake eblake at redhat.com
Thu Jun 23 13:30:57 UTC 2011


On 06/23/2011 06:48 AM, Daniel P. Berrange wrote:
> This patch implements a new API which allows a libvirt client
> application to connect to QEMU's VNC server, by passing a FD
> from an anonymous socketpair, to libvirt, which then passes it
> onto QEMU via the monitor. This obviously only works if the
> client app is talking to a local libvirt over UNIX sockets,
> not for any remote apps using TCP, or SSH tunnel.

In the remote case, would it be possible to reuse libvirt's rpc streams
such that the libvirt local to the qemu sets up the fd, then passes the
data from the local socket over the stream back to the remote client to
feed into the client's fd (that is, similar to how we support remote
consoles)?  But that doesn't have to happen right away.

> 
>  typedef enum {
>      VIR_DOMAIN_CONNECT_GRAPHICS_SKIPAUTH = (1 << 0),
>  } virDomainConnectGraphicsFlags;
> 
>  int virDomainConnectGraphics(virDomainPtr dom,
>                               const char *devname,
>                               int fd,
>                               unsigned int flags);
> 
> The QEMU monitor command I proposed actually allo2s
> conecting to VNC or SPICE or any character device,
> so I might rename this API to replace 'Graphics'
> with 'Client' or something. Or we could add a
> separate API for connecting to character devices.
> 
> This does a semi-nasty hack to the remote protocol, defining
> a new client -> server message type: REMOTE_CALL_WITH_FD
> which is identical to REMOTE_CALL, but a UNIX FD is passed
> between the header & payload. The reason I call this nasty
> is that it only allows for a single FD to be passed per
> RPC call. This seems like a reasonable restriction and it
> makes the code utterly trivial now, but I'm afraid it might
> bite us later.

I'm not too worried.  Look at how qemu's getfd monitor command works -
all it does is pass a single fd and associate it with a name, then all
subsequent commands that want an fd use the associated name.  That way,
you can pass as many fds as you need, one at a time, prior to the actual
command that wants to use multiple fds.

Of course, in the case of virDomainConnectGraphics, where we only need
one fd, it is much nicer to pass the fd and act on it immediately,
without having to go through separate naming of each passed fd followed
by referring to the name.

> +++ b/daemon/libvirtd.c
> @@ -67,6 +67,7 @@
>  #include "stream.h"
>  #include "hooks.h"
>  #include "virtaudit.h"
> +#include "passfd.h"

Yay gnulib for making this easy!

> @@ -1882,6 +1889,12 @@ readmore:
>              qemudDispatchClientFailure(client);
>          }
>  
> +        if (msg->hdr.type == REMOTE_CALL_WITH_FD) {
> +            VIR_ERROR("Trying to get FD");
> +            msg->fd = recvfd(client->fd, O_CLOEXEC);
> +            VIR_ERROR("Got %d", msg->fd);
> +        }
> +
>          /* Check if any filters match this message */
>          filter = client->filters;

I'm guessing that this depends on your rpc rewrite series going in
first, so that probably ought to get a better review before I spend too
much time on this one.  But the general idea seems useful.

> +++ b/src/libvirt.c
> @@ -15548,3 +15548,53 @@ error:
>      virDispatchError(dom->conn);
>      return -1;
>  }
> +
> +int virDomainConnectGraphics(virDomainPtr dom,
> +                             const char *devname,
> +                             int fd,
> +                             unsigned int flags)

No documentation?  What shame...

> +++ b/src/libvirt_private.syms
> @@ -950,6 +950,9 @@ virThreadIsSelf;
>  virThreadJoin;
>  virThreadSelf;
>  virThreadSelfID;
> +virThreadLocalGet;
> +virThreadLocalInit;
> +virThreadLocalSet;

Sorting?

> @@ -8429,6 +8487,7 @@ static virDriver qemuDriver = {
>      .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
>      .qemuDomainMonitorCommand = qemuDomainMonitorCommand, /* 0.8.3 */
>      .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
> +    .domainConnectGraphics = qemuDomainConnectGraphics, /* 0.9.2 */

0.9.3 (maybe, but certainly not 0.9.2).

> @@ -6525,6 +6622,7 @@ static virDriver remote_driver = {
>      .domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
>      .qemuDomainMonitorCommand = remoteQemuDomainMonitorCommand, /* 0.8.3 */
>      .domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
> +    .domainConnectGraphics = remoteDomainConnectGraphics, /* 0.9.2 */

Likewise.

-- 
Eric Blake   eblake at redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 619 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20110623/2e5fcae5/attachment-0001.sig>


More information about the libvir-list mailing list