[libvirt] [PATCH 15/15] Switch to using virNetServer APIs for monitor socket

Daniel P. Berrange berrange at redhat.com
Tue Jul 3 15:58:54 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

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 at redhat.com>
---
 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




More information about the libvir-list mailing list