提交 fa142073 编写于 作者: M Martin Kletzander

Move daemon-related parts of virNetServer to virNetDaemon

This allows to have more servers in one daemon which helps isolating
some resources.
Signed-off-by: NMartin Kletzander <mkletzan@redhat.com>
上级 387cb8c6
/* /*
* libvirtd.c: daemon start of day, guest process & i/o management * libvirtd.c: daemon start of day, guest process & i/o management
* *
* Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
#include "viralloc.h" #include "viralloc.h"
#include "virconf.h" #include "virconf.h"
#include "virnetlink.h" #include "virnetlink.h"
#include "virnetserver.h" #include "virnetdaemon.h"
#include "remote.h" #include "remote.h"
#include "virhook.h" #include "virhook.h"
#include "viraudit.h" #include "viraudit.h"
...@@ -776,14 +776,14 @@ daemonSetupPrivs(void) ...@@ -776,14 +776,14 @@ daemonSetupPrivs(void)
#endif #endif
static void daemonShutdownHandler(virNetServerPtr srv, static void daemonShutdownHandler(virNetDaemonPtr dmn,
siginfo_t *sig ATTRIBUTE_UNUSED, siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
virNetServerQuit(srv); virNetDaemonQuit(dmn);
} }
static void daemonReloadHandler(virNetServerPtr srv ATTRIBUTE_UNUSED, static void daemonReloadHandler(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
siginfo_t *sig ATTRIBUTE_UNUSED, siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
...@@ -799,15 +799,15 @@ static void daemonReloadHandler(virNetServerPtr srv ATTRIBUTE_UNUSED, ...@@ -799,15 +799,15 @@ static void daemonReloadHandler(virNetServerPtr srv ATTRIBUTE_UNUSED,
VIR_WARN("Error while reloading drivers"); VIR_WARN("Error while reloading drivers");
} }
static int daemonSetupSignals(virNetServerPtr srv) static int daemonSetupSignals(virNetDaemonPtr dmn)
{ {
if (virNetServerAddSignalHandler(srv, SIGINT, daemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGINT, daemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGQUIT, daemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGQUIT, daemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGTERM, daemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGTERM, daemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGHUP, daemonReloadHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGHUP, daemonReloadHandler, NULL) < 0)
return -1; return -1;
return 0; return 0;
} }
...@@ -815,12 +815,12 @@ static int daemonSetupSignals(virNetServerPtr srv) ...@@ -815,12 +815,12 @@ static int daemonSetupSignals(virNetServerPtr srv)
static void daemonInhibitCallback(bool inhibit, void *opaque) static void daemonInhibitCallback(bool inhibit, void *opaque)
{ {
virNetServerPtr srv = opaque; virNetDaemonPtr dmn = opaque;
if (inhibit) if (inhibit)
virNetServerAddShutdownInhibition(srv); virNetDaemonAddShutdownInhibition(dmn);
else else
virNetServerRemoveShutdownInhibition(srv); virNetDaemonRemoveShutdownInhibition(dmn);
} }
...@@ -830,26 +830,26 @@ static DBusConnection *systemBus; ...@@ -830,26 +830,26 @@ static DBusConnection *systemBus;
static void daemonStopWorker(void *opaque) static void daemonStopWorker(void *opaque)
{ {
virNetServerPtr srv = opaque; virNetDaemonPtr dmn = opaque;
VIR_DEBUG("Begin stop srv=%p", srv); VIR_DEBUG("Begin stop dmn=%p", dmn);
ignore_value(virStateStop()); ignore_value(virStateStop());
VIR_DEBUG("Completed stop srv=%p", srv); VIR_DEBUG("Completed stop dmn=%p", dmn);
/* Exit libvirtd cleanly */ /* Exit libvirtd cleanly */
virNetServerQuit(srv); virNetDaemonQuit(dmn);
} }
/* We do this in a thread to not block the main loop */ /* We do this in a thread to not block the main loop */
static void daemonStop(virNetServerPtr srv) static void daemonStop(virNetDaemonPtr dmn)
{ {
virThread thr; virThread thr;
virObjectRef(srv); virObjectRef(dmn);
if (virThreadCreate(&thr, false, daemonStopWorker, srv) < 0) if (virThreadCreate(&thr, false, daemonStopWorker, dmn) < 0)
virObjectUnref(srv); virObjectUnref(dmn);
} }
...@@ -858,14 +858,14 @@ handleSessionMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED, ...@@ -858,14 +858,14 @@ handleSessionMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED,
DBusMessage *message, DBusMessage *message,
void *opaque) void *opaque)
{ {
virNetServerPtr srv = opaque; virNetDaemonPtr dmn = opaque;
VIR_DEBUG("srv=%p", srv); VIR_DEBUG("dmn=%p", dmn);
if (dbus_message_is_signal(message, if (dbus_message_is_signal(message,
DBUS_INTERFACE_LOCAL, DBUS_INTERFACE_LOCAL,
"Disconnected")) "Disconnected"))
daemonStop(srv); daemonStop(dmn);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }
...@@ -876,14 +876,14 @@ handleSystemMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED, ...@@ -876,14 +876,14 @@ handleSystemMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED,
DBusMessage *message, DBusMessage *message,
void *opaque) void *opaque)
{ {
virNetServerPtr srv = opaque; virNetDaemonPtr dmn = opaque;
VIR_DEBUG("srv=%p", srv); VIR_DEBUG("dmn=%p", dmn);
if (dbus_message_is_signal(message, if (dbus_message_is_signal(message,
"org.freedesktop.login1.Manager", "org.freedesktop.login1.Manager",
"PrepareForShutdown")) "PrepareForShutdown"))
daemonStop(srv); daemonStop(dmn);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }
...@@ -892,22 +892,22 @@ handleSystemMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED, ...@@ -892,22 +892,22 @@ handleSystemMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED,
static void daemonRunStateInit(void *opaque) static void daemonRunStateInit(void *opaque)
{ {
virNetServerPtr srv = opaque; virNetDaemonPtr dmn = opaque;
virIdentityPtr sysident = virIdentityGetSystem(); virIdentityPtr sysident = virIdentityGetSystem();
virIdentitySetCurrent(sysident); virIdentitySetCurrent(sysident);
/* Since driver initialization can take time inhibit daemon shutdown until /* Since driver initialization can take time inhibit daemon shutdown until
we're done so clients get a chance to connect */ we're done so clients get a chance to connect */
daemonInhibitCallback(true, srv); daemonInhibitCallback(true, dmn);
/* Start the stateful HV drivers /* Start the stateful HV drivers
* This is deliberately done after telling the parent process * This is deliberately done after telling the parent process
* we're ready, since it can take a long time and this will * we're ready, since it can take a long time and this will
* seriously delay OS bootup process */ * seriously delay OS bootup process */
if (virStateInitialize(virNetServerIsPrivileged(srv), if (virStateInitialize(virNetDaemonIsPrivileged(dmn),
daemonInhibitCallback, daemonInhibitCallback,
srv) < 0) { dmn) < 0) {
VIR_ERROR(_("Driver state initialization failed")); VIR_ERROR(_("Driver state initialization failed"));
/* Ensure the main event loop quits */ /* Ensure the main event loop quits */
kill(getpid(), SIGTERM); kill(getpid(), SIGTERM);
...@@ -918,17 +918,17 @@ static void daemonRunStateInit(void *opaque) ...@@ -918,17 +918,17 @@ static void daemonRunStateInit(void *opaque)
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
/* Tie the non-priviledged libvirtd to the session/shutdown lifecycle */ /* Tie the non-priviledged libvirtd to the session/shutdown lifecycle */
if (!virNetServerIsPrivileged(srv)) { if (!virNetDaemonIsPrivileged(dmn)) {
sessionBus = virDBusGetSessionBus(); sessionBus = virDBusGetSessionBus();
if (sessionBus != NULL) if (sessionBus != NULL)
dbus_connection_add_filter(sessionBus, dbus_connection_add_filter(sessionBus,
handleSessionMessageFunc, srv, NULL); handleSessionMessageFunc, dmn, NULL);
systemBus = virDBusGetSystemBus(); systemBus = virDBusGetSystemBus();
if (systemBus != NULL) { if (systemBus != NULL) {
dbus_connection_add_filter(systemBus, dbus_connection_add_filter(systemBus,
handleSystemMessageFunc, srv, NULL); handleSystemMessageFunc, dmn, NULL);
dbus_bus_add_match(systemBus, dbus_bus_add_match(systemBus,
"type='signal',sender='org.freedesktop.login1', interface='org.freedesktop.login1.Manager'", "type='signal',sender='org.freedesktop.login1', interface='org.freedesktop.login1.Manager'",
NULL); NULL);
...@@ -936,20 +936,20 @@ static void daemonRunStateInit(void *opaque) ...@@ -936,20 +936,20 @@ static void daemonRunStateInit(void *opaque)
} }
#endif #endif
/* Only now accept clients from network */ /* Only now accept clients from network */
virNetServerUpdateServices(srv, true); virNetDaemonUpdateServices(dmn, true);
cleanup: cleanup:
daemonInhibitCallback(false, srv); daemonInhibitCallback(false, dmn);
virObjectUnref(srv); virObjectUnref(dmn);
virObjectUnref(sysident); virObjectUnref(sysident);
virIdentitySetCurrent(NULL); virIdentitySetCurrent(NULL);
} }
static int daemonStateInit(virNetServerPtr srv) static int daemonStateInit(virNetDaemonPtr dmn)
{ {
virThread thr; virThread thr;
virObjectRef(srv); virObjectRef(dmn);
if (virThreadCreate(&thr, false, daemonRunStateInit, srv) < 0) { if (virThreadCreate(&thr, false, daemonRunStateInit, dmn) < 0) {
virObjectUnref(srv); virObjectUnref(dmn);
return -1; return -1;
} }
return 0; return 0;
...@@ -1100,6 +1100,7 @@ daemonUsage(const char *argv0, bool privileged) ...@@ -1100,6 +1100,7 @@ daemonUsage(const char *argv0, bool privileged)
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
virNetDaemonPtr dmn = NULL;
virNetServerPtr srv = NULL; virNetServerPtr srv = NULL;
char *remote_config_file = NULL; char *remote_config_file = NULL;
int statuswrite = -1; int statuswrite = -1;
...@@ -1354,6 +1355,12 @@ int main(int argc, char **argv) { ...@@ -1354,6 +1355,12 @@ int main(int argc, char **argv) {
goto cleanup; goto cleanup;
} }
if (!(dmn = virNetDaemonNew()) ||
virNetDaemonAddServer(dmn, srv) < 0) {
ret = VIR_DAEMON_ERR_INIT;
goto cleanup;
}
/* Beyond this point, nothing should rely on using /* Beyond this point, nothing should rely on using
* getuid/geteuid() == 0, for privilege level checks. * getuid/geteuid() == 0, for privilege level checks.
*/ */
...@@ -1408,11 +1415,10 @@ int main(int argc, char **argv) { ...@@ -1408,11 +1415,10 @@ int main(int argc, char **argv) {
if (timeout != -1) { if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout); VIR_DEBUG("Registering shutdown timeout %d", timeout);
virNetServerAutoShutdown(srv, virNetDaemonAutoShutdown(dmn, timeout);
timeout);
} }
if ((daemonSetupSignals(srv)) < 0) { if ((daemonSetupSignals(dmn)) < 0) {
ret = VIR_DAEMON_ERR_SIGNAL; ret = VIR_DAEMON_ERR_SIGNAL;
goto cleanup; goto cleanup;
} }
...@@ -1467,7 +1473,7 @@ int main(int argc, char **argv) { ...@@ -1467,7 +1473,7 @@ int main(int argc, char **argv) {
} }
/* Initialize drivers & then start accepting new clients from network */ /* Initialize drivers & then start accepting new clients from network */
if (daemonStateInit(srv) < 0) { if (daemonStateInit(dmn) < 0) {
ret = VIR_DAEMON_ERR_INIT; ret = VIR_DAEMON_ERR_INIT;
goto cleanup; goto cleanup;
} }
...@@ -1489,7 +1495,7 @@ int main(int argc, char **argv) { ...@@ -1489,7 +1495,7 @@ int main(int argc, char **argv) {
#endif #endif
/* Run event loop. */ /* Run event loop. */
virNetServerRun(srv); virNetDaemonRun(dmn);
ret = 0; ret = 0;
...@@ -1501,7 +1507,8 @@ int main(int argc, char **argv) { ...@@ -1501,7 +1507,8 @@ int main(int argc, char **argv) {
virObjectUnref(remoteProgram); virObjectUnref(remoteProgram);
virObjectUnref(lxcProgram); virObjectUnref(lxcProgram);
virObjectUnref(qemuProgram); virObjectUnref(qemuProgram);
virNetServerClose(srv); virNetDaemonClose(dmn);
virObjectUnref(dmn);
virObjectUnref(srv); virObjectUnref(srv);
virNetlinkShutdown(); virNetlinkShutdown();
if (statuswrite != -1) { if (statuswrite != -1) {
......
...@@ -82,7 +82,9 @@ ...@@ -82,7 +82,9 @@
<ul> <ul>
<li>Daemon Startup <li>Daemon Startup
<p>The daemon initialization processing will declare itself <p>The daemon initialization processing will declare itself
as a server via a virNetServerNew() call, then use as a daemon via a virNetDaemonNew() call, then creates new server
using virNetServerNew() and adds that server to the main daemon
struct with virNetDaemonAddServer() call. It will then use
virDriverLoadModule() to find/load all known drivers, virDriverLoadModule() to find/load all known drivers,
set up an RPC server program using the <code>remoteProcs[]</code> set up an RPC server program using the <code>remoteProcs[]</code>
table via a virNetServerProgramNew() call. The table is the table via a virNetServerProgramNew() call. The table is the
......
...@@ -532,6 +532,13 @@ ...@@ -532,6 +532,13 @@
calls in parallel, with dispatch across multiple worker threads. calls in parallel, with dispatch across multiple worker threads.
</dd> </dd>
<dt><code>virNetDaemonPtr</code> (virnetdaemon.h)</dt>
<dd>The virNetDaemon APIs are used to manage a daemon process. A
deamon is a process that might expose one or more servers. It
handles most process-related details, network-related should
be part of the underlying server.
</dd>
<dt><code>virNetServerMDNSPtr</code> (virnetservermdns.h)</dt> <dt><code>virNetServerMDNSPtr</code> (virnetservermdns.h)</dt>
<dd>The virNetServerMDNS APIs are used to advertise a server <dd>The virNetServerMDNS APIs are used to advertise a server
across the local network, enabling clients to automatically across the local network, enabling clients to automatically
......
...@@ -132,6 +132,7 @@ src/rpc/virkeepalive.c ...@@ -132,6 +132,7 @@ src/rpc/virkeepalive.c
src/rpc/virnetclient.c src/rpc/virnetclient.c
src/rpc/virnetclientprogram.c src/rpc/virnetclientprogram.c
src/rpc/virnetclientstream.c src/rpc/virnetclientstream.c
src/rpc/virnetdaemon.c
src/rpc/virnetmessage.c src/rpc/virnetmessage.c
src/rpc/virnetsaslcontext.c src/rpc/virnetsaslcontext.c
src/rpc/virnetsocket.c src/rpc/virnetsocket.c
......
...@@ -2507,6 +2507,7 @@ libvirt_net_rpc_server_la_SOURCES = \ ...@@ -2507,6 +2507,7 @@ libvirt_net_rpc_server_la_SOURCES = \
rpc/virnetserverservice.h rpc/virnetserverservice.c \ rpc/virnetserverservice.h rpc/virnetserverservice.c \
rpc/virnetserverclient.h rpc/virnetserverclient.c \ rpc/virnetserverclient.h rpc/virnetserverclient.c \
rpc/virnetservermdns.h rpc/virnetservermdns.c \ rpc/virnetservermdns.h rpc/virnetservermdns.c \
rpc/virnetdaemon.h rpc/virnetdaemon.c \
rpc/virnetserver.h rpc/virnetserver.c rpc/virnetserver.h rpc/virnetserver.c
libvirt_net_rpc_server_la_CFLAGS = \ libvirt_net_rpc_server_la_CFLAGS = \
$(AVAHI_CFLAGS) \ $(AVAHI_CFLAGS) \
......
...@@ -57,6 +57,24 @@ virNetClientStreamSendPacket; ...@@ -57,6 +57,24 @@ virNetClientStreamSendPacket;
virNetClientStreamSetError; virNetClientStreamSetError;
# rpc/virnetdaemon.h
virNetDaemonAddServer;
virNetDaemonAddServerPostExec;
virNetDaemonAddShutdownInhibition;
virNetDaemonAddSignalHandler;
virNetDaemonAutoShutdown;
virNetDaemonClose;
virNetDaemonGetServer;
virNetDaemonIsPrivileged;
virNetDaemonNew;
virNetDaemonNewPostExecRestart;
virNetDaemonPreExecRestart;
virNetDaemonQuit;
virNetDaemonRemoveShutdownInhibition;
virNetDaemonRun;
virNetDaemonUpdateServices;
# rpc/virnetmessage.h # rpc/virnetmessage.h
virNetMessageClear; virNetMessageClear;
virNetMessageDecodeHeader; virNetMessageDecodeHeader;
...@@ -80,18 +98,16 @@ xdr_virNetMessageError; ...@@ -80,18 +98,16 @@ xdr_virNetMessageError;
virNetServerAddClient; virNetServerAddClient;
virNetServerAddProgram; virNetServerAddProgram;
virNetServerAddService; virNetServerAddService;
virNetServerAddShutdownInhibition;
virNetServerAddSignalHandler;
virNetServerAutoShutdown;
virNetServerClose; virNetServerClose;
virNetServerIsPrivileged; virNetServerHasClients;
virNetServerKeepAliveRequired; virNetServerKeepAliveRequired;
virNetServerNew; virNetServerNew;
virNetServerNewPostExecRestart; virNetServerNewPostExecRestart;
virNetServerPreExecRestart; virNetServerPreExecRestart;
virNetServerQuit; virNetServerProcessClients;
virNetServerRemoveShutdownInhibition; virNetServerStart;
virNetServerRun; virNetServerTrackCompletedAuth;
virNetServerTrackPendingAuth;
virNetServerUpdateServices; virNetServerUpdateServices;
......
/* /*
* lock_daemon.c: lock management daemon * lock_daemon.c: lock management daemon
* *
* Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006-2015 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "virlog.h" #include "virlog.h"
#include "viralloc.h" #include "viralloc.h"
#include "virconf.h" #include "virconf.h"
#include "rpc/virnetdaemon.h"
#include "rpc/virnetserver.h" #include "rpc/virnetserver.h"
#include "virrandom.h" #include "virrandom.h"
#include "virhash.h" #include "virhash.h"
...@@ -60,6 +61,7 @@ VIR_LOG_INIT("locking.lock_daemon"); ...@@ -60,6 +61,7 @@ VIR_LOG_INIT("locking.lock_daemon");
struct _virLockDaemon { struct _virLockDaemon {
virMutex lock; virMutex lock;
virNetDaemonPtr dmn;
virNetServerPtr srv; virNetServerPtr srv;
virHashTablePtr lockspaces; virHashTablePtr lockspaces;
virLockSpacePtr defaultLockspace; virLockSpacePtr defaultLockspace;
...@@ -118,6 +120,7 @@ virLockDaemonFree(virLockDaemonPtr lockd) ...@@ -118,6 +120,7 @@ virLockDaemonFree(virLockDaemonPtr lockd)
return; return;
virObjectUnref(lockd->srv); virObjectUnref(lockd->srv);
virObjectUnref(lockd->dmn);
virHashFree(lockd->lockspaces); virHashFree(lockd->lockspaces);
virLockSpaceFree(lockd->defaultLockspace); virLockSpaceFree(lockd->defaultLockspace);
...@@ -155,6 +158,10 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged) ...@@ -155,6 +158,10 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged)
(void*)(intptr_t)(privileged ? 0x1 : 0x0)))) (void*)(intptr_t)(privileged ? 0x1 : 0x0))))
goto error; goto error;
if (!(lockd->dmn = virNetDaemonNew()) ||
virNetDaemonAddServer(lockd->dmn, lockd->srv) < 0)
goto error;
if (!(lockd->lockspaces = virHashCreate(VIR_LOCK_DAEMON_NUM_LOCKSPACES, if (!(lockd->lockspaces = virHashCreate(VIR_LOCK_DAEMON_NUM_LOCKSPACES,
virLockDaemonLockSpaceDataFree))) virLockDaemonLockSpaceDataFree)))
goto error; goto error;
...@@ -230,18 +237,29 @@ virLockDaemonNewPostExecRestart(virJSONValuePtr object, bool privileged) ...@@ -230,18 +237,29 @@ virLockDaemonNewPostExecRestart(virJSONValuePtr object, bool privileged)
} }
} }
if (!(child = virJSONValueObjectGet(object, "server"))) { if (virJSONValueObjectHasKey(object, "daemon")) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", if (!(child = virJSONValueObjectGet(object, "daemon"))) {
_("Missing server data from JSON file")); virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
goto error; _("Malformed daemon data from JSON file"));
goto error;
}
} else {
if (!(child = virJSONValueObjectGet(object, "server"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing server data from JSON file"));
goto error;
}
} }
if (!(lockd->srv = virNetServerNewPostExecRestart(child, if (!(lockd->dmn = virNetDaemonNewPostExecRestart(child)))
virLockDaemonClientNew, goto error;
virLockDaemonClientNewPostExecRestart,
virLockDaemonClientPreExecRestart, if (!(lockd->srv = virNetDaemonAddServerPostExec(lockd->dmn,
virLockDaemonClientFree, virLockDaemonClientNew,
(void*)(intptr_t)(privileged ? 0x1 : 0x0)))) virLockDaemonClientNewPostExecRestart,
virLockDaemonClientPreExecRestart,
virLockDaemonClientFree,
(void*)(intptr_t)(privileged ? 0x1 : 0x0))))
goto error; goto error;
return lockd; return lockd;
...@@ -529,32 +547,32 @@ virLockDaemonVersion(const char *argv0) ...@@ -529,32 +547,32 @@ virLockDaemonVersion(const char *argv0)
} }
static void static void
virLockDaemonShutdownHandler(virNetServerPtr srv, virLockDaemonShutdownHandler(virNetDaemonPtr dmn,
siginfo_t *sig ATTRIBUTE_UNUSED, siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
virNetServerQuit(srv); virNetDaemonQuit(dmn);
} }
static void static void
virLockDaemonExecRestartHandler(virNetServerPtr srv, virLockDaemonExecRestartHandler(virNetDaemonPtr dmn,
siginfo_t *sig ATTRIBUTE_UNUSED, siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
execRestart = true; execRestart = true;
virNetServerQuit(srv); virNetDaemonQuit(dmn);
} }
static int static int
virLockDaemonSetupSignals(virNetServerPtr srv) virLockDaemonSetupSignals(virNetDaemonPtr dmn)
{ {
if (virNetServerAddSignalHandler(srv, SIGINT, virLockDaemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGINT, virLockDaemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGQUIT, virLockDaemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGQUIT, virLockDaemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGTERM, virLockDaemonShutdownHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGTERM, virLockDaemonShutdownHandler, NULL) < 0)
return -1; return -1;
if (virNetServerAddSignalHandler(srv, SIGUSR1, virLockDaemonExecRestartHandler, NULL) < 0) if (virNetDaemonAddSignalHandler(dmn, SIGUSR1, virLockDaemonExecRestartHandler, NULL) < 0)
return -1; return -1;
return 0; return 0;
} }
...@@ -966,7 +984,7 @@ virLockDaemonPostExecRestart(const char *state_file, ...@@ -966,7 +984,7 @@ virLockDaemonPostExecRestart(const char *state_file,
static int static int
virLockDaemonPreExecRestart(const char *state_file, virLockDaemonPreExecRestart(const char *state_file,
virNetServerPtr srv, virNetDaemonPtr dmn,
char **argv) char **argv)
{ {
virJSONValuePtr child; virJSONValuePtr child;
...@@ -982,10 +1000,10 @@ virLockDaemonPreExecRestart(const char *state_file, ...@@ -982,10 +1000,10 @@ virLockDaemonPreExecRestart(const char *state_file,
if (!(object = virJSONValueNewObject())) if (!(object = virJSONValueNewObject()))
goto cleanup; goto cleanup;
if (!(child = virNetServerPreExecRestart(srv))) if (!(child = virNetDaemonPreExecRestart(dmn)))
goto cleanup; goto cleanup;
if (virJSONValueObjectAppend(object, "server", child) < 0) { if (virJSONValueObjectAppend(object, "daemon", child) < 0) {
virJSONValueFree(child); virJSONValueFree(child);
goto cleanup; goto cleanup;
} }
...@@ -1350,11 +1368,11 @@ int main(int argc, char **argv) { ...@@ -1350,11 +1368,11 @@ int main(int argc, char **argv) {
if (timeout != -1) { if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout); VIR_DEBUG("Registering shutdown timeout %d", timeout);
virNetServerAutoShutdown(lockDaemon->srv, virNetDaemonAutoShutdown(lockDaemon->dmn,
timeout); timeout);
} }
if ((virLockDaemonSetupSignals(lockDaemon->srv)) < 0) { if ((virLockDaemonSetupSignals(lockDaemon->dmn)) < 0) {
ret = VIR_LOCK_DAEMON_ERR_SIGNAL; ret = VIR_LOCK_DAEMON_ERR_SIGNAL;
goto cleanup; goto cleanup;
} }
...@@ -1366,6 +1384,7 @@ int main(int argc, char **argv) { ...@@ -1366,6 +1384,7 @@ int main(int argc, char **argv) {
ret = VIR_LOCK_DAEMON_ERR_INIT; ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup; goto cleanup;
} }
if (virNetServerAddProgram(lockDaemon->srv, lockProgram) < 0) { if (virNetServerAddProgram(lockDaemon->srv, lockProgram) < 0) {
ret = VIR_LOCK_DAEMON_ERR_INIT; ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup; goto cleanup;
...@@ -1389,12 +1408,12 @@ int main(int argc, char **argv) { ...@@ -1389,12 +1408,12 @@ int main(int argc, char **argv) {
/* Start accepting new clients from network */ /* Start accepting new clients from network */
virNetServerUpdateServices(lockDaemon->srv, true); virNetDaemonUpdateServices(lockDaemon->dmn, true);
virNetServerRun(lockDaemon->srv); virNetDaemonRun(lockDaemon->dmn);
if (execRestart && if (execRestart &&
virLockDaemonPreExecRestart(state_file, virLockDaemonPreExecRestart(state_file,
lockDaemon->srv, lockDaemon->dmn,
argv) < 0) argv) < 0)
ret = VIR_LOCK_DAEMON_ERR_REEXEC; ret = VIR_LOCK_DAEMON_ERR_REEXEC;
else else
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "viralloc.h" #include "viralloc.h"
#include "virerror.h" #include "virerror.h"
#include "virlog.h" #include "virlog.h"
#include "rpc/virnetserver.h" #include "rpc/virnetdaemon.h"
#include "configmake.h" #include "configmake.h"
#include "virstring.h" #include "virstring.h"
#include "virutil.h" #include "virutil.h"
......
/* /*
* lock_daemon_dispatch.c: lock management daemon dispatch * lock_daemon_dispatch.c: lock management daemon dispatch
* *
* Copyright (C) 2006-2012 Red Hat, Inc. * Copyright (C) 2006-2015 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <config.h> #include <config.h>
#include "rpc/virnetserver.h" #include "rpc/virnetdaemon.h"
#include "rpc/virnetserverclient.h" #include "rpc/virnetserverclient.h"
#include "virlog.h" #include "virlog.h"
#include "virstring.h" #include "virstring.h"
......
/* /*
* Copyright (C) 2010-2014 Red Hat, Inc. * Copyright (C) 2010-2015 Red Hat, Inc.
* Copyright IBM Corp. 2008 * Copyright IBM Corp. 2008
* *
* lxc_controller.c: linux container process controller * lxc_controller.c: linux container process controller
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
#include "virprocess.h" #include "virprocess.h"
#include "virnuma.h" #include "virnuma.h"
#include "virdbus.h" #include "virdbus.h"
#include "rpc/virnetserver.h" #include "rpc/virnetdaemon.h"
#include "virstring.h" #include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_LXC #define VIR_FROM_THIS VIR_FROM_LXC
...@@ -93,7 +93,7 @@ struct _virLXCControllerConsole { ...@@ -93,7 +93,7 @@ struct _virLXCControllerConsole {
size_t fromContLen; size_t fromContLen;
char fromContBuf[1024]; char fromContBuf[1024];
virNetServerPtr server; virNetDaemonPtr daemon;
}; };
typedef struct _virLXCController virLXCController; typedef struct _virLXCController virLXCController;
...@@ -128,8 +128,7 @@ struct _virLXCController { ...@@ -128,8 +128,7 @@ struct _virLXCController {
virSecurityManagerPtr securityManager; virSecurityManagerPtr securityManager;
/* Server socket */ virNetDaemonPtr daemon;
virNetServerPtr server;
bool firstClient; bool firstClient;
virNetServerClientPtr client; virNetServerClientPtr client;
virNetServerProgramPtr prog; virNetServerProgramPtr prog;
...@@ -152,7 +151,7 @@ static void virLXCControllerQuitTimer(int timer ATTRIBUTE_UNUSED, void *opaque) ...@@ -152,7 +151,7 @@ static void virLXCControllerQuitTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
virLXCControllerPtr ctrl = opaque; virLXCControllerPtr ctrl = opaque;
VIR_DEBUG("Triggering event loop quit"); VIR_DEBUG("Triggering event loop quit");
virNetServerQuit(ctrl->server); virNetDaemonQuit(ctrl->daemon);
} }
...@@ -283,7 +282,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) ...@@ -283,7 +282,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
if (ctrl->timerShutdown != -1) if (ctrl->timerShutdown != -1)
virEventRemoveTimeout(ctrl->timerShutdown); virEventRemoveTimeout(ctrl->timerShutdown);
virObjectUnref(ctrl->server); virObjectUnref(ctrl->daemon);
virLXCControllerFreeFuse(ctrl); virLXCControllerFreeFuse(ctrl);
VIR_FREE(ctrl->nbdpids); VIR_FREE(ctrl->nbdpids);
...@@ -301,7 +300,7 @@ static int virLXCControllerAddConsole(virLXCControllerPtr ctrl, ...@@ -301,7 +300,7 @@ static int virLXCControllerAddConsole(virLXCControllerPtr ctrl,
{ {
if (VIR_EXPAND_N(ctrl->consoles, ctrl->nconsoles, 1) < 0) if (VIR_EXPAND_N(ctrl->consoles, ctrl->nconsoles, 1) < 0)
return -1; return -1;
ctrl->consoles[ctrl->nconsoles-1].server = ctrl->server; ctrl->consoles[ctrl->nconsoles-1].daemon = ctrl->daemon;
ctrl->consoles[ctrl->nconsoles-1].hostFd = hostFd; ctrl->consoles[ctrl->nconsoles-1].hostFd = hostFd;
ctrl->consoles[ctrl->nconsoles-1].hostWatch = -1; ctrl->consoles[ctrl->nconsoles-1].hostWatch = -1;
...@@ -902,6 +901,7 @@ static void *virLXCControllerClientPrivateNew(virNetServerClientPtr client, ...@@ -902,6 +901,7 @@ static void *virLXCControllerClientPrivateNew(virNetServerClientPtr client,
static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
{ {
virNetServerPtr srv = NULL;
virNetServerServicePtr svc = NULL; virNetServerServicePtr svc = NULL;
char *sockpath; char *sockpath;
...@@ -909,13 +909,13 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) ...@@ -909,13 +909,13 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
LXC_STATE_DIR, ctrl->name) < 0) LXC_STATE_DIR, ctrl->name) < 0)
return -1; return -1;
if (!(ctrl->server = virNetServerNew(0, 0, 0, 1, if (!(srv = virNetServerNew(0, 0, 0, 1,
0, -1, 0, false, 0, -1, 0, false,
NULL, NULL,
virLXCControllerClientPrivateNew, virLXCControllerClientPrivateNew,
NULL, NULL,
virLXCControllerClientPrivateFree, virLXCControllerClientPrivateFree,
ctrl))) ctrl)))
goto error; goto error;
if (virSecurityManagerSetSocketLabel(ctrl->securityManager, ctrl->def) < 0) if (virSecurityManagerSetSocketLabel(ctrl->securityManager, ctrl->def) < 0)
...@@ -936,7 +936,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) ...@@ -936,7 +936,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
if (virSecurityManagerClearSocketLabel(ctrl->securityManager, ctrl->def) < 0) if (virSecurityManagerClearSocketLabel(ctrl->securityManager, ctrl->def) < 0)
goto error; goto error;
if (virNetServerAddService(ctrl->server, svc, NULL) < 0) if (virNetServerAddService(srv, svc, NULL) < 0)
goto error; goto error;
virObjectUnref(svc); virObjectUnref(svc);
svc = NULL; svc = NULL;
...@@ -947,14 +947,19 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) ...@@ -947,14 +947,19 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
virLXCMonitorNProcs))) virLXCMonitorNProcs)))
goto error; goto error;
virNetServerUpdateServices(ctrl->server, true); if (!(ctrl->daemon = virNetDaemonNew()) ||
virNetDaemonAddServer(ctrl->daemon, srv) < 0)
goto error;
virNetDaemonUpdateServices(ctrl->daemon, true);
VIR_FREE(sockpath); VIR_FREE(sockpath);
return 0; return 0;
error: error:
VIR_FREE(sockpath); VIR_FREE(sockpath);
virObjectUnref(ctrl->server); virObjectUnref(srv);
ctrl->server = NULL; virObjectUnref(ctrl->daemon);
ctrl->daemon = NULL;
virObjectUnref(svc); virObjectUnref(svc);
return -1; return -1;
} }
...@@ -982,7 +987,7 @@ static bool wantReboot; ...@@ -982,7 +987,7 @@ static bool wantReboot;
static virMutex lock = VIR_MUTEX_INITIALIZER; static virMutex lock = VIR_MUTEX_INITIALIZER;
static void virLXCControllerSignalChildIO(virNetServerPtr server, static void virLXCControllerSignalChildIO(virNetDaemonPtr daemon,
siginfo_t *info ATTRIBUTE_UNUSED, siginfo_t *info ATTRIBUTE_UNUSED,
void *opaque) void *opaque)
{ {
...@@ -993,7 +998,7 @@ static void virLXCControllerSignalChildIO(virNetServerPtr server, ...@@ -993,7 +998,7 @@ static void virLXCControllerSignalChildIO(virNetServerPtr server,
ret = waitpid(-1, &status, WNOHANG); ret = waitpid(-1, &status, WNOHANG);
VIR_DEBUG("Got sig child %d vs %lld", ret, (unsigned long long)ctrl->initpid); VIR_DEBUG("Got sig child %d vs %lld", ret, (unsigned long long)ctrl->initpid);
if (ret == ctrl->initpid) { if (ret == ctrl->initpid) {
virNetServerQuit(server); virNetDaemonQuit(daemon);
virMutexLock(&lock); virMutexLock(&lock);
if (WIFSIGNALED(status) && if (WIFSIGNALED(status) &&
WTERMSIG(status) == SIGHUP) { WTERMSIG(status) == SIGHUP) {
...@@ -1052,7 +1057,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol ...@@ -1052,7 +1057,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
VIR_DEBUG(":fail"); VIR_DEBUG(":fail");
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to add epoll fd")); _("Unable to add epoll fd"));
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
goto cleanup; goto cleanup;
} }
console->hostEpoll = events; console->hostEpoll = events;
...@@ -1064,7 +1069,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol ...@@ -1064,7 +1069,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to remove epoll fd")); _("Unable to remove epoll fd"));
VIR_DEBUG(":fail"); VIR_DEBUG(":fail");
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
goto cleanup; goto cleanup;
} }
console->hostEpoll = 0; console->hostEpoll = 0;
...@@ -1090,7 +1095,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol ...@@ -1090,7 +1095,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to add epoll fd")); _("Unable to add epoll fd"));
VIR_DEBUG(":fail"); VIR_DEBUG(":fail");
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
goto cleanup; goto cleanup;
} }
console->contEpoll = events; console->contEpoll = events;
...@@ -1102,7 +1107,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol ...@@ -1102,7 +1107,7 @@ static void virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to remove epoll fd")); _("Unable to remove epoll fd"));
VIR_DEBUG(":fail"); VIR_DEBUG(":fail");
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
goto cleanup; goto cleanup;
} }
console->contEpoll = 0; console->contEpoll = 0;
...@@ -1131,7 +1136,7 @@ static void virLXCControllerConsoleEPoll(int watch, int fd, int events, void *op ...@@ -1131,7 +1136,7 @@ static void virLXCControllerConsoleEPoll(int watch, int fd, int events, void *op
continue; continue;
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to wait on epoll")); _("Unable to wait on epoll"));
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
goto cleanup; goto cleanup;
} }
...@@ -1244,7 +1249,7 @@ static void virLXCControllerConsoleIO(int watch, int fd, int events, void *opaqu ...@@ -1244,7 +1249,7 @@ static void virLXCControllerConsoleIO(int watch, int fd, int events, void *opaqu
virEventRemoveHandle(console->contWatch); virEventRemoveHandle(console->contWatch);
virEventRemoveHandle(console->hostWatch); virEventRemoveHandle(console->hostWatch);
console->contWatch = console->hostWatch = -1; console->contWatch = console->hostWatch = -1;
virNetServerQuit(console->server); virNetDaemonQuit(console->daemon);
virMutexUnlock(&lock); virMutexUnlock(&lock);
} }
...@@ -1264,7 +1269,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) ...@@ -1264,7 +1269,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
int rc = -1; int rc = -1;
size_t i; size_t i;
if (virNetServerAddSignalHandler(ctrl->server, if (virNetDaemonAddSignalHandler(ctrl->daemon,
SIGCHLD, SIGCHLD,
virLXCControllerSignalChildIO, virLXCControllerSignalChildIO,
ctrl) < 0) ctrl) < 0)
...@@ -1310,7 +1315,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) ...@@ -1310,7 +1315,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
} }
} }
virNetServerRun(ctrl->server); virNetDaemonRun(ctrl->daemon);
err = virGetLastError(); err = virGetLastError();
if (!err || err->code == VIR_ERR_OK) if (!err || err->code == VIR_ERR_OK)
...@@ -2284,7 +2289,7 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl, ...@@ -2284,7 +2289,7 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl,
VIR_DEBUG("Waiting for client to complete dispatch"); VIR_DEBUG("Waiting for client to complete dispatch");
ctrl->inShutdown = true; ctrl->inShutdown = true;
virNetServerClientDelayedClose(ctrl->client); virNetServerClientDelayedClose(ctrl->client);
virNetServerRun(ctrl->server); virNetDaemonRun(ctrl->daemon);
} }
VIR_DEBUG("Client has gone away"); VIR_DEBUG("Client has gone away");
return 0; return 0;
......
/*
* virnetdaemon.c
*
* Copyright (C) 2015 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: Martin Kletzander <mkletzan@redhat.com>
*/
#include <config.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "virnetdaemon.h"
#include "virlog.h"
#include "viralloc.h"
#include "virerror.h"
#include "virthread.h"
#include "virthreadpool.h"
#include "virutil.h"
#include "virfile.h"
#include "virnetserver.h"
#include "virnetservermdns.h"
#include "virdbus.h"
#include "virstring.h"
#include "virsystemd.h"
#ifndef SA_SIGINFO
# define SA_SIGINFO 0
#endif
#define VIR_FROM_THIS VIR_FROM_RPC
VIR_LOG_INIT("rpc.netserver");
typedef struct _virNetDaemonSignal virNetDaemonSignal;
typedef virNetDaemonSignal *virNetDaemonSignalPtr;
struct _virNetDaemonSignal {
struct sigaction oldaction;
int signum;
virNetDaemonSignalFunc func;
void *opaque;
};
struct _virNetDaemon {
virObjectLockable parent;
bool privileged;
size_t nsignals;
virNetDaemonSignalPtr *signals;
int sigread;
int sigwrite;
int sigwatch;
size_t nservers;
virNetServerPtr *servers;
virJSONValuePtr srvObject;
bool quit;
unsigned int autoShutdownTimeout;
size_t autoShutdownInhibitions;
bool autoShutdownCallingInhibit;
int autoShutdownInhibitFd;
};
static virClassPtr virNetDaemonClass;
static void
virNetDaemonDispose(void *obj)
{
virNetDaemonPtr dmn = obj;
size_t i;
VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd);
for (i = 0; i < dmn->nsignals; i++) {
sigaction(dmn->signals[i]->signum, &dmn->signals[i]->oldaction, NULL);
VIR_FREE(dmn->signals[i]);
}
VIR_FREE(dmn->signals);
VIR_FORCE_CLOSE(dmn->sigread);
VIR_FORCE_CLOSE(dmn->sigwrite);
if (dmn->sigwatch > 0)
virEventRemoveHandle(dmn->sigwatch);
for (i = 0; i < dmn->nservers; i++)
virObjectUnref(dmn->servers[i]);
VIR_FREE(dmn->servers);
virJSONValueFree(dmn->srvObject);
}
static int
virNetDaemonOnceInit(void)
{
if (!(virNetDaemonClass = virClassNew(virClassForObjectLockable(),
"virNetDaemon",
sizeof(virNetDaemon),
virNetDaemonDispose)))
return -1;
return 0;
}
VIR_ONCE_GLOBAL_INIT(virNetDaemon)
virNetDaemonPtr
virNetDaemonNew(void)
{
virNetDaemonPtr dmn;
struct sigaction sig_action;
if (virNetDaemonInitialize() < 0)
return NULL;
if (!(dmn = virObjectLockableNew(virNetDaemonClass)))
return NULL;
dmn->sigwrite = dmn->sigread = -1;
dmn->privileged = geteuid() == 0;
dmn->autoShutdownInhibitFd = -1;
if (virEventRegisterDefaultImpl() < 0)
goto error;
memset(&sig_action, 0, sizeof(sig_action));
sig_action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sig_action, NULL);
return dmn;
error:
virObjectUnref(dmn);
return NULL;
}
int
virNetDaemonAddServer(virNetDaemonPtr dmn, virNetServerPtr srv)
{
int ret = -1;
virObjectLock(dmn);
if (VIR_APPEND_ELEMENT(dmn->servers, dmn->nservers, srv) < 0)
goto cleanup;
virObjectRef(srv);
ret = dmn->nservers - 1;
cleanup:
virObjectUnlock(dmn);
return ret;
}
/*
* Separate function merely for the purpose of unified error
* reporting.
*/
static virNetServerPtr
virNetDaemonGetServerInternal(virNetDaemonPtr dmn,
int subServerID)
{
if (subServerID < 0 || subServerID >= dmn->nservers) {
virReportError(VIR_ERR_INVALID_ARG,
_("Invalid server ID: %d"),
subServerID);
return NULL;
}
return virObjectRef(dmn->servers[subServerID]);
}
virNetServerPtr
virNetDaemonGetServer(virNetDaemonPtr dmn,
int subServerID)
{
virNetServerPtr srv = NULL;
virObjectLock(dmn);
srv = virNetDaemonGetServerInternal(dmn, subServerID);
virObjectUnlock(dmn);
return srv;
}
virNetServerPtr
virNetDaemonAddServerPostExec(virNetDaemonPtr dmn,
virNetServerClientPrivNew clientPrivNew,
virNetServerClientPrivNewPostExecRestart clientPrivNewPostExecRestart,
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
virFreeCallback clientPrivFree,
void *clientPrivOpaque)
{
virJSONValuePtr object = NULL;
virNetServerPtr srv = NULL;
virObjectLock(dmn);
if (!dmn->srvObject) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot add more servers post-exec than "
"there were pre-exec"));
goto error;
}
if (virJSONValueIsArray(dmn->srvObject)) {
object = virJSONValueArraySteal(dmn->srvObject, 0);
if (virJSONValueArraySize(dmn->srvObject) == 0) {
virJSONValueFree(dmn->srvObject);
dmn->srvObject = NULL;
}
} else {
object = dmn->srvObject;
dmn->srvObject = NULL;
}
srv = virNetServerNewPostExecRestart(object,
clientPrivNew,
clientPrivNewPostExecRestart,
clientPrivPreExecRestart,
clientPrivFree,
clientPrivOpaque);
if (!srv || VIR_APPEND_ELEMENT_COPY(dmn->servers, dmn->nservers, srv) < 0)
goto error;
virJSONValueFree(object);
virObjectUnlock(dmn);
return srv;
error:
virObjectUnlock(dmn);
virObjectUnref(srv);
virJSONValueFree(object);
return NULL;
}
virNetDaemonPtr
virNetDaemonNewPostExecRestart(virJSONValuePtr object)
{
virNetDaemonPtr dmn = NULL;
virJSONValuePtr servers = virJSONValueObjectGet(object, "servers");
bool new_version = virJSONValueObjectHasKey(object, "servers");
if (!(dmn = virNetDaemonNew()))
goto error;
if (new_version && !servers) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed servers data in JSON document"));
goto error;
}
if (!(dmn->srvObject = virJSONValueCopy(new_version ? servers : object)))
goto error;
return dmn;
error:
virObjectUnref(dmn);
return NULL;
}
virJSONValuePtr
virNetDaemonPreExecRestart(virNetDaemonPtr dmn)
{
virJSONValuePtr object, srvArray = NULL;
size_t i;
virObjectLock(dmn);
if (!(object = virJSONValueNewObject()))
goto error;
if (!(srvArray = virJSONValueNewArray()) ||
virJSONValueObjectAppend(object, "servers", srvArray) < 0)
goto error;
for (i = 0; i < dmn->nservers; i++) {
virJSONValuePtr srvJSON = NULL;
srvJSON = virNetServerPreExecRestart(dmn->servers[i]);
if (!srvJSON)
goto error;
if (virJSONValueArrayAppend(srvArray, srvJSON) < 0) {
virJSONValueFree(srvJSON);
goto error;
}
}
virObjectUnlock(dmn);
return object;
error:
virJSONValueFree(object);
virJSONValueFree(srvArray);
virObjectUnlock(dmn);
return NULL;
}
bool
virNetDaemonIsPrivileged(virNetDaemonPtr dmn)
{
bool priv;
virObjectLock(dmn);
priv = dmn->privileged;
virObjectUnlock(dmn);
return priv;
}
void
virNetDaemonAutoShutdown(virNetDaemonPtr dmn,
unsigned int timeout)
{
virObjectLock(dmn);
dmn->autoShutdownTimeout = timeout;
virObjectUnlock(dmn);
}
#if defined(HAVE_DBUS) && defined(DBUS_TYPE_UNIX_FD)
static void
virNetDaemonGotInhibitReply(DBusPendingCall *pending,
void *opaque)
{
virNetDaemonPtr dmn = opaque;
DBusMessage *reply;
int fd;
virObjectLock(dmn);
dmn->autoShutdownCallingInhibit = false;
VIR_DEBUG("dmn=%p", dmn);
reply = dbus_pending_call_steal_reply(pending);
if (reply == NULL)
goto cleanup;
if (dbus_message_get_args(reply, NULL,
DBUS_TYPE_UNIX_FD, &fd,
DBUS_TYPE_INVALID)) {
if (dmn->autoShutdownInhibitions) {
dmn->autoShutdownInhibitFd = fd;
} else {
/* We stopped the last VM since we made the inhibit call */
VIR_FORCE_CLOSE(fd);
}
}
dbus_message_unref(reply);
cleanup:
virObjectUnlock(dmn);
}
/* As per: http://www.freedesktop.org/wiki/Software/systemd/inhibit */
static void
virNetDaemonCallInhibit(virNetDaemonPtr dmn,
const char *what,
const char *who,
const char *why,
const char *mode)
{
DBusMessage *message;
DBusPendingCall *pendingReply;
DBusConnection *systemBus;
VIR_DEBUG("dmn=%p what=%s who=%s why=%s mode=%s",
dmn, NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
if (!(systemBus = virDBusGetSystemBus()))
return;
/* Only one outstanding call at a time */
if (dmn->autoShutdownCallingInhibit)
return;
message = dbus_message_new_method_call("org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Inhibit");
if (message == NULL)
return;
dbus_message_append_args(message,
DBUS_TYPE_STRING, &what,
DBUS_TYPE_STRING, &who,
DBUS_TYPE_STRING, &why,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
pendingReply = NULL;
if (dbus_connection_send_with_reply(systemBus, message,
&pendingReply,
25*1000)) {
dbus_pending_call_set_notify(pendingReply,
virNetDaemonGotInhibitReply,
dmn, NULL);
dmn->autoShutdownCallingInhibit = true;
}
dbus_message_unref(message);
}
#endif
void
virNetDaemonAddShutdownInhibition(virNetDaemonPtr dmn)
{
virObjectLock(dmn);
dmn->autoShutdownInhibitions++;
VIR_DEBUG("dmn=%p inhibitions=%zu", dmn, dmn->autoShutdownInhibitions);
#if defined(HAVE_DBUS) && defined(DBUS_TYPE_UNIX_FD)
if (dmn->autoShutdownInhibitions == 1)
virNetDaemonCallInhibit(dmn,
"shutdown",
_("Libvirt"),
_("Virtual machines need to be saved"),
"delay");
#endif
virObjectUnlock(dmn);
}
void
virNetDaemonRemoveShutdownInhibition(virNetDaemonPtr dmn)
{
virObjectLock(dmn);
dmn->autoShutdownInhibitions--;
VIR_DEBUG("dmn=%p inhibitions=%zu", dmn, dmn->autoShutdownInhibitions);
if (dmn->autoShutdownInhibitions == 0)
VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd);
virObjectUnlock(dmn);
}
static sig_atomic_t sigErrors;
static int sigLastErrno;
static int sigWrite = -1;
static void
virNetDaemonSignalHandler(int sig, siginfo_t * siginfo,
void* context ATTRIBUTE_UNUSED)
{
int origerrno;
int r;
siginfo_t tmp;
if (SA_SIGINFO)
tmp = *siginfo;
else
memset(&tmp, 0, sizeof(tmp));
/* set the sig num in the struct */
tmp.si_signo = sig;
origerrno = errno;
r = safewrite(sigWrite, &tmp, sizeof(tmp));
if (r == -1) {
sigErrors++;
sigLastErrno = errno;
}
errno = origerrno;
}
static void
virNetDaemonSignalEvent(int watch,
int fd ATTRIBUTE_UNUSED,
int events ATTRIBUTE_UNUSED,
void *opaque)
{
virNetDaemonPtr dmn = opaque;
siginfo_t siginfo;
size_t i;
virObjectLock(dmn);
if (saferead(dmn->sigread, &siginfo, sizeof(siginfo)) != sizeof(siginfo)) {
virReportSystemError(errno, "%s",
_("Failed to read from signal pipe"));
virEventRemoveHandle(watch);
dmn->sigwatch = -1;
goto cleanup;
}
for (i = 0; i < dmn->nsignals; i++) {
if (siginfo.si_signo == dmn->signals[i]->signum) {
virNetDaemonSignalFunc func = dmn->signals[i]->func;
void *funcopaque = dmn->signals[i]->opaque;
virObjectUnlock(dmn);
func(dmn, &siginfo, funcopaque);
return;
}
}
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected signal received: %d"), siginfo.si_signo);
cleanup:
virObjectUnlock(dmn);
}
static int
virNetDaemonSignalSetup(virNetDaemonPtr dmn)
{
int fds[2] = { -1, -1 };
if (dmn->sigwrite != -1)
return 0;
if (pipe2(fds, O_CLOEXEC|O_NONBLOCK) < 0) {
virReportSystemError(errno, "%s",
_("Unable to create signal pipe"));
return -1;
}
if ((dmn->sigwatch = virEventAddHandle(fds[0],
VIR_EVENT_HANDLE_READABLE,
virNetDaemonSignalEvent,
dmn, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to add signal handle watch"));
goto error;
}
dmn->sigread = fds[0];
dmn->sigwrite = fds[1];
sigWrite = fds[1];
return 0;
error:
VIR_FORCE_CLOSE(fds[0]);
VIR_FORCE_CLOSE(fds[1]);
return -1;
}
int
virNetDaemonAddSignalHandler(virNetDaemonPtr dmn,
int signum,
virNetDaemonSignalFunc func,
void *opaque)
{
virNetDaemonSignalPtr sigdata = NULL;
struct sigaction sig_action;
virObjectLock(dmn);
if (virNetDaemonSignalSetup(dmn) < 0)
goto error;
if (VIR_EXPAND_N(dmn->signals, dmn->nsignals, 1) < 0)
goto error;
if (VIR_ALLOC(sigdata) < 0)
goto error;
sigdata->signum = signum;
sigdata->func = func;
sigdata->opaque = opaque;
memset(&sig_action, 0, sizeof(sig_action));
sig_action.sa_sigaction = virNetDaemonSignalHandler;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(signum, &sig_action, &sigdata->oldaction);
dmn->signals[dmn->nsignals-1] = sigdata;
virObjectUnlock(dmn);
return 0;
error:
VIR_FREE(sigdata);
virObjectUnlock(dmn);
return -1;
}
static void
virNetDaemonAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
void *opaque)
{
virNetDaemonPtr dmn = opaque;
virObjectLock(dmn);
if (!dmn->autoShutdownInhibitions) {
VIR_DEBUG("Automatic shutdown triggered");
dmn->quit = true;
}
virObjectUnlock(dmn);
}
void
virNetDaemonUpdateServices(virNetDaemonPtr dmn,
bool enabled)
{
size_t i;
virObjectLock(dmn);
for (i = 0; i < dmn->nservers; i++)
virNetServerUpdateServices(dmn->servers[i], enabled);
virObjectUnlock(dmn);
}
void
virNetDaemonRun(virNetDaemonPtr dmn)
{
int timerid = -1;
bool timerActive = false;
size_t i;
virObjectLock(dmn);
if (dmn->srvObject) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Not all servers restored, cannot run server"));
goto cleanup;
}
for (i = 0; i < dmn->nservers; i++) {
if (virNetServerStart(dmn->servers[i]) < 0)
goto cleanup;
}
dmn->quit = false;
if (dmn->autoShutdownTimeout &&
(timerid = virEventAddTimeout(-1,
virNetDaemonAutoShutdownTimer,
dmn, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to register shutdown timeout"));
goto cleanup;
}
/* We are accepting connections now. Notify systemd
* so it can start dependent services. */
virSystemdNotifyStartup();
VIR_DEBUG("dmn=%p quit=%d", dmn, dmn->quit);
while (!dmn->quit) {
/* A shutdown timeout is specified, so check
* if any drivers have active state, if not
* shutdown after timeout seconds
*/
if (dmn->autoShutdownTimeout) {
if (timerActive) {
for (i = 0; i < dmn->nservers; i++) {
if (virNetServerHasClients(dmn->servers[i])) {
VIR_DEBUG("Deactivating shutdown timer %d", timerid);
virEventUpdateTimeout(timerid, -1);
timerActive = false;
break;
}
}
} else {
for (i = 0; i < dmn->nservers; i++) {
if (!virNetServerHasClients(dmn->servers[i])) {
VIR_DEBUG("Activating shutdown timer %d", timerid);
virEventUpdateTimeout(timerid,
dmn->autoShutdownTimeout * 1000);
timerActive = true;
break;
}
}
}
}
virObjectUnlock(dmn);
if (virEventRunDefaultImpl() < 0) {
virObjectLock(dmn);
VIR_DEBUG("Loop iteration error, exiting");
break;
}
virObjectLock(dmn);
for (i = 0; i < dmn->nservers; i++)
virNetServerProcessClients(dmn->servers[i]);
}
cleanup:
virObjectUnlock(dmn);
}
void
virNetDaemonQuit(virNetDaemonPtr dmn)
{
virObjectLock(dmn);
VIR_DEBUG("Quit requested %p", dmn);
dmn->quit = true;
virObjectUnlock(dmn);
}
void
virNetDaemonClose(virNetDaemonPtr dmn)
{
size_t i;
if (!dmn)
return;
virObjectLock(dmn);
for (i = 0; i < dmn->nservers; i++)
virNetServerClose(dmn->servers[i]);
virObjectUnlock(dmn);
}
/*
* virnetdaemon.h
*
* Copyright (C) 2015 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: Martin Kletzander <mkletzan@redhat.com>
*/
#ifndef __VIR_NET_DAEMON_H__
# define __VIR_NET_DAEMON_H__
# include <signal.h>
# ifdef WITH_GNUTLS
# include "virnettlscontext.h"
# endif
# include "virobject.h"
# include "virjson.h"
# include "virnetserverprogram.h"
# include "virnetserverclient.h"
# include "virnetserverservice.h"
# include "virnetserver.h"
virNetDaemonPtr virNetDaemonNew(void);
int virNetDaemonAddServer(virNetDaemonPtr dmn, virNetServerPtr);
virNetServerPtr virNetDaemonAddServerPostExec(virNetDaemonPtr dmn,
virNetServerClientPrivNew clientPrivNew,
virNetServerClientPrivNewPostExecRestart clientPrivNewPostExecRestart,
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart,
virFreeCallback clientPrivFree,
void *clientPrivOpaque);
virNetDaemonPtr virNetDaemonNewPostExecRestart(virJSONValuePtr object);
virJSONValuePtr virNetDaemonPreExecRestart(virNetDaemonPtr dmn);
typedef int (*virNetDaemonAutoShutdownFunc)(virNetDaemonPtr dmn, void *opaque);
bool virNetDaemonIsPrivileged(virNetDaemonPtr dmn);
void virNetDaemonAutoShutdown(virNetDaemonPtr dmn,
unsigned int timeout);
void virNetDaemonAddShutdownInhibition(virNetDaemonPtr dmn);
void virNetDaemonRemoveShutdownInhibition(virNetDaemonPtr dmn);
typedef void (*virNetDaemonSignalFunc)(virNetDaemonPtr dmn, siginfo_t *info, void *opaque);
int virNetDaemonAddSignalHandler(virNetDaemonPtr dmn,
int signum,
virNetDaemonSignalFunc func,
void *opaque);
void virNetDaemonUpdateServices(virNetDaemonPtr dmn,
bool enabled);
void virNetDaemonRun(virNetDaemonPtr dmn);
void virNetDaemonQuit(virNetDaemonPtr dmn);
void virNetDaemonClose(virNetDaemonPtr dmn);
virNetServerPtr virNetDaemonGetServer(virNetDaemonPtr dmn,
int subServerID);
#endif /* __VIR_NET_DAEMON_H__ */
/* /*
* virnetserver.c: generic network RPC server * virnetserver.c: generic network RPC server
* *
* Copyright (C) 2006-2012, 2014 Red Hat, Inc. * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -23,40 +23,19 @@ ...@@ -23,40 +23,19 @@
#include <config.h> #include <config.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "virnetserver.h" #include "virnetserver.h"
#include "virlog.h" #include "virlog.h"
#include "viralloc.h" #include "viralloc.h"
#include "virerror.h" #include "virerror.h"
#include "virthread.h" #include "virthread.h"
#include "virthreadpool.h" #include "virthreadpool.h"
#include "virutil.h"
#include "virfile.h"
#include "virnetservermdns.h" #include "virnetservermdns.h"
#include "virdbus.h"
#include "virstring.h" #include "virstring.h"
#include "virsystemd.h"
#ifndef SA_SIGINFO
# define SA_SIGINFO 0
#endif
#define VIR_FROM_THIS VIR_FROM_RPC #define VIR_FROM_THIS VIR_FROM_RPC
VIR_LOG_INIT("rpc.netserver"); VIR_LOG_INIT("rpc.netserver");
typedef struct _virNetServerSignal virNetServerSignal;
typedef virNetServerSignal *virNetServerSignalPtr;
struct _virNetServerSignal {
struct sigaction oldaction;
int signum;
virNetServerSignalFunc func;
void *opaque;
};
typedef struct _virNetServerJob virNetServerJob; typedef struct _virNetServerJob virNetServerJob;
typedef virNetServerJob *virNetServerJobPtr; typedef virNetServerJob *virNetServerJobPtr;
...@@ -72,14 +51,6 @@ struct _virNetServer { ...@@ -72,14 +51,6 @@ struct _virNetServer {
virThreadPoolPtr workers; virThreadPoolPtr workers;
bool privileged;
size_t nsignals;
virNetServerSignalPtr *signals;
int sigread;
int sigwrite;
int sigwatch;
char *mdnsGroupName; char *mdnsGroupName;
virNetServerMDNSPtr mdns; virNetServerMDNSPtr mdns;
virNetServerMDNSGroupPtr mdnsGroup; virNetServerMDNSGroupPtr mdnsGroup;
...@@ -100,17 +71,10 @@ struct _virNetServer { ...@@ -100,17 +71,10 @@ struct _virNetServer {
unsigned int keepaliveCount; unsigned int keepaliveCount;
bool keepaliveRequired; bool keepaliveRequired;
bool quit;
#ifdef WITH_GNUTLS #ifdef WITH_GNUTLS
virNetTLSContextPtr tls; virNetTLSContextPtr tls;
#endif #endif
unsigned int autoShutdownTimeout;
size_t autoShutdownInhibitions;
bool autoShutdownCallingInhibit;
int autoShutdownInhibitFd;
virNetServerClientPrivNew clientPrivNew; virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart; virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
virFreeCallback clientPrivFree; virFreeCallback clientPrivFree;
...@@ -356,7 +320,6 @@ virNetServerPtr virNetServerNew(size_t min_workers, ...@@ -356,7 +320,6 @@ virNetServerPtr virNetServerNew(size_t min_workers,
void *clientPrivOpaque) void *clientPrivOpaque)
{ {
virNetServerPtr srv; virNetServerPtr srv;
struct sigaction sig_action;
if (virNetServerInitialize() < 0) if (virNetServerInitialize() < 0)
return NULL; return NULL;
...@@ -376,13 +339,10 @@ virNetServerPtr virNetServerNew(size_t min_workers, ...@@ -376,13 +339,10 @@ virNetServerPtr virNetServerNew(size_t min_workers,
srv->keepaliveInterval = keepaliveInterval; srv->keepaliveInterval = keepaliveInterval;
srv->keepaliveCount = keepaliveCount; srv->keepaliveCount = keepaliveCount;
srv->keepaliveRequired = keepaliveRequired; srv->keepaliveRequired = keepaliveRequired;
srv->sigwrite = srv->sigread = -1;
srv->clientPrivNew = clientPrivNew; srv->clientPrivNew = clientPrivNew;
srv->clientPrivPreExecRestart = clientPrivPreExecRestart; srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
srv->clientPrivFree = clientPrivFree; srv->clientPrivFree = clientPrivFree;
srv->clientPrivOpaque = clientPrivOpaque; srv->clientPrivOpaque = clientPrivOpaque;
srv->privileged = geteuid() == 0;
srv->autoShutdownInhibitFd = -1;
if (VIR_STRDUP(srv->mdnsGroupName, mdnsGroupName) < 0) if (VIR_STRDUP(srv->mdnsGroupName, mdnsGroupName) < 0)
goto error; goto error;
...@@ -394,15 +354,7 @@ virNetServerPtr virNetServerNew(size_t min_workers, ...@@ -394,15 +354,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
goto error; goto error;
} }
if (virEventRegisterDefaultImpl() < 0)
goto error;
memset(&sig_action, 0, sizeof(sig_action));
sig_action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sig_action, NULL);
return srv; return srv;
error: error:
virObjectUnref(srv); virObjectUnref(srv);
return NULL; return NULL;
...@@ -499,7 +451,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, ...@@ -499,7 +451,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
goto error; goto error;
} }
n = virJSONValueArraySize(services); n = virJSONValueArraySize(services);
if (n < 0) { if (n < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed services data in JSON document")); _("Malformed services data in JSON document"));
...@@ -532,7 +484,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, ...@@ -532,7 +484,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
goto error; goto error;
} }
n = virJSONValueArraySize(clients); n = virJSONValueArraySize(clients);
if (n < 0) { if (n < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed clients data in JSON document")); _("Malformed clients data in JSON document"));
...@@ -679,286 +631,6 @@ virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv) ...@@ -679,286 +631,6 @@ virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv)
} }
bool virNetServerIsPrivileged(virNetServerPtr srv)
{
bool priv;
virObjectLock(srv);
priv = srv->privileged;
virObjectUnlock(srv);
return priv;
}
void virNetServerAutoShutdown(virNetServerPtr srv,
unsigned int timeout)
{
virObjectLock(srv);
srv->autoShutdownTimeout = timeout;
virObjectUnlock(srv);
}
#if defined(HAVE_DBUS) && defined(DBUS_TYPE_UNIX_FD)
static void virNetServerGotInhibitReply(DBusPendingCall *pending,
void *opaque)
{
virNetServerPtr srv = opaque;
DBusMessage *reply;
int fd;
virObjectLock(srv);
srv->autoShutdownCallingInhibit = false;
VIR_DEBUG("srv=%p", srv);
reply = dbus_pending_call_steal_reply(pending);
if (reply == NULL)
goto cleanup;
if (dbus_message_get_args(reply, NULL,
DBUS_TYPE_UNIX_FD, &fd,
DBUS_TYPE_INVALID)) {
if (srv->autoShutdownInhibitions) {
srv->autoShutdownInhibitFd = fd;
} else {
/* We stopped the last VM since we made the inhibit call */
VIR_FORCE_CLOSE(fd);
}
}
dbus_message_unref(reply);
cleanup:
virObjectUnlock(srv);
}
/* As per: http://www.freedesktop.org/wiki/Software/systemd/inhibit */
static void virNetServerCallInhibit(virNetServerPtr srv,
const char *what,
const char *who,
const char *why,
const char *mode)
{
DBusMessage *message;
DBusPendingCall *pendingReply;
DBusConnection *systemBus;
VIR_DEBUG("srv=%p what=%s who=%s why=%s mode=%s",
srv, NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
if (!(systemBus = virDBusGetSystemBus()))
return;
/* Only one outstanding call at a time */
if (srv->autoShutdownCallingInhibit)
return;
message = dbus_message_new_method_call("org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Inhibit");
if (message == NULL)
return;
dbus_message_append_args(message,
DBUS_TYPE_STRING, &what,
DBUS_TYPE_STRING, &who,
DBUS_TYPE_STRING, &why,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
pendingReply = NULL;
if (dbus_connection_send_with_reply(systemBus, message,
&pendingReply,
25*1000)) {
dbus_pending_call_set_notify(pendingReply,
virNetServerGotInhibitReply,
srv, NULL);
srv->autoShutdownCallingInhibit = true;
}
dbus_message_unref(message);
}
#endif
void virNetServerAddShutdownInhibition(virNetServerPtr srv)
{
virObjectLock(srv);
srv->autoShutdownInhibitions++;
VIR_DEBUG("srv=%p inhibitions=%zu", srv, srv->autoShutdownInhibitions);
#if defined(HAVE_DBUS) && defined(DBUS_TYPE_UNIX_FD)
if (srv->autoShutdownInhibitions == 1)
virNetServerCallInhibit(srv,
"shutdown",
_("Libvirt"),
_("Virtual machines need to be saved"),
"delay");
#endif
virObjectUnlock(srv);
}
void virNetServerRemoveShutdownInhibition(virNetServerPtr srv)
{
virObjectLock(srv);
srv->autoShutdownInhibitions--;
VIR_DEBUG("srv=%p inhibitions=%zu", srv, srv->autoShutdownInhibitions);
if (srv->autoShutdownInhibitions == 0)
VIR_FORCE_CLOSE(srv->autoShutdownInhibitFd);
virObjectUnlock(srv);
}
static sig_atomic_t sigErrors;
static int sigLastErrno;
static int sigWrite = -1;
static void
virNetServerSignalHandler(int sig, siginfo_t * siginfo,
void* context ATTRIBUTE_UNUSED)
{
int origerrno;
int r;
siginfo_t tmp;
if (SA_SIGINFO)
tmp = *siginfo;
else
memset(&tmp, 0, sizeof(tmp));
/* set the sig num in the struct */
tmp.si_signo = sig;
origerrno = errno;
r = safewrite(sigWrite, &tmp, sizeof(tmp));
if (r == -1) {
sigErrors++;
sigLastErrno = errno;
}
errno = origerrno;
}
static void
virNetServerSignalEvent(int watch,
int fd ATTRIBUTE_UNUSED,
int events ATTRIBUTE_UNUSED,
void *opaque)
{
virNetServerPtr srv = opaque;
siginfo_t siginfo;
size_t i;
virObjectLock(srv);
if (saferead(srv->sigread, &siginfo, sizeof(siginfo)) != sizeof(siginfo)) {
virReportSystemError(errno, "%s",
_("Failed to read from signal pipe"));
virEventRemoveHandle(watch);
srv->sigwatch = -1;
goto cleanup;
}
for (i = 0; i < srv->nsignals; i++) {
if (siginfo.si_signo == srv->signals[i]->signum) {
virNetServerSignalFunc func = srv->signals[i]->func;
void *funcopaque = srv->signals[i]->opaque;
virObjectUnlock(srv);
func(srv, &siginfo, funcopaque);
return;
}
}
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected signal received: %d"), siginfo.si_signo);
cleanup:
virObjectUnlock(srv);
}
static int virNetServerSignalSetup(virNetServerPtr srv)
{
int fds[2] = { -1, -1 };
if (srv->sigwrite != -1)
return 0;
if (pipe2(fds, O_CLOEXEC|O_NONBLOCK) < 0) {
virReportSystemError(errno, "%s",
_("Unable to create signal pipe"));
return -1;
}
if ((srv->sigwatch = virEventAddHandle(fds[0],
VIR_EVENT_HANDLE_READABLE,
virNetServerSignalEvent,
srv, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to add signal handle watch"));
goto error;
}
srv->sigread = fds[0];
srv->sigwrite = fds[1];
sigWrite = fds[1];
return 0;
error:
VIR_FORCE_CLOSE(fds[0]);
VIR_FORCE_CLOSE(fds[1]);
return -1;
}
int virNetServerAddSignalHandler(virNetServerPtr srv,
int signum,
virNetServerSignalFunc func,
void *opaque)
{
virNetServerSignalPtr sigdata = NULL;
struct sigaction sig_action;
virObjectLock(srv);
if (virNetServerSignalSetup(srv) < 0)
goto error;
if (VIR_EXPAND_N(srv->signals, srv->nsignals, 1) < 0)
goto error;
if (VIR_ALLOC(sigdata) < 0)
goto error;
sigdata->signum = signum;
sigdata->func = func;
sigdata->opaque = opaque;
memset(&sig_action, 0, sizeof(sig_action));
sig_action.sa_sigaction = virNetServerSignalHandler;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(signum, &sig_action, &sigdata->oldaction);
srv->signals[srv->nsignals-1] = sigdata;
virObjectUnlock(srv);
return 0;
error:
VIR_FREE(sigdata);
virObjectUnlock(srv);
return -1;
}
int virNetServerAddService(virNetServerPtr srv, int virNetServerAddService(virNetServerPtr srv,
virNetServerServicePtr svc, virNetServerServicePtr svc,
...@@ -1023,22 +695,6 @@ int virNetServerSetTLSContext(virNetServerPtr srv, ...@@ -1023,22 +695,6 @@ int virNetServerSetTLSContext(virNetServerPtr srv,
#endif #endif
static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
void *opaque)
{
virNetServerPtr srv = opaque;
virObjectLock(srv);
if (!srv->autoShutdownInhibitions) {
VIR_DEBUG("Automatic shutdown triggered");
srv->quit = true;
}
virObjectUnlock(srv);
}
static void static void
virNetServerUpdateServicesLocked(virNetServerPtr srv, virNetServerUpdateServicesLocked(virNetServerPtr srv,
bool enabled) bool enabled)
...@@ -1087,127 +743,16 @@ virNetServerCheckLimits(virNetServerPtr srv) ...@@ -1087,127 +743,16 @@ virNetServerCheckLimits(virNetServerPtr srv)
} }
} }
void virNetServerRun(virNetServerPtr srv)
{
int timerid = -1;
bool timerActive = false;
size_t i;
virObjectLock(srv);
if (srv->mdns &&
virNetServerMDNSStart(srv->mdns) < 0)
goto cleanup;
srv->quit = false;
if (srv->autoShutdownTimeout &&
(timerid = virEventAddTimeout(-1,
virNetServerAutoShutdownTimer,
srv, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to register shutdown timeout"));
goto cleanup;
}
/* We are accepting connections now. Notify systemd
* so it can start dependent services. */
virSystemdNotifyStartup();
VIR_DEBUG("srv=%p quit=%d", srv, srv->quit);
while (!srv->quit) {
/* A shutdown timeout is specified, so check
* if any drivers have active state, if not
* shutdown after timeout seconds
*/
if (srv->autoShutdownTimeout) {
if (timerActive) {
if (srv->clients) {
VIR_DEBUG("Deactivating shutdown timer %d", timerid);
virEventUpdateTimeout(timerid, -1);
timerActive = false;
}
} else {
if (!srv->clients) {
VIR_DEBUG("Activating shutdown timer %d", timerid);
virEventUpdateTimeout(timerid,
srv->autoShutdownTimeout * 1000);
timerActive = true;
}
}
}
virObjectUnlock(srv);
if (virEventRunDefaultImpl() < 0) {
virObjectLock(srv);
VIR_DEBUG("Loop iteration error, exiting");
break;
}
virObjectLock(srv);
reprocess:
for (i = 0; i < srv->nclients; i++) {
/* Coverity 5.3.0 couldn't see that srv->clients is non-NULL
* if srv->nclients is non-zero. */
sa_assert(srv->clients);
if (virNetServerClientWantClose(srv->clients[i]))
virNetServerClientClose(srv->clients[i]);
if (virNetServerClientIsClosed(srv->clients[i])) {
virNetServerClientPtr client = srv->clients[i];
VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients);
if (virNetServerClientNeedAuth(client))
virNetServerTrackCompletedAuthLocked(srv);
virNetServerCheckLimits(srv);
virObjectUnlock(srv);
virObjectUnref(client);
virObjectLock(srv);
goto reprocess;
}
}
}
cleanup:
virObjectUnlock(srv);
}
void virNetServerQuit(virNetServerPtr srv)
{
virObjectLock(srv);
VIR_DEBUG("Quit requested %p", srv);
srv->quit = true;
virObjectUnlock(srv);
}
void virNetServerDispose(void *obj) void virNetServerDispose(void *obj)
{ {
virNetServerPtr srv = obj; virNetServerPtr srv = obj;
size_t i; size_t i;
VIR_FORCE_CLOSE(srv->autoShutdownInhibitFd);
for (i = 0; i < srv->nservices; i++) for (i = 0; i < srv->nservices; i++)
virNetServerServiceToggle(srv->services[i], false); virNetServerServiceToggle(srv->services[i], false);
virThreadPoolFree(srv->workers); virThreadPoolFree(srv->workers);
for (i = 0; i < srv->nsignals; i++) {
sigaction(srv->signals[i]->signum, &srv->signals[i]->oldaction, NULL);
VIR_FREE(srv->signals[i]);
}
VIR_FREE(srv->signals);
VIR_FORCE_CLOSE(srv->sigread);
VIR_FORCE_CLOSE(srv->sigwrite);
if (srv->sigwatch > 0)
virEventRemoveHandle(srv->sigwatch);
for (i = 0; i < srv->nservices; i++) for (i = 0; i < srv->nservices; i++)
virObjectUnref(srv->services[i]); virObjectUnref(srv->services[i]);
VIR_FREE(srv->services); VIR_FREE(srv->services);
...@@ -1280,3 +825,62 @@ size_t virNetServerTrackCompletedAuth(virNetServerPtr srv) ...@@ -1280,3 +825,62 @@ size_t virNetServerTrackCompletedAuth(virNetServerPtr srv)
virObjectUnlock(srv); virObjectUnlock(srv);
return ret; return ret;
} }
bool
virNetServerHasClients(virNetServerPtr srv)
{
bool ret;
virObjectLock(srv);
ret = !!srv->nclients;
virObjectUnlock(srv);
return ret;
}
void
virNetServerProcessClients(virNetServerPtr srv)
{
size_t i;
virObjectLock(srv);
reprocess:
for (i = 0; i < srv->nclients; i++) {
/* Coverity 5.3.0 couldn't see that srv->clients is non-NULL
* if srv->nclients is non-zero. */
sa_assert(srv->clients);
if (virNetServerClientWantClose(srv->clients[i]))
virNetServerClientClose(srv->clients[i]);
if (virNetServerClientIsClosed(srv->clients[i])) {
virNetServerClientPtr client = srv->clients[i];
VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients);
if (virNetServerClientNeedAuth(client))
virNetServerTrackCompletedAuthLocked(srv);
virNetServerCheckLimits(srv);
virObjectUnlock(srv);
virObjectUnref(client);
virObjectLock(srv);
goto reprocess;
}
}
virObjectUnlock(srv);
}
int
virNetServerStart(virNetServerPtr srv)
{
/*
* Do whatever needs to be done before starting.
*/
if (!srv->mdns)
return 0;
return virNetServerMDNSStart(srv->mdns);
}
/* /*
* virnetserver.h: generic network RPC server * virnetserver.h: generic network RPC server
* *
* Copyright (C) 2006-2011 Red Hat, Inc. * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#ifndef __VIR_NET_SERVER_H__ #ifndef __VIR_NET_SERVER_H__
# define __VIR_NET_SERVER_H__ # define __VIR_NET_SERVER_H__
# include <signal.h>
# ifdef WITH_GNUTLS # ifdef WITH_GNUTLS
# include "virnettlscontext.h" # include "virnettlscontext.h"
# endif # endif
...@@ -35,6 +33,9 @@ ...@@ -35,6 +33,9 @@
# include "virobject.h" # include "virobject.h"
# include "virjson.h" # include "virjson.h"
typedef struct _virNetServer virNetServer;
typedef virNetServer *virNetServerPtr;
virNetServerPtr virNetServerNew(size_t min_workers, virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers, size_t max_workers,
size_t priority_workers, size_t priority_workers,
...@@ -56,24 +57,9 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object, ...@@ -56,24 +57,9 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
virFreeCallback clientPrivFree, virFreeCallback clientPrivFree,
void *clientPrivOpaque); void *clientPrivOpaque);
virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv); void virNetServerClose(virNetServerPtr srv);
typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
bool virNetServerIsPrivileged(virNetServerPtr srv);
void virNetServerAutoShutdown(virNetServerPtr srv,
unsigned int timeout);
void virNetServerAddShutdownInhibition(virNetServerPtr srv);
void virNetServerRemoveShutdownInhibition(virNetServerPtr srv);
typedef void (*virNetServerSignalFunc)(virNetServerPtr srv, siginfo_t *info, void *opaque);
int virNetServerAddSignalHandler(virNetServerPtr srv, virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv);
int signum,
virNetServerSignalFunc func,
void *opaque);
int virNetServerAddService(virNetServerPtr srv, int virNetServerAddService(virNetServerPtr srv,
virNetServerServicePtr svc, virNetServerServicePtr svc,
...@@ -90,18 +76,18 @@ int virNetServerSetTLSContext(virNetServerPtr srv, ...@@ -90,18 +76,18 @@ int virNetServerSetTLSContext(virNetServerPtr srv,
virNetTLSContextPtr tls); virNetTLSContextPtr tls);
# endif # endif
void virNetServerUpdateServices(virNetServerPtr srv,
bool enabled);
void virNetServerRun(virNetServerPtr srv);
void virNetServerQuit(virNetServerPtr srv);
void virNetServerClose(virNetServerPtr srv);
bool virNetServerKeepAliveRequired(virNetServerPtr srv); bool virNetServerKeepAliveRequired(virNetServerPtr srv);
size_t virNetServerTrackPendingAuth(virNetServerPtr srv); size_t virNetServerTrackPendingAuth(virNetServerPtr srv);
size_t virNetServerTrackCompletedAuth(virNetServerPtr srv); size_t virNetServerTrackCompletedAuth(virNetServerPtr srv);
#endif int virNetServerAddClient(virNetServerPtr srv,
virNetServerClientPtr client);
bool virNetServerHasClients(virNetServerPtr srv);
void virNetServerProcessClients(virNetServerPtr srv);
void virNetServerUpdateServices(virNetServerPtr srv, bool enabled);
int virNetServerStart(virNetServerPtr srv);
#endif /* __VIR_NET_SERVER_H__ */
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
# include "virnetserverclient.h" # include "virnetserverclient.h"
# include "virobject.h" # include "virobject.h"
typedef struct _virNetDaemon virNetDaemon;
typedef virNetDaemon *virNetDaemonPtr;
typedef struct _virNetServer virNetServer; typedef struct _virNetServer virNetServer;
typedef virNetServer *virNetServerPtr; typedef virNetServer *virNetServerPtr;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册