mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
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: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
@@ -1523,6 +1523,8 @@ libvirt_lxc_SOURCES = \
|
|||||||
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
|
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
|
||||||
libvirt_lxc_LDADD = \
|
libvirt_lxc_LDADD = \
|
||||||
$(NUMACTL_LIBS) \
|
$(NUMACTL_LIBS) \
|
||||||
|
libvirt-net-rpc-server.la \
|
||||||
|
libvirt-net-rpc.la \
|
||||||
libvirt_driver_security.la \
|
libvirt_driver_security.la \
|
||||||
libvirt_conf.la \
|
libvirt_conf.la \
|
||||||
libvirt_util.la \
|
libvirt_util.la \
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
#include "processinfo.h"
|
#include "processinfo.h"
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
#include "virrandom.h"
|
#include "virrandom.h"
|
||||||
|
#include "rpc/virnetserver.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_LXC
|
#define VIR_FROM_THIS VIR_FROM_LXC
|
||||||
|
|
||||||
@@ -124,10 +125,8 @@ struct _virLXCController {
|
|||||||
|
|
||||||
virSecurityManagerPtr securityManager;
|
virSecurityManagerPtr securityManager;
|
||||||
|
|
||||||
int monitorServerFd;
|
/* Server socket */
|
||||||
int monitorServerWatch;
|
virNetServerPtr server;
|
||||||
int monitorClientFd;
|
|
||||||
int monitorClientWatch;
|
|
||||||
|
|
||||||
virCgroupPtr cgroup;
|
virCgroupPtr cgroup;
|
||||||
};
|
};
|
||||||
@@ -143,11 +142,6 @@ static virLXCControllerPtr virLXCControllerNew(const char *name)
|
|||||||
if (VIR_ALLOC(ctrl) < 0)
|
if (VIR_ALLOC(ctrl) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
ctrl->monitorServerFd = -1;
|
|
||||||
ctrl->monitorServerWatch = -1;
|
|
||||||
ctrl->monitorClientFd = -1;
|
|
||||||
ctrl->monitorClientWatch = -1;
|
|
||||||
|
|
||||||
if (!(ctrl->name = strdup(name)))
|
if (!(ctrl->name = strdup(name)))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
@@ -254,12 +248,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
|
|||||||
virDomainDefFree(ctrl->def);
|
virDomainDefFree(ctrl->def);
|
||||||
VIR_FREE(ctrl->name);
|
VIR_FREE(ctrl->name);
|
||||||
|
|
||||||
if (ctrl->monitorServerWatch != -1)
|
virNetServerFree(ctrl->server);
|
||||||
virEventRemoveHandle(ctrl->monitorServerWatch);
|
|
||||||
VIR_FORCE_CLOSE(ctrl->monitorServerFd);
|
|
||||||
if (ctrl->monitorClientWatch != -1)
|
|
||||||
virEventRemoveHandle(ctrl->monitorClientWatch);
|
|
||||||
VIR_FORCE_CLOSE(ctrl->monitorClientFd);
|
|
||||||
|
|
||||||
VIR_FREE(ctrl);
|
VIR_FREE(ctrl);
|
||||||
}
|
}
|
||||||
@@ -777,54 +766,58 @@ cleanup:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*lxcMonitorPath(virLXCControllerPtr ctrl)
|
|
||||||
|
static int virLXCControllerClientHook(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||||
|
virNetServerClientPtr client,
|
||||||
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
virLXCControllerPtr ctrl = opaque;
|
||||||
|
virNetServerClientSetPrivateData(client, ctrl, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
|
||||||
|
{
|
||||||
|
virNetServerServicePtr svc = NULL;
|
||||||
char *sockpath;
|
char *sockpath;
|
||||||
|
|
||||||
if (virAsprintf(&sockpath, "%s/%s.sock",
|
if (virAsprintf(&sockpath, "%s/%s.sock",
|
||||||
LXC_STATE_DIR, ctrl->def->name) < 0)
|
LXC_STATE_DIR, ctrl->name) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
return sockpath;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
static int lxcMonitorServer(const char *sockpath)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
|
|
||||||
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
_("failed to create server socket '%s'"),
|
|
||||||
sockpath);
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink(sockpath);
|
if (!(ctrl->server = virNetServerNew(0, 0, 0, 1,
|
||||||
memset(&addr, 0, sizeof(addr));
|
-1, 0, false,
|
||||||
addr.sun_family = AF_UNIX;
|
NULL,
|
||||||
if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) {
|
virLXCControllerClientHook,
|
||||||
lxcError(VIR_ERR_INTERNAL_ERROR,
|
ctrl)))
|
||||||
_("Socket path %s too long for destination"), sockpath);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
if (!(svc = virNetServerServiceNewUNIX(sockpath,
|
||||||
virReportSystemError(errno,
|
0700,
|
||||||
_("failed to bind server socket '%s'"),
|
0,
|
||||||
sockpath);
|
0,
|
||||||
|
false,
|
||||||
|
5,
|
||||||
|
NULL)))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
if (listen(fd, 30 /* backlog */ ) < 0) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
_("failed to listen server socket %s"),
|
|
||||||
sockpath);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
if (virNetServerAddService(ctrl->server, svc, NULL) < 0)
|
||||||
|
goto error;
|
||||||
|
virNetServerServiceFree(svc);
|
||||||
|
svc = NULL;
|
||||||
|
|
||||||
|
virNetServerUpdateServices(ctrl->server, true);
|
||||||
|
VIR_FREE(sockpath);
|
||||||
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
VIR_FORCE_CLOSE(fd);
|
VIR_FREE(sockpath);
|
||||||
|
virNetServerFree(ctrl->server);
|
||||||
|
ctrl->server = NULL;
|
||||||
|
virNetServerServiceFree(svc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,120 +840,23 @@ static int lxcControllerClearCapabilities(void)
|
|||||||
return 0;
|
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 bool quit = false;
|
||||||
static virMutex lock;
|
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,
|
static void virLXCControllerSignalChildIO(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||||
int fd ATTRIBUTE_UNUSED,
|
siginfo_t *info ATTRIBUTE_UNUSED,
|
||||||
int events ATTRIBUTE_UNUSED,
|
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
char buf[1];
|
virLXCControllerPtr ctrl = opaque;
|
||||||
int ret;
|
int ret;
|
||||||
virLXCControllerPtr ctrl = opaque;
|
|
||||||
|
|
||||||
ignore_value(read(sigpipe[0], buf, 1));
|
|
||||||
ret = waitpid(-1, NULL, WNOHANG);
|
ret = waitpid(-1, NULL, WNOHANG);
|
||||||
if (ret == ctrl->initpid) {
|
if (ret == ctrl->initpid)
|
||||||
virMutexLock(&lock);
|
virNetServerQuit(ctrl->server);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr console)
|
||||||
{
|
{
|
||||||
int hostEvents = 0;
|
int hostEvents = 0;
|
||||||
@@ -1222,53 +1118,14 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
|
|||||||
if (virMutexInit(&lock) < 0)
|
if (virMutexInit(&lock) < 0)
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
|
|
||||||
if (pipe2(sigpipe, O_CLOEXEC|O_NONBLOCK) < 0) {
|
if (virNetServerAddSignalHandler(ctrl->server,
|
||||||
virReportSystemError(errno, "%s",
|
SIGCHLD,
|
||||||
_("Cannot create signal pipe"));
|
virLXCControllerSignalChildIO,
|
||||||
|
ctrl) < 0)
|
||||||
goto cleanup;
|
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"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("serverFd=%d clientFd=%d",
|
|
||||||
ctrl->monitorServerFd, ctrl->monitorClientFd);
|
|
||||||
virResetLastError();
|
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++) {
|
for (i = 0 ; i < ctrl->nconsoles ; i++) {
|
||||||
if ((ctrl->consoles[i].epollFd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
|
if ((ctrl->consoles[i].epollFd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
|
||||||
virReportSystemError(errno, "%s",
|
virReportSystemError(errno, "%s",
|
||||||
@@ -1322,7 +1179,6 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virMutexDestroy(&lock);
|
virMutexDestroy(&lock);
|
||||||
signal(SIGCHLD, SIG_DFL);
|
|
||||||
cleanup2:
|
cleanup2:
|
||||||
|
|
||||||
for (i = 0 ; i < ctrl->nconsoles ; i++)
|
for (i = 0 ; i < ctrl->nconsoles ; i++)
|
||||||
@@ -1669,12 +1525,6 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
|
|||||||
if (virLXCControllerDaemonHandshake(ctrl) < 0)
|
if (virLXCControllerDaemonHandshake(ctrl) < 0)
|
||||||
goto cleanup;
|
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++)
|
for (i = 0 ; i < ctrl->nconsoles ; i++)
|
||||||
if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0)
|
if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -1706,7 +1556,6 @@ int main(int argc, char *argv[])
|
|||||||
char **veths = NULL;
|
char **veths = NULL;
|
||||||
int handshakeFd = -1;
|
int handshakeFd = -1;
|
||||||
int bg = 0;
|
int bg = 0;
|
||||||
char *sockpath = NULL;
|
|
||||||
const struct option options[] = {
|
const struct option options[] = {
|
||||||
{ "background", 0, NULL, 'b' },
|
{ "background", 0, NULL, 'b' },
|
||||||
{ "name", 1, NULL, 'n' },
|
{ "name", 1, NULL, 'n' },
|
||||||
@@ -1857,10 +1706,7 @@ int main(int argc, char *argv[])
|
|||||||
if (virLXCControllerValidateConsoles(ctrl) < 0)
|
if (virLXCControllerValidateConsoles(ctrl) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if ((sockpath = lxcMonitorPath(ctrl)) == NULL)
|
if (virLXCControllerSetupServer(ctrl) < 0)
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if ((ctrl->monitorServerFd = lxcMonitorServer(sockpath)) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (bg) {
|
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);
|
rc = virLXCControllerRun(ctrl);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virPidFileDelete(LXC_STATE_DIR, name);
|
virPidFileDelete(LXC_STATE_DIR, name);
|
||||||
virLXCControllerDeleteInterfaces(ctrl);
|
virLXCControllerDeleteInterfaces(ctrl);
|
||||||
if (sockpath)
|
|
||||||
unlink(sockpath);
|
|
||||||
VIR_FREE(sockpath);
|
|
||||||
for (i = 0 ; i < nttyFDs ; i++)
|
for (i = 0 ; i < nttyFDs ; i++)
|
||||||
VIR_FORCE_CLOSE(ttyFDs[i]);
|
VIR_FORCE_CLOSE(ttyFDs[i]);
|
||||||
VIR_FREE(ttyFDs);
|
VIR_FREE(ttyFDs);
|
||||||
|
|||||||
Reference in New Issue
Block a user