

Re: [Libvir] Preliminary patch to support remote driver / libvirtd (updated: 20070213)

Attached is the latest rev of this patch to support remote drivers. It is still not in a state where it can or should be applied. In particular it
still "does nothing" except supporting the version and type calls.


 * The URL syntax has changed.  Please see the first attachment for
   complete details of the new syntax.
 * Attempts to verify client IP address using TLS certificate, but
   this code is probably not correct.
 * libvirtd has a comprehensive configuration file.
 * libvirtd forks into the background, and has many other improvements.
 * All previous comments that I received should have been taken into
   account and where possible fixed.  Please let me know if there's
   anything I've missed.

Some things to discuss

Should libvirt clients automatically reconnect when the server (libvirtd)
restarts?  SunRPC supports this, reasonably seamlessly.  The problem is
that we will be issuing a "cookie" to the client to represent various
structures held on the server (mainly virConnectPtr, but also virDomainPtr
and a few others).  The mapping of cookie -> structure is lost when
libvirtd restarts unless we keep it somewhere persistent.  Now if we
keep track of cookie -> URLs in a persistent place, then when a client
represents a cookie that we don't know about because it was created in
a previous libvirtd session, we can look it up and reopen the connection
to the backend (using the URL). In the current implementation of libvirt
this looks safe.

Should libvirtd run as a preforked server?  SunRPC is basically single
threaded.  The server handles one RPC at a time and processes it to
completion before handling the next.  The simple way around this is to
use a preforked server.  This has implications with cookies -- either
they need to be stored in shared memory (similar to Apache's scoreboard
stuff) or else in persistent storage.

		-		-		-

The second attachment is the patch.  You can also download the patch
from http://www.annexia.org/tmp/libvirt-tls-20070213.patch

/* Architecture and notes:
 * virConnectOpen in this driver looks for remote URLs and will
 * try some method to connect to a libvirtd running on a remote
 * machine.
 * Local URLs are the standard URLs used by other drivers -
 * for example "qemud:///system".
 * Remote URLs contain either a server name or a remote transport
 * name.  For example: "qemud://server.example.com/system" contains
 * a server name (server.example.com), and "qemud+unix:///system"
 * contains a transport (unix).  Commonly remote URLs contain
 * both, for example: "qemud+tls://server.example.com/system"
 * (transport tls, server name server.example.com).
 * All other vir* calls made on this connection are forwarded
 * to the libvirtd daemon which carries out the requested action.
 * So for example if you call virDomainCreateLinux, then the
 * domain gets created on the remote machine, and virConnectListDomains
 * lists domains running on the remote machine.
 * Connections can be authenticated and encrypted -- it depends
 * on the transport selected.
 * The current implementation uses SunRPC layered over one of:
 *  - GnuTLS (an SSL/TLS library providing enterprise-level
 *      authentication and encryption)
 *  - a local Unix domain socket
 *  - ssh or another external program such as rsh
 *  - a plain TCP socket (unencrypted, not recommended for production)
 * See http://et.redhat.com/~rjones/secure_rpc for an insight into
 * the thinking that went into the selection of SunRPC.  In
 * the future we may use a different RPC system - for example
 * XML-RPC would be a logical choice - so for now you should regard
 * the protocol used as private and subject to change in future
 * versions of libvirt without notice.
 * The URL (name parameter to virConnectOpen) is a URL of the
 * following general form:
 *  "driver+transport://server:port/path?var=value&var=value&..."
 * Transport, server and port are all optional (except that you must
 * have either transport or server as explained above).  You may
 * have zero or more variables (or omit the query string entirely).
 * Driver is the usual libvirt driver, as used on the remote
 * machine, and path is specific to driver.
 * Some examples:
 *  "xend://server/"              Remote xend, using TLS, port 16514
 *  "qemud+unix:///session"       Communicate over Unix domain socket
 *                                  to a local libvirtd.
 *  "qemud+ssh://server/session?command=/opt/openssh/bin/ssh"
 *                                Communicate over ssh to a remote
 *                                  libvirtd on server.  Control qemu
 *                                  on remote.  ssh command is located
 *                                  in a non-standard place.
 *  "qemud+tcp://server:5000/session"
 *                                Unencrypted TCP, port 5000.
 *  "xend+ext:///?command=my_shell_script"
 *                                Run my_shell_script which uses its own
 *                                method (eg. rsh, ssh, ...) to talk to
 *                                the remote libvirtd, controlling a
 *                                remote xend.
 * [To emphasise - in ALL instances communication is with a remote
 * libvirtd, even if that remote libvirtd itself talks to another
 * daemon such as xend or qemud].
 * The transport is one of: tls, unix, ssh, ext or tcp.  If no
 * transport is given, the default is to use tls.
 * For tls, the default port is 16514.  For tcp, the default port is
 * 16509 (but note that tcp is almost never enabled because it is
 * insecure - it's only there for testing).
 * For ssh: The default port for ssh is 22.  You should configure ssh
 * so that it doesn't ask for a password (eg. using ssh-agent).  The
 * remote server should have a recent version of the the netcat program
 * installed as 'nc', and the remote libvirtd must be configured to
 * listen on a Unix domain socket.  The following full command is run:
 *   ssh -p $port [-l $username] $hostname $netcat -U /var/run/libvirtd/socket
 * For ext: Only the command you specify is run.  It is up to you to
 * write this command so that it somehow makes a connection to a
 * remote libvirtd, and passes input and output over its stdin/stdout.
 * The var=value pairs provide optional extra information:
 *   Variable    Transport     Meaning
 *   command     ssh,ext       Name or path of external program.
 *                               For ssh this defaults to "ssh".
 *                               For ext you must supply it.
 *   name        (all)         Optionally the name used in remote
 *                               virConnectOpen.  The default is to
 *                               construct the name by removing
 *                               transport, server name, port and
 *                               variables from the remote URL to
 *                               form a local URL.  But if this
 *                               doesn't give the desired result you
 *                               may specify the exact name here.
 *   socket      unix,ssh,ext  Name of the Unix domain socket.  The
 *                               default is in <remote_internal.h>.
 *   netcat      ssh           Name of the netcat program on the
 *                               remote server.  Default is "nc".
 *   no_verify   tls           If set to a non-zero value, this will
 *                               not check the peer's certificate
 *                               (it will still print a warning).
 *                               The default is to always check.
 * The value is %-escaped (just like URL encoding), so if you want it
 * to contain a literal space use "%20" or "+", if you want it to have
 * a literal + character use "%2b", and for a literal % character use "%25".
 * To provide some forwards compatibility, variables which are not
 * understood are ignored (but a warning is printed on stderr).
 * For the details of the implementation of SunRPC over GnuTLS, etc.
 * please see http://et.redhat.com/~rjones/secure_rpc which contains
 * simple code samples which will allow you to understand what's
 * going on here.

Attachment: libvirt-tls-20070213.patch
Description: Binary data
