Implement the RPC protocol for the libvirt-lxc.la library

Add the infrastructure for the libvirt-lxc.la library to
the remote protocol client and daemon

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-12-21 14:20:04 +00:00
parent 8bc18eaac6
commit 509eb51e7c
8 changed files with 237 additions and 26 deletions

View File

@ -17,7 +17,9 @@ CLEANFILES =
DAEMON_GENERATED = \
$(srcdir)/remote_dispatch.h \
$(srcdir)/qemu_dispatch.h
$(srcdir)/lxc_dispatch.h \
$(srcdir)/qemu_dispatch.h \
$(NULL)
DAEMON_SOURCES = \
libvirtd.c libvirtd.h \
@ -25,12 +27,14 @@ DAEMON_SOURCES = \
remote.c remote.h \
stream.c stream.h \
../src/remote/remote_protocol.c \
../src/remote/lxc_protocol.c \
../src/remote/qemu_protocol.c \
$(DAEMON_GENERATED)
DISTCLEANFILES =
EXTRA_DIST = \
remote_dispatch.h \
lxc_dispatch.h \
qemu_dispatch.h \
libvirtd.conf \
libvirtd.init.in \
@ -54,6 +58,7 @@ EXTRA_DIST = \
BUILT_SOURCES =
REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x
LXC_PROTOCOL = $(top_srcdir)/src/remote/lxc_protocol.x
QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x
$(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
@ -61,6 +66,11 @@ $(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b remote REMOTE \
$(REMOTE_PROTOCOL) > $@
$(srcdir)/lxc_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(LXC_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b lxc LXC \
$(LXC_PROTOCOL) > $@
$(srcdir)/qemu_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
$(QEMU_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu QEMU \
@ -117,6 +127,7 @@ libvirtd_LDADD += ../src/libvirt_probes.lo
endif
libvirtd_LDADD += \
../src/libvirt-lxc.la \
../src/libvirt-qemu.la
if ! WITH_DRIVER_MODULES

View File

@ -103,6 +103,7 @@ virNetSASLContextPtr saslCtxt = NULL;
#endif
virNetServerProgramPtr remoteProgram = NULL;
virNetServerProgramPtr qemuProgram = NULL;
virNetServerProgramPtr lxcProgram = NULL;
enum {
VIR_DAEMON_ERR_NONE = 0,
@ -1370,6 +1371,18 @@ int main(int argc, char **argv) {
goto cleanup;
}
if (!(lxcProgram = virNetServerProgramNew(LXC_PROGRAM,
LXC_PROTOCOL_VERSION,
lxcProcs,
lxcNProcs))) {
ret = VIR_DAEMON_ERR_INIT;
goto cleanup;
}
if (virNetServerAddProgram(srv, lxcProgram) < 0) {
ret = VIR_DAEMON_ERR_INIT;
goto cleanup;
}
if (!(qemuProgram = virNetServerProgramNew(QEMU_PROGRAM,
QEMU_PROTOCOL_VERSION,
qemuProcs,
@ -1475,6 +1488,7 @@ int main(int argc, char **argv) {
cleanup:
virNetlinkEventServiceStopAll();
virObjectUnref(remoteProgram);
virObjectUnref(lxcProgram);
virObjectUnref(qemuProgram);
virNetServerClose(srv);
virObjectUnref(srv);

View File

@ -32,6 +32,7 @@
# include <rpc/types.h>
# include <rpc/xdr.h>
# include "remote_protocol.h"
# include "lxc_protocol.h"
# include "qemu_protocol.h"
# include "virlog.h"
# include "virthread.h"

View File

@ -50,6 +50,7 @@
#include "virprocess.h"
#include "remote_protocol.h"
#include "qemu_protocol.h"
#include "lxc_protocol.h"
#define VIR_FROM_THIS VIR_FROM_RPC
@ -105,6 +106,7 @@ remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors,
#include "remote_dispatch.h"
#include "qemu_dispatch.h"
#include "lxc_dispatch.h"
/* Prototypes */
@ -4620,6 +4622,56 @@ cleanup:
return rv;
}
static int
lxcDispatchDomainOpenNamespace(virNetServerPtr server ATTRIBUTE_UNUSED,
virNetServerClientPtr client ATTRIBUTE_UNUSED,
virNetMessagePtr msg ATTRIBUTE_UNUSED,
virNetMessageErrorPtr rerr,
lxc_domain_open_namespace_args *args)
{
int rv = -1;
struct daemonClientPrivate *priv =
virNetServerClientGetPrivateData(client);
int *fdlist = NULL;
int ret;
virDomainPtr dom = NULL;
size_t i;
if (!priv->conn) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
goto cleanup;
}
if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
goto cleanup;
ret = virDomainLxcOpenNamespace(dom,
&fdlist,
args->flags);
if (ret < 0)
goto cleanup;
/* We shouldn't have received any from the client,
* but in case they're playing games with us, prevent
* a resource leak
*/
for (i = 0 ; i < msg->nfds ; i++)
VIR_FORCE_CLOSE(msg->fds[i]);
VIR_FREE(msg->fds);
msg->nfds = 0;
msg->fds = fdlist;
msg->nfds = ret;
rv = 1;
cleanup:
if (rv < 0)
virNetMessageSaveError(rerr);
virDomainFree(dom);
return rv;
}
/*----- Helpers. -----*/
/* get_nonnull_domain and get_nonnull_network turn an on-wire

View File

@ -32,6 +32,9 @@
extern virNetServerProgramProc remoteProcs[];
extern size_t remoteNProcs;
extern virNetServerProgramProc lxcProcs[];
extern size_t lxcNProcs;
extern virNetServerProgramProc qemuProcs[];
extern size_t qemuNProcs;

View File

@ -272,19 +272,28 @@ REMOTE_DRIVER_GENERATED = \
$(srcdir)/remote/remote_protocol.c \
$(srcdir)/remote/remote_protocol.h \
$(srcdir)/remote/remote_client_bodies.h \
$(srcdir)/remote/lxc_protocol.c \
$(srcdir)/remote/lxc_protocol.h \
$(srcdir)/remote/lxc_client_bodies.h \
$(srcdir)/remote/qemu_protocol.c \
$(srcdir)/remote/qemu_protocol.h \
$(srcdir)/remote/qemu_client_bodies.h
REMOTE_PROTOCOL = $(srcdir)/remote/remote_protocol.x
LXC_PROTOCOL = $(srcdir)/remote/lxc_protocol.x
QEMU_PROTOCOL = $(srcdir)/remote/qemu_protocol.x
REMOTE_DRIVER_PROTOCOL = $(REMOTE_PROTOCOL) $(QEMU_PROTOCOL)
REMOTE_DRIVER_PROTOCOL = $(REMOTE_PROTOCOL) $(QEMU_PROTOCOL) $(LXC_PROTOCOL)
$(srcdir)/remote/remote_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \
$(REMOTE_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \
-k remote REMOTE $(REMOTE_PROTOCOL) > $@
$(srcdir)/remote/lxc_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \
$(LXC_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \
-k lxc LXC $(LXC_PROTOCOL) > $@
$(srcdir)/remote/qemu_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \
$(QEMU_PROTOCOL)
$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \
@ -318,7 +327,7 @@ EXTRA_DIST += $(REMOTE_DRIVER_PROTOCOL) \
# The alternation of the following regexps matches both cases.
r1 = /\* \d+ \*/
r2 = /\* <[[:xdigit:]]+> \S+:\d+ \*/
struct_prefix = (remote_|qemu_|virNet|keepalive_)
struct_prefix = (remote_|qemu_|lxc_|virNet|keepalive_)
PDWTAGS = \
$(AM_V_GEN)if (pdwtags --help) > /dev/null 2>&1; then \
@ -374,6 +383,7 @@ EXTRA_DIST += check-symfile.pl check-symsorting.pl
PROTOCOL_STRUCTS = \
$(srcdir)/remote_protocol-structs \
$(srcdir)/lxc_protocol-structs \
$(srcdir)/qemu_protocol-structs \
$(srcdir)/virnetprotocol-structs \
$(srcdir)/virkeepaliveprotocol-structs
@ -382,7 +392,9 @@ check-protocol: $(PROTOCOL_STRUCTS) $(PROTOCOL_STRUCTS:structs=struct)
# The .o file that pdwtags parses is created as a side effect of running
# libtool; but from make's perspective we depend on the .lo file.
$(srcdir)/remote_protocol-struct $(srcdir)/qemu_protocol-struct: \
$(srcdir)/remote_protocol-struct \
$(srcdir)/qemu_protocol-struct \
$(srcdir)/lxc_protocol-struct: \
$(srcdir)/%-struct: libvirt_driver_remote_la-%.lo
$(PDWTAGS)
$(srcdir)/virnetprotocol-struct $(srcdir)/virkeepaliveprotocol-struct: \
@ -1546,6 +1558,7 @@ tapset_DATA = libvirt_probes.stp libvirt_qemu_probes.stp libvirt_functions.stp
RPC_PROBE_FILES = $(srcdir)/rpc/virnetprotocol.x \
$(srcdir)/rpc/virkeepaliveprotocol.x \
$(srcdir)/remote/remote_protocol.x \
$(srcdir)/remote/lxc_protocol.x \
$(srcdir)/remote/qemu_protocol.x
libvirt_functions.stp: $(RPC_PROBE_FILES) $(srcdir)/rpc/gensystemtap.pl

49
src/remote/lxc_protocol.x Normal file
View File

@ -0,0 +1,49 @@
/* -*- c -*-
* lxc_protocol.x: private protocol for communicating between
* remote_internal driver and libvirtd. This protocol is
* internal and may change at any time.
*
* Copyright (C) 2010-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel Berrange <berrange@redhat.com>
*/
%#include "internal.h"
%#include "remote_protocol.h"
/*----- Protocol. -----*/
struct lxc_domain_open_namespace_args {
remote_nonnull_domain dom;
unsigned int flags;
};
/* Define the program number, protocol version and procedure numbers here. */
const LXC_PROGRAM = 0x00068000;
const LXC_PROTOCOL_VERSION = 1;
enum lxc_procedure {
/* Each function must have a three-word comment. The first word is
* whether gendispatch.pl handles daemon, the second whether
* it handles src/remote.
* The last argument describes priority of API. There are two accepted
* values: low, high; Each API that might eventually access hypervisor's
* monitor (and thus block) MUST fall into low priority. However, there
* are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY
* be marked as high priority. If in doubt, it's safe to choose low. */
LXC_PROC_DOMAIN_OPEN_NAMESPACE = 1 /* skipgen skipgen priority:low */
};

View File

@ -37,6 +37,7 @@
#include "virbuffer.h"
#include "remote_driver.h"
#include "remote_protocol.h"
#include "lxc_protocol.h"
#include "qemu_protocol.h"
#include "viralloc.h"
#include "virutil.h"
@ -77,6 +78,7 @@ struct private_data {
virNetClientPtr client;
virNetClientProgramPtr remoteProgram;
virNetClientProgramPtr qemuProgram;
virNetClientProgramPtr lxcProgram;
int counter; /* Serial number for RPC */
@ -95,6 +97,7 @@ struct private_data {
enum {
REMOTE_CALL_QEMU = (1 << 0),
REMOTE_CALL_LXC = (1 << 1),
};
@ -112,10 +115,13 @@ static int call(virConnectPtr conn, struct private_data *priv,
unsigned int flags, int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret);
static int callWithFD(virConnectPtr conn, struct private_data *priv,
unsigned int flags, int fd, int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret);
static int callFull(virConnectPtr conn, struct private_data *priv,
unsigned int flags,
int *fdin, size_t fdinlen,
int **fdout, size_t *fdoutlen,
int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret);
static int remoteAuthenticate(virConnectPtr conn, struct private_data *priv,
virConnectAuthPtr auth, const char *authtype);
#if WITH_SASL
@ -768,6 +774,12 @@ doRemoteOpen(virConnectPtr conn,
ARRAY_CARDINALITY(remoteDomainEvents),
conn)))
goto failed;
if (!(priv->lxcProgram = virNetClientProgramNew(LXC_PROGRAM,
LXC_PROTOCOL_VERSION,
NULL,
0,
NULL)))
goto failed;
if (!(priv->qemuProgram = virNetClientProgramNew(QEMU_PROGRAM,
QEMU_PROTOCOL_VERSION,
NULL,
@ -776,6 +788,7 @@ doRemoteOpen(virConnectPtr conn,
goto failed;
if (virNetClientAddProgram(priv->client, priv->remoteProgram) < 0 ||
virNetClientAddProgram(priv->client, priv->lxcProgram) < 0 ||
virNetClientAddProgram(priv->client, priv->qemuProgram) < 0)
goto failed;
@ -860,6 +873,7 @@ no_memory:
failed:
virObjectUnref(priv->remoteProgram);
virObjectUnref(priv->lxcProgram);
virObjectUnref(priv->qemuProgram);
virNetClientClose(priv->client);
virObjectUnref(priv->client);
@ -1024,8 +1038,9 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv)
virObjectUnref(priv->client);
priv->client = NULL;
virObjectUnref(priv->remoteProgram);
virObjectUnref(priv->lxcProgram);
virObjectUnref(priv->qemuProgram);
priv->remoteProgram = priv->qemuProgram = NULL;
priv->remoteProgram = priv->qemuProgram = priv->lxcProgram = NULL;
/* Free hostname copy */
VIR_FREE(priv->hostname);
@ -5409,6 +5424,8 @@ remoteDomainOpenGraphics(virDomainPtr dom,
int rv = -1;
remote_domain_open_graphics_args args;
struct private_data *priv = dom->conn->privateData;
int fdin[] = { fd };
size_t fdinlen = ARRAY_CARDINALITY(fdin);
remoteDriverLock(priv);
@ -5416,9 +5433,12 @@ remoteDomainOpenGraphics(virDomainPtr dom,
args.idx = idx;
args.flags = flags;
if (callWithFD(dom->conn, priv, 0, fd, REMOTE_PROC_DOMAIN_OPEN_GRAPHICS,
(xdrproc_t) xdr_remote_domain_open_graphics_args, (char *) &args,
(xdrproc_t) xdr_void, NULL) == -1)
if (callFull(dom->conn, priv, 0,
fdin, fdinlen,
NULL, NULL,
REMOTE_PROC_DOMAIN_OPEN_GRAPHICS,
(xdrproc_t) xdr_remote_domain_open_graphics_args, (char *) &args,
(xdrproc_t) xdr_void, NULL) == -1)
goto done;
rv = 0;
@ -5523,6 +5543,7 @@ done:
}
#include "remote_client_bodies.h"
#include "lxc_client_bodies.h"
#include "qemu_client_bodies.h"
/*
@ -5530,22 +5551,30 @@ done:
* send that to the server and wait for reply
*/
static int
callWithFD(virConnectPtr conn ATTRIBUTE_UNUSED,
struct private_data *priv,
unsigned int flags,
int fd,
int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret)
callFull(virConnectPtr conn ATTRIBUTE_UNUSED,
struct private_data *priv,
unsigned int flags,
int *fdin,
size_t fdinlen,
int **fdout,
size_t *fdoutlen,
int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret)
{
int rv;
virNetClientProgramPtr prog = flags & REMOTE_CALL_QEMU ? priv->qemuProgram : priv->remoteProgram;
virNetClientProgramPtr prog;
int counter = priv->counter++;
virNetClientPtr client = priv->client;
int fds[] = { fd };
size_t nfds = fd == -1 ? 0 : 1;
priv->localUses++;
if (flags & REMOTE_CALL_QEMU)
prog = priv->qemuProgram;
else if (flags & REMOTE_CALL_LXC)
prog = priv->lxcProgram;
else
prog = priv->remoteProgram;
/* Unlock, so that if we get any async events/stream data
* while processing the RPC, we don't deadlock when our
* callbacks for those are invoked
@ -5555,7 +5584,8 @@ callWithFD(virConnectPtr conn ATTRIBUTE_UNUSED,
client,
counter,
proc_nr,
nfds, nfds ? fds : NULL, NULL, NULL,
fdinlen, fdin,
fdoutlen, fdout,
args_filter, args,
ret_filter, ret);
remoteDriverLock(priv);
@ -5572,9 +5602,12 @@ call(virConnectPtr conn,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret)
{
return callWithFD(conn, priv, flags, -1, proc_nr,
args_filter, args,
ret_filter, ret);
return callFull(conn, priv, flags,
NULL, 0,
NULL, NULL,
proc_nr,
args_filter, args,
ret_filter, ret);
}
@ -5850,6 +5883,40 @@ done:
return rv;
}
static int
remoteDomainLxcOpenNamespace(virDomainPtr domain,
int **fdlist,
unsigned int flags)
{
int rv = -1;
lxc_domain_open_namespace_args args;
struct private_data *priv = domain->conn->privateData;
size_t nfds = 0;
remoteDriverLock(priv);
make_nonnull_domain(&args.dom, domain);
args.flags = flags;
*fdlist = NULL;
if (callFull(domain->conn, priv, REMOTE_CALL_LXC,
NULL, 0,
fdlist, &nfds,
LXC_PROC_DOMAIN_OPEN_NAMESPACE,
(xdrproc_t) xdr_lxc_domain_open_namespace_args, (char *) &args,
(xdrproc_t) xdr_void, NULL) == -1)
goto done;
rv = nfds;
done:
remoteDriverUnlock(priv);
return rv;
}
static void
remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
{
@ -6170,6 +6237,7 @@ static virDriver remote_driver = {
.nodeGetMemoryParameters = remoteNodeGetMemoryParameters, /* 0.10.2 */
.nodeGetCPUMap = remoteNodeGetCPUMap, /* 1.0.0 */
.domainFSTrim = remoteDomainFSTrim, /* 1.0.1 */
.domainLxcOpenNamespace = remoteDomainLxcOpenNamespace, /* 1.0.2 */
};
static virNetworkDriver network_driver = {