From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> In preparation for introducing a full RPC protocol for libvirt_lxc, switch over to using the virNetServer APIs for the monitor connection Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/Makefile.am | 2 + src/lxc/lxc_controller.c | 268 +++++++++------------------------------------- 2 files changed, 54 insertions(+), 216 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index eeeda1c..6c3eaa7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1523,6 +1523,8 @@ libvirt_lxc_SOURCES = \ libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS) libvirt_lxc_LDADD = \ $(NUMACTL_LIBS) \ + libvirt-net-rpc-server.la \ + libvirt-net-rpc.la \ libvirt_driver_security.la \ libvirt_conf.la \ libvirt_util.la \ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 27b51b4..ed43aad 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -68,6 +68,7 @@ #include "processinfo.h" #include "nodeinfo.h" #include "virrandom.h" +#include "rpc/virnetserver.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -124,10 +125,8 @@ struct _virLXCController { virSecurityManagerPtr securityManager; - int monitorServerFd; - int monitorServerWatch; - int monitorClientFd; - int monitorClientWatch; + /* Server socket */ + virNetServerPtr server; virCgroupPtr cgroup; }; @@ -143,11 +142,6 @@ static virLXCControllerPtr virLXCControllerNew(const char *name) if (VIR_ALLOC(ctrl) < 0) goto no_memory; - ctrl->monitorServerFd = -1; - ctrl->monitorServerWatch = -1; - ctrl->monitorClientFd = -1; - ctrl->monitorClientWatch = -1; - if (!(ctrl->name = strdup(name))) goto no_memory; @@ -254,12 +248,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) virDomainDefFree(ctrl->def); VIR_FREE(ctrl->name); - if (ctrl->monitorServerWatch != -1) - virEventRemoveHandle(ctrl->monitorServerWatch); - VIR_FORCE_CLOSE(ctrl->monitorServerFd); - if (ctrl->monitorClientWatch != -1) - virEventRemoveHandle(ctrl->monitorClientWatch); - VIR_FORCE_CLOSE(ctrl->monitorClientFd); + virNetServerFree(ctrl->server); VIR_FREE(ctrl); } @@ -778,54 +767,58 @@ cleanup: return rc; } -static char*lxcMonitorPath(virLXCControllerPtr ctrl) -{ - char *sockpath; - if (virAsprintf(&sockpath, "%s/%s.sock", - LXC_STATE_DIR, ctrl->def->name) < 0) - virReportOOMError(); - return sockpath; +static int virLXCControllerClientHook(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + void *opaque) +{ + virLXCControllerPtr ctrl = opaque; + virNetServerClientSetPrivateData(client, ctrl, NULL); + return 0; } -static int lxcMonitorServer(const char *sockpath) + +static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) { - int fd; - struct sockaddr_un addr; + virNetServerServicePtr svc = NULL; + char *sockpath; - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - virReportSystemError(errno, - _("failed to create server socket '%s'"), - sockpath); - goto error; + if (virAsprintf(&sockpath, "%s/%s.sock", + LXC_STATE_DIR, ctrl->name) < 0) { + virReportOOMError(); + return -1; } - unlink(sockpath); - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Socket path %s too long for destination"), sockpath); + if (!(ctrl->server = virNetServerNew(0, 0, 0, 1, + -1, 0, false, + NULL, + virLXCControllerClientHook, + ctrl))) goto error; - } - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - virReportSystemError(errno, - _("failed to bind server socket '%s'"), - sockpath); + if (!(svc = virNetServerServiceNewUNIX(sockpath, + 0700, + 0, + 0, + false, + 5, + NULL))) goto error; - } - if (listen(fd, 30 /* backlog */ ) < 0) { - virReportSystemError(errno, - _("failed to listen server socket %s"), - sockpath); + + if (virNetServerAddService(ctrl->server, svc, NULL) < 0) goto error; - } + virNetServerServiceFree(svc); + svc = NULL; - return fd; + virNetServerUpdateServices(ctrl->server, true); + VIR_FREE(sockpath); + return 0; error: - VIR_FORCE_CLOSE(fd); + VIR_FREE(sockpath); + virNetServerFree(ctrl->server); + ctrl->server = NULL; + virNetServerServiceFree(svc); return -1; } @@ -848,120 +841,23 @@ static int lxcControllerClearCapabilities(void) return 0; } -/* Return true if it is ok to ignore an accept-after-epoll syscall - that fails with the specified errno value. Else false. */ -static bool -ignorable_accept_errno(int errnum) -{ - return (errnum == EINVAL - || errnum == ECONNABORTED - || errnum == EAGAIN - || errnum == EWOULDBLOCK); -} - static bool quit = false; static virMutex lock; -static int sigpipe[2]; -static void virLXCControllerSignalChildHandler(int signum ATTRIBUTE_UNUSED) -{ - ignore_value(write(sigpipe[1], "1", 1)); -} -static void virLXCControllerSignalChildIO(int watch ATTRIBUTE_UNUSED, - int fd ATTRIBUTE_UNUSED, - int events ATTRIBUTE_UNUSED, +static void virLXCControllerSignalChildIO(virNetServerPtr server ATTRIBUTE_UNUSED, + siginfo_t *info ATTRIBUTE_UNUSED, void *opaque) { - char buf[1]; - int ret; virLXCControllerPtr ctrl = opaque; + int ret; - ignore_value(read(sigpipe[0], buf, 1)); ret = waitpid(-1, NULL, WNOHANG); - if (ret == ctrl->initpid) { - virMutexLock(&lock); - quit = true; - virMutexUnlock(&lock); - } -} - - -static void virLXCControllerClientIO(int watch ATTRIBUTE_UNUSED, int fd, int events, void *opaque) -{ - virLXCControllerPtr ctrl = opaque; - char buf[1024]; - ssize_t ret; - - if (events & (VIR_EVENT_HANDLE_HANGUP | - VIR_EVENT_HANDLE_ERROR)) { - virEventRemoveHandle(ctrl->monitorClientWatch); - ctrl->monitorClientWatch = -1; - return; - } - -reread: - ret = read(fd, buf, sizeof(buf)); - if (ret == -1 && errno == EINTR) - goto reread; - if (ret == -1 && errno == EAGAIN) - return; - if (ret == -1) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to read from monitor client")); - virMutexLock(&lock); - quit = true; - virMutexUnlock(&lock); - return; - } - if (ret == 0) { - VIR_DEBUG("Client %d gone", fd); - VIR_FORCE_CLOSE(ctrl->monitorClientFd); - virEventRemoveHandle(ctrl->monitorClientWatch); - ctrl->monitorClientWatch = -1; - } + if (ret == ctrl->initpid) + virNetServerQuit(ctrl->server); } -static void virLXCControllerServerAccept(int watch ATTRIBUTE_UNUSED, int fd, int events ATTRIBUTE_UNUSED, void *opaque) -{ - virLXCControllerPtr ctrl = opaque; - int client; - - if ((client = accept(fd, NULL, NULL)) < 0) { - /* First reflex may be simply to declare accept failure - to be a fatal error. However, accept may fail when - a client quits between the above poll and here. - That case is not fatal, but rather to be expected, - if not common, so ignore it. */ - if (ignorable_accept_errno(errno)) - return; - virReportSystemError(errno, "%s", - _("Unable to accept monitor client")); - virMutexLock(&lock); - quit = true; - virMutexUnlock(&lock); - return; - } - VIR_DEBUG("New client %d (old %d)\n", client, ctrl->monitorClientFd); - VIR_FORCE_CLOSE(ctrl->monitorClientFd); - virEventRemoveHandle(ctrl->monitorClientWatch); - - ctrl->monitorClientFd = client; - if ((ctrl->monitorClientWatch = virEventAddHandle(ctrl->monitorClientFd, - VIR_EVENT_HANDLE_READABLE, - virLXCControllerClientIO, - ctrl, - NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch client socket")); - virMutexLock(&lock); - quit = true; - virMutexUnlock(&lock); - return; - } -} - static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr console) { int hostEvents = 0; @@ -1223,53 +1119,14 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) if (virMutexInit(&lock) < 0) goto cleanup2; - if (pipe2(sigpipe, O_CLOEXEC|O_NONBLOCK) < 0) { - virReportSystemError(errno, "%s", - _("Cannot create signal pipe")); - goto cleanup; - } - - if (virEventAddHandle(sigpipe[0], - VIR_EVENT_HANDLE_READABLE, - virLXCControllerSignalChildIO, - ctrl, - NULL) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch signal pipe")); - goto cleanup; - } - - if (signal(SIGCHLD, virLXCControllerSignalChildHandler) == SIG_ERR) { - virReportSystemError(errno, "%s", - _("Cannot install signal handler")); + if (virNetServerAddSignalHandler(ctrl->server, + SIGCHLD, + virLXCControllerSignalChildIO, + ctrl) < 0) goto cleanup; - } - VIR_DEBUG("serverFd=%d clientFd=%d", - ctrl->monitorServerFd, ctrl->monitorClientFd); virResetLastError(); - if ((ctrl->monitorServerWatch = virEventAddHandle(ctrl->monitorServerFd, - VIR_EVENT_HANDLE_READABLE, - virLXCControllerServerAccept, - ctrl, - NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch monitor socket")); - goto cleanup; - } - - if (ctrl->monitorClientFd != -1 && - (ctrl->monitorClientWatch = virEventAddHandle(ctrl->monitorClientFd, - VIR_EVENT_HANDLE_READABLE, - virLXCControllerClientIO, - ctrl, - NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch client socket")); - goto cleanup; - } - for (i = 0 ; i < ctrl->nconsoles ; i++) { if ((ctrl->consoles[i].epollFd = epoll_create1(EPOLL_CLOEXEC)) < 0) { virReportSystemError(errno, "%s", @@ -1323,7 +1180,6 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) cleanup: virMutexDestroy(&lock); - signal(SIGCHLD, SIG_DFL); cleanup2: for (i = 0 ; i < ctrl->nconsoles ; i++) @@ -1668,12 +1524,6 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerDaemonHandshake(ctrl) < 0) goto cleanup; - if (virSetBlocking(ctrl->monitorServerFd, false) < 0 || - virSetBlocking(ctrl->monitorClientFd, false) < 0) { - virReportSystemError(errno, "%s", - _("Unable to set file descriptor non-blocking")); - goto cleanup; - } for (i = 0 ; i < ctrl->nconsoles ; i++) if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0) goto cleanup; @@ -1707,7 +1557,6 @@ int main(int argc, char *argv[]) char **veths = NULL; int handshakeFd = -1; int bg = 0; - char *sockpath = NULL; const struct option options[] = { { "background", 0, NULL, 'b' }, { "name", 1, NULL, 'n' }, @@ -1858,10 +1707,7 @@ int main(int argc, char *argv[]) if (virLXCControllerValidateConsoles(ctrl) < 0) goto cleanup; - if ((sockpath = lxcMonitorPath(ctrl)) == NULL) - goto cleanup; - - if ((ctrl->monitorServerFd = lxcMonitorServer(sockpath)) < 0) + if (virLXCControllerSetupServer(ctrl) < 0) goto cleanup; if (bg) { @@ -1896,21 +1742,11 @@ int main(int argc, char *argv[]) } } - /* Accept initial client which is the libvirtd daemon */ - if ((ctrl->monitorClientFd = accept(ctrl->monitorServerFd, NULL, 0)) < 0) { - virReportSystemError(errno, "%s", - _("Failed to accept a connection from driver")); - goto cleanup; - } - rc = virLXCControllerRun(ctrl); cleanup: virPidFileDelete(LXC_STATE_DIR, name); virLXCControllerDeleteInterfaces(ctrl); - if (sockpath) - unlink(sockpath); - VIR_FREE(sockpath); for (i = 0 ; i < nttyFDs ; i++) VIR_FORCE_CLOSE(ttyFDs[i]); VIR_FREE(ttyFDs); -- 1.7.10.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list