提交 9a4d0b51 编写于 作者: D Daniel P. Berrange

Switch to using virNetServer APIs for monitor socket

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: NDaniel P. Berrange <berrange@redhat.com>
上级 9612e4b2
......@@ -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 \
......
......@@ -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);
}
......@@ -777,54 +766,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;
}
......@@ -847,120 +840,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;
......@@ -1222,53 +1118,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",
......@@ -1322,7 +1179,6 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
cleanup:
virMutexDestroy(&lock);
signal(SIGCHLD, SIG_DFL);
cleanup2:
for (i = 0 ; i < ctrl->nconsoles ; i++)
......@@ -1669,12 +1525,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;
......@@ -1706,7 +1556,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' },
......@@ -1857,10 +1706,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) {
......@@ -1895,21 +1741,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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册