This allows to have more servers in one daemon which helps isolating
some resources.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
daemon/libvirtd.c | 101 ++---
docs/internals.html.in | 4 +-
docs/internals/rpc.html.in | 7 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/libvirt_remote.syms | 30 +-
src/locking/lock_daemon.c | 75 ++--
src/locking/lock_daemon_config.c | 2 +-
src/locking/lock_daemon_dispatch.c | 4 +-
src/lxc/lxc_controller.c | 65 ++--
src/rpc/virnetdaemon.c | 749 +++++++++++++++++++++++++++++++++++++
src/rpc/virnetdaemon.h | 82 ++++
src/rpc/virnetserver.c | 520 +++----------------------
src/rpc/virnetserver.h | 46 +--
src/rpc/virnetserverprogram.h | 3 +
15 files changed, 1086 insertions(+), 604 deletions(-)
create mode 100644 src/rpc/virnetdaemon.c
create mode 100644 src/rpc/virnetdaemon.h
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 1e2c002ebacb..94103e2d0d8c 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1,7 +1,7 @@
/*
* 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
*
* This library is free software; you can redistribute it and/or
@@ -49,7 +49,7 @@
#include "viralloc.h"
#include "virconf.h"
#include "virnetlink.h"
-#include "virnetserver.h"
+#include "virnetdaemon.h"
#include "remote.h"
#include "virhook.h"
#include "viraudit.h"
@@ -776,14 +776,14 @@ daemonSetupPrivs(void)
#endif
-static void daemonShutdownHandler(virNetServerPtr srv,
+static void daemonShutdownHandler(virNetDaemonPtr dmn,
siginfo_t *sig 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,
void *opaque ATTRIBUTE_UNUSED)
{
@@ -799,15 +799,15 @@ static void daemonReloadHandler(virNetServerPtr srv
ATTRIBUTE_UNUSED,
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;
- if (virNetServerAddSignalHandler(srv, SIGQUIT, daemonShutdownHandler, NULL) < 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGQUIT, daemonShutdownHandler, NULL) < 0)
return -1;
- if (virNetServerAddSignalHandler(srv, SIGTERM, daemonShutdownHandler, NULL) < 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGTERM, daemonShutdownHandler, NULL) < 0)
return -1;
- if (virNetServerAddSignalHandler(srv, SIGHUP, daemonReloadHandler, NULL) < 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGHUP, daemonReloadHandler, NULL) < 0)
return -1;
return 0;
}
@@ -815,12 +815,12 @@ static int daemonSetupSignals(virNetServerPtr srv)
static void daemonInhibitCallback(bool inhibit, void *opaque)
{
- virNetServerPtr srv = opaque;
+ virNetDaemonPtr dmn = opaque;
if (inhibit)
- virNetServerAddShutdownInhibition(srv);
+ virNetDaemonAddShutdownInhibition(dmn);
else
- virNetServerRemoveShutdownInhibition(srv);
+ virNetDaemonRemoveShutdownInhibition(dmn);
}
@@ -830,26 +830,26 @@ static DBusConnection *systemBus;
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());
- VIR_DEBUG("Completed stop srv=%p", srv);
+ VIR_DEBUG("Completed stop dmn=%p", dmn);
/* Exit libvirtd cleanly */
- virNetServerQuit(srv);
+ virNetDaemonQuit(dmn);
}
/* We do this in a thread to not block the main loop */
-static void daemonStop(virNetServerPtr srv)
+static void daemonStop(virNetDaemonPtr dmn)
{
virThread thr;
- virObjectRef(srv);
- if (virThreadCreate(&thr, false, daemonStopWorker, srv) < 0)
- virObjectUnref(srv);
+ virObjectRef(dmn);
+ if (virThreadCreate(&thr, false, daemonStopWorker, dmn) < 0)
+ virObjectUnref(dmn);
}
@@ -858,14 +858,14 @@ handleSessionMessageFunc(DBusConnection *connection
ATTRIBUTE_UNUSED,
DBusMessage *message,
void *opaque)
{
- virNetServerPtr srv = opaque;
+ virNetDaemonPtr dmn = opaque;
- VIR_DEBUG("srv=%p", srv);
+ VIR_DEBUG("dmn=%p", dmn);
if (dbus_message_is_signal(message,
DBUS_INTERFACE_LOCAL,
"Disconnected"))
- daemonStop(srv);
+ daemonStop(dmn);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -876,14 +876,14 @@ handleSystemMessageFunc(DBusConnection *connection
ATTRIBUTE_UNUSED,
DBusMessage *message,
void *opaque)
{
- virNetServerPtr srv = opaque;
+ virNetDaemonPtr dmn = opaque;
- VIR_DEBUG("srv=%p", srv);
+ VIR_DEBUG("dmn=%p", dmn);
if (dbus_message_is_signal(message,
"org.freedesktop.login1.Manager",
"PrepareForShutdown"))
- daemonStop(srv);
+ daemonStop(dmn);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -892,22 +892,22 @@ handleSystemMessageFunc(DBusConnection *connection
ATTRIBUTE_UNUSED,
static void daemonRunStateInit(void *opaque)
{
- virNetServerPtr srv = opaque;
+ virNetDaemonPtr dmn = opaque;
virIdentityPtr sysident = virIdentityGetSystem();
virIdentitySetCurrent(sysident);
/* Since driver initialization can take time inhibit daemon shutdown until
we're done so clients get a chance to connect */
- daemonInhibitCallback(true, srv);
+ daemonInhibitCallback(true, dmn);
/* Start the stateful HV drivers
* This is deliberately done after telling the parent process
* we're ready, since it can take a long time and this will
* seriously delay OS bootup process */
- if (virStateInitialize(virNetServerIsPrivileged(srv),
+ if (virStateInitialize(virNetDaemonIsPrivileged(dmn),
daemonInhibitCallback,
- srv) < 0) {
+ dmn) < 0) {
VIR_ERROR(_("Driver state initialization failed"));
/* Ensure the main event loop quits */
kill(getpid(), SIGTERM);
@@ -918,17 +918,17 @@ static void daemonRunStateInit(void *opaque)
#ifdef HAVE_DBUS
/* Tie the non-priviledged libvirtd to the session/shutdown lifecycle */
- if (!virNetServerIsPrivileged(srv)) {
+ if (!virNetDaemonIsPrivileged(dmn)) {
sessionBus = virDBusGetSessionBus();
if (sessionBus != NULL)
dbus_connection_add_filter(sessionBus,
- handleSessionMessageFunc, srv, NULL);
+ handleSessionMessageFunc, dmn, NULL);
systemBus = virDBusGetSystemBus();
if (systemBus != NULL) {
dbus_connection_add_filter(systemBus,
- handleSystemMessageFunc, srv, NULL);
+ handleSystemMessageFunc, dmn, NULL);
dbus_bus_add_match(systemBus,
"type='signal',sender='org.freedesktop.login1',
interface='org.freedesktop.login1.Manager'",
NULL);
@@ -936,20 +936,20 @@ static void daemonRunStateInit(void *opaque)
}
#endif
/* Only now accept clients from network */
- virNetServerUpdateServices(srv, true);
+ virNetDaemonUpdateServices(dmn, true);
cleanup:
- daemonInhibitCallback(false, srv);
- virObjectUnref(srv);
+ daemonInhibitCallback(false, dmn);
+ virObjectUnref(dmn);
virObjectUnref(sysident);
virIdentitySetCurrent(NULL);
}
-static int daemonStateInit(virNetServerPtr srv)
+static int daemonStateInit(virNetDaemonPtr dmn)
{
virThread thr;
- virObjectRef(srv);
- if (virThreadCreate(&thr, false, daemonRunStateInit, srv) < 0) {
- virObjectUnref(srv);
+ virObjectRef(dmn);
+ if (virThreadCreate(&thr, false, daemonRunStateInit, dmn) < 0) {
+ virObjectUnref(dmn);
return -1;
}
return 0;
@@ -1100,6 +1100,7 @@ daemonUsage(const char *argv0, bool privileged)
}
int main(int argc, char **argv) {
+ virNetDaemonPtr dmn = NULL;
virNetServerPtr srv = NULL;
char *remote_config_file = NULL;
int statuswrite = -1;
@@ -1354,6 +1355,12 @@ int main(int argc, char **argv) {
goto cleanup;
}
+ if (!(dmn = virNetDaemonNew()) ||
+ virNetDaemonAddServer(dmn, srv) < 0) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+
/* Beyond this point, nothing should rely on using
* getuid/geteuid() == 0, for privilege level checks.
*/
@@ -1408,11 +1415,10 @@ int main(int argc, char **argv) {
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
- virNetServerAutoShutdown(srv,
- timeout);
+ virNetDaemonAutoShutdown(dmn, timeout);
}
- if ((daemonSetupSignals(srv)) < 0) {
+ if ((daemonSetupSignals(dmn)) < 0) {
ret = VIR_DAEMON_ERR_SIGNAL;
goto cleanup;
}
@@ -1467,7 +1473,7 @@ int main(int argc, char **argv) {
}
/* Initialize drivers & then start accepting new clients from network */
- if (daemonStateInit(srv) < 0) {
+ if (daemonStateInit(dmn) < 0) {
ret = VIR_DAEMON_ERR_INIT;
goto cleanup;
}
@@ -1489,7 +1495,7 @@ int main(int argc, char **argv) {
#endif
/* Run event loop. */
- virNetServerRun(srv);
+ virNetDaemonRun(dmn);
ret = 0;
@@ -1501,7 +1507,8 @@ int main(int argc, char **argv) {
virObjectUnref(remoteProgram);
virObjectUnref(lxcProgram);
virObjectUnref(qemuProgram);
- virNetServerClose(srv);
+ virNetDaemonClose(dmn);
+ virObjectUnref(dmn);
virObjectUnref(srv);
virNetlinkShutdown();
if (statuswrite != -1) {
diff --git a/docs/internals.html.in b/docs/internals.html.in
index 398d02e649b3..c30f52f9f062 100644
--- a/docs/internals.html.in
+++ b/docs/internals.html.in
@@ -82,7 +82,9 @@
<ul>
<li>Daemon Startup
<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,
set up an RPC server program using the
<code>remoteProcs[]</code>
table via a virNetServerProgramNew() call. The table is the
diff --git a/docs/internals/rpc.html.in b/docs/internals/rpc.html.in
index f2ed64f1c0e5..a48a4c0d6dc3 100644
--- a/docs/internals/rpc.html.in
+++ b/docs/internals/rpc.html.in
@@ -532,6 +532,13 @@
calls in parallel, with dispatch across multiple worker threads.
</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>
<dd>The virNetServerMDNS APIs are used to advertise a server
across the local network, enabling clients to automatically
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bb0f6e154349..ebb048258466 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -132,6 +132,7 @@ src/rpc/virkeepalive.c
src/rpc/virnetclient.c
src/rpc/virnetclientprogram.c
src/rpc/virnetclientstream.c
+src/rpc/virnetdaemon.c
src/rpc/virnetmessage.c
src/rpc/virnetsaslcontext.c
src/rpc/virnetsocket.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a9ebb07b1d32..d71c31876f51 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2507,6 +2507,7 @@ libvirt_net_rpc_server_la_SOURCES = \
rpc/virnetserverservice.h rpc/virnetserverservice.c \
rpc/virnetserverclient.h rpc/virnetserverclient.c \
rpc/virnetservermdns.h rpc/virnetservermdns.c \
+ rpc/virnetdaemon.h rpc/virnetdaemon.c \
rpc/virnetserver.h rpc/virnetserver.c
libvirt_net_rpc_server_la_CFLAGS = \
$(AVAHI_CFLAGS) \
diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index bdd68f63e971..e6ca041ea8e1 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -57,6 +57,24 @@ virNetClientStreamSendPacket;
virNetClientStreamSetError;
+# rpc/virnetdaemon.h
+virNetDaemonAddServer;
+virNetDaemonAddServerPostExec;
+virNetDaemonAddShutdownInhibition;
+virNetDaemonAddSignalHandler;
+virNetDaemonAutoShutdown;
+virNetDaemonClose;
+virNetDaemonGetServer;
+virNetDaemonIsPrivileged;
+virNetDaemonNew;
+virNetDaemonNewPostExecRestart;
+virNetDaemonPreExecRestart;
+virNetDaemonQuit;
+virNetDaemonRemoveShutdownInhibition;
+virNetDaemonRun;
+virNetDaemonUpdateServices;
+
+
# rpc/virnetmessage.h
virNetMessageClear;
virNetMessageDecodeHeader;
@@ -80,18 +98,16 @@ xdr_virNetMessageError;
virNetServerAddClient;
virNetServerAddProgram;
virNetServerAddService;
-virNetServerAddShutdownInhibition;
-virNetServerAddSignalHandler;
-virNetServerAutoShutdown;
virNetServerClose;
-virNetServerIsPrivileged;
+virNetServerHasClients;
virNetServerKeepAliveRequired;
virNetServerNew;
virNetServerNewPostExecRestart;
virNetServerPreExecRestart;
-virNetServerQuit;
-virNetServerRemoveShutdownInhibition;
-virNetServerRun;
+virNetServerProcessClients;
+virNetServerStart;
+virNetServerTrackCompletedAuth;
+virNetServerTrackPendingAuth;
virNetServerUpdateServices;
diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
index 042ff947f804..ecbe03a4c154 100644
--- a/src/locking/lock_daemon.c
+++ b/src/locking/lock_daemon.c
@@ -1,7 +1,7 @@
/*
* 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
* modify it under the terms of the GNU Lesser General Public
@@ -41,6 +41,7 @@
#include "virlog.h"
#include "viralloc.h"
#include "virconf.h"
+#include "rpc/virnetdaemon.h"
#include "rpc/virnetserver.h"
#include "virrandom.h"
#include "virhash.h"
@@ -60,6 +61,7 @@ VIR_LOG_INIT("locking.lock_daemon");
struct _virLockDaemon {
virMutex lock;
+ virNetDaemonPtr dmn;
virNetServerPtr srv;
virHashTablePtr lockspaces;
virLockSpacePtr defaultLockspace;
@@ -118,6 +120,7 @@ virLockDaemonFree(virLockDaemonPtr lockd)
return;
virObjectUnref(lockd->srv);
+ virObjectUnref(lockd->dmn);
virHashFree(lockd->lockspaces);
virLockSpaceFree(lockd->defaultLockspace);
@@ -155,6 +158,10 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged)
(void*)(intptr_t)(privileged ? 0x1 : 0x0))))
goto error;
+ if (!(lockd->dmn = virNetDaemonNew()) ||
+ virNetDaemonAddServer(lockd->dmn, lockd->srv) < 0)
+ goto error;
+
if (!(lockd->lockspaces = virHashCreate(VIR_LOCK_DAEMON_NUM_LOCKSPACES,
virLockDaemonLockSpaceDataFree)))
goto error;
@@ -230,18 +237,29 @@ virLockDaemonNewPostExecRestart(virJSONValuePtr object, bool
privileged)
}
}
- if (!(child = virJSONValueObjectGet(object, "server"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Missing server data from JSON file"));
- goto error;
+ if (virJSONValueObjectHasKey(object, "daemon")) {
+ if (!(child = virJSONValueObjectGet(object, "daemon"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("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,
- virLockDaemonClientNew,
-
virLockDaemonClientNewPostExecRestart,
- virLockDaemonClientPreExecRestart,
- virLockDaemonClientFree,
- (void*)(intptr_t)(privileged ? 0x1
: 0x0))))
+ if (!(lockd->dmn = virNetDaemonNewPostExecRestart(child)))
+ goto error;
+
+ if (!(lockd->srv = virNetDaemonAddServerPostExec(lockd->dmn,
+ virLockDaemonClientNew,
+
virLockDaemonClientNewPostExecRestart,
+ virLockDaemonClientPreExecRestart,
+ virLockDaemonClientFree,
+ (void*)(intptr_t)(privileged ? 0x1 :
0x0))))
goto error;
return lockd;
@@ -529,32 +547,32 @@ virLockDaemonVersion(const char *argv0)
}
static void
-virLockDaemonShutdownHandler(virNetServerPtr srv,
+virLockDaemonShutdownHandler(virNetDaemonPtr dmn,
siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
- virNetServerQuit(srv);
+ virNetDaemonQuit(dmn);
}
static void
-virLockDaemonExecRestartHandler(virNetServerPtr srv,
+virLockDaemonExecRestartHandler(virNetDaemonPtr dmn,
siginfo_t *sig ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
execRestart = true;
- virNetServerQuit(srv);
+ virNetDaemonQuit(dmn);
}
static int
-virLockDaemonSetupSignals(virNetServerPtr srv)
+virLockDaemonSetupSignals(virNetDaemonPtr dmn)
{
- if (virNetServerAddSignalHandler(srv, SIGINT, virLockDaemonShutdownHandler, NULL)
< 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGINT, virLockDaemonShutdownHandler, NULL)
< 0)
return -1;
- if (virNetServerAddSignalHandler(srv, SIGQUIT, virLockDaemonShutdownHandler, NULL)
< 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGQUIT, virLockDaemonShutdownHandler, NULL)
< 0)
return -1;
- if (virNetServerAddSignalHandler(srv, SIGTERM, virLockDaemonShutdownHandler, NULL)
< 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGTERM, virLockDaemonShutdownHandler, NULL)
< 0)
return -1;
- if (virNetServerAddSignalHandler(srv, SIGUSR1, virLockDaemonExecRestartHandler, NULL)
< 0)
+ if (virNetDaemonAddSignalHandler(dmn, SIGUSR1, virLockDaemonExecRestartHandler, NULL)
< 0)
return -1;
return 0;
}
@@ -966,7 +984,7 @@ virLockDaemonPostExecRestart(const char *state_file,
static int
virLockDaemonPreExecRestart(const char *state_file,
- virNetServerPtr srv,
+ virNetDaemonPtr dmn,
char **argv)
{
virJSONValuePtr child;
@@ -982,10 +1000,10 @@ virLockDaemonPreExecRestart(const char *state_file,
if (!(object = virJSONValueNewObject()))
goto cleanup;
- if (!(child = virNetServerPreExecRestart(srv)))
+ if (!(child = virNetDaemonPreExecRestart(dmn)))
goto cleanup;
- if (virJSONValueObjectAppend(object, "server", child) < 0) {
+ if (virJSONValueObjectAppend(object, "daemon", child) < 0) {
virJSONValueFree(child);
goto cleanup;
}
@@ -1350,11 +1368,11 @@ int main(int argc, char **argv) {
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
- virNetServerAutoShutdown(lockDaemon->srv,
+ virNetDaemonAutoShutdown(lockDaemon->dmn,
timeout);
}
- if ((virLockDaemonSetupSignals(lockDaemon->srv)) < 0) {
+ if ((virLockDaemonSetupSignals(lockDaemon->dmn)) < 0) {
ret = VIR_LOCK_DAEMON_ERR_SIGNAL;
goto cleanup;
}
@@ -1366,6 +1384,7 @@ int main(int argc, char **argv) {
ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup;
}
+
if (virNetServerAddProgram(lockDaemon->srv, lockProgram) < 0) {
ret = VIR_LOCK_DAEMON_ERR_INIT;
goto cleanup;
@@ -1389,12 +1408,12 @@ int main(int argc, char **argv) {
/* Start accepting new clients from network */
- virNetServerUpdateServices(lockDaemon->srv, true);
- virNetServerRun(lockDaemon->srv);
+ virNetDaemonUpdateServices(lockDaemon->dmn, true);
+ virNetDaemonRun(lockDaemon->dmn);
if (execRestart &&
virLockDaemonPreExecRestart(state_file,
- lockDaemon->srv,
+ lockDaemon->dmn,
argv) < 0)
ret = VIR_LOCK_DAEMON_ERR_REEXEC;
else
diff --git a/src/locking/lock_daemon_config.c b/src/locking/lock_daemon_config.c
index 8a6d18f93598..106e82059ee3 100644
--- a/src/locking/lock_daemon_config.c
+++ b/src/locking/lock_daemon_config.c
@@ -28,7 +28,7 @@
#include "viralloc.h"
#include "virerror.h"
#include "virlog.h"
-#include "rpc/virnetserver.h"
+#include "rpc/virnetdaemon.h"
#include "configmake.h"
#include "virstring.h"
#include "virutil.h"
diff --git a/src/locking/lock_daemon_dispatch.c b/src/locking/lock_daemon_dispatch.c
index bad646c6d07b..1b479db55dd4 100644
--- a/src/locking/lock_daemon_dispatch.c
+++ b/src/locking/lock_daemon_dispatch.c
@@ -1,7 +1,7 @@
/*
* 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
* modify it under the terms of the GNU Lesser General Public
@@ -22,7 +22,7 @@
#include <config.h>
-#include "rpc/virnetserver.h"
+#include "rpc/virnetdaemon.h"
#include "rpc/virnetserverclient.h"
#include "virlog.h"
#include "virstring.h"
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index efbe71feac1d..f456d1f74fe0 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 Red Hat, Inc.
+ * Copyright (C) 2010-2015 Red Hat, Inc.
* Copyright IBM Corp. 2008
*
* lxc_controller.c: linux container process controller
@@ -65,7 +65,7 @@
#include "virprocess.h"
#include "virnuma.h"
#include "virdbus.h"
-#include "rpc/virnetserver.h"
+#include "rpc/virnetdaemon.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -93,7 +93,7 @@ struct _virLXCControllerConsole {
size_t fromContLen;
char fromContBuf[1024];
- virNetServerPtr server;
+ virNetDaemonPtr daemon;
};
typedef struct _virLXCController virLXCController;
@@ -125,8 +125,7 @@ struct _virLXCController {
virSecurityManagerPtr securityManager;
- /* Server socket */
- virNetServerPtr server;
+ virNetDaemonPtr daemon;
bool firstClient;
virNetServerClientPtr client;
virNetServerProgramPtr prog;
@@ -149,7 +148,7 @@ static void virLXCControllerQuitTimer(int timer ATTRIBUTE_UNUSED, void
*opaque)
virLXCControllerPtr ctrl = opaque;
VIR_DEBUG("Triggering event loop quit");
- virNetServerQuit(ctrl->server);
+ virNetDaemonQuit(ctrl->daemon);
}
@@ -280,7 +279,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
if (ctrl->timerShutdown != -1)
virEventRemoveTimeout(ctrl->timerShutdown);
- virObjectUnref(ctrl->server);
+ virObjectUnref(ctrl->daemon);
virLXCControllerFreeFuse(ctrl);
virCgroupFree(&ctrl->cgroup);
@@ -296,7 +295,7 @@ static int virLXCControllerAddConsole(virLXCControllerPtr ctrl,
{
if (VIR_EXPAND_N(ctrl->consoles, ctrl->nconsoles, 1) < 0)
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].hostWatch = -1;
@@ -846,6 +845,7 @@ static void *virLXCControllerClientPrivateNew(virNetServerClientPtr
client,
static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
{
+ virNetServerPtr srv = NULL;
virNetServerServicePtr svc = NULL;
char *sockpath;
@@ -853,13 +853,13 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
LXC_STATE_DIR, ctrl->name) < 0)
return -1;
- if (!(ctrl->server = virNetServerNew(0, 0, 0, 1,
- 0, -1, 0, false,
- NULL,
- virLXCControllerClientPrivateNew,
- NULL,
- virLXCControllerClientPrivateFree,
- ctrl)))
+ if (!(srv = virNetServerNew(0, 0, 0, 1,
+ 0, -1, 0, false,
+ NULL,
+ virLXCControllerClientPrivateNew,
+ NULL,
+ virLXCControllerClientPrivateFree,
+ ctrl)))
goto error;
if (virSecurityManagerSetSocketLabel(ctrl->securityManager, ctrl->def) < 0)
@@ -880,7 +880,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
if (virSecurityManagerClearSocketLabel(ctrl->securityManager, ctrl->def) <
0)
goto error;
- if (virNetServerAddService(ctrl->server, svc, NULL) < 0)
+ if (virNetServerAddService(srv, svc, NULL) < 0)
goto error;
virObjectUnref(svc);
svc = NULL;
@@ -891,14 +891,19 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
virLXCMonitorNProcs)))
goto error;
- virNetServerUpdateServices(ctrl->server, true);
+ if (!(ctrl->daemon = virNetDaemonNew()) ||
+ virNetDaemonAddServer(ctrl->daemon, srv) < 0)
+ goto error;
+
+ virNetDaemonUpdateServices(ctrl->daemon, true);
VIR_FREE(sockpath);
return 0;
error:
VIR_FREE(sockpath);
- virObjectUnref(ctrl->server);
- ctrl->server = NULL;
+ virObjectUnref(srv);
+ virObjectUnref(ctrl->daemon);
+ ctrl->daemon = NULL;
virObjectUnref(svc);
return -1;
}
@@ -926,7 +931,7 @@ static bool wantReboot;
static virMutex lock = VIR_MUTEX_INITIALIZER;
-static void virLXCControllerSignalChildIO(virNetServerPtr server,
+static void virLXCControllerSignalChildIO(virNetDaemonPtr daemon,
siginfo_t *info ATTRIBUTE_UNUSED,
void *opaque)
{
@@ -937,7 +942,7 @@ static void virLXCControllerSignalChildIO(virNetServerPtr server,
ret = waitpid(-1, &status, WNOHANG);
VIR_DEBUG("Got sig child %d vs %lld", ret, (unsigned long
long)ctrl->initpid);
if (ret == ctrl->initpid) {
- virNetServerQuit(server);
+ virNetDaemonQuit(daemon);
virMutexLock(&lock);
if (WIFSIGNALED(status) &&
WTERMSIG(status) == SIGHUP) {
@@ -996,7 +1001,7 @@ static void
virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
VIR_DEBUG(":fail");
virReportSystemError(errno, "%s",
_("Unable to add epoll fd"));
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
goto cleanup;
}
console->hostEpoll = events;
@@ -1008,7 +1013,7 @@ static void
virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s",
_("Unable to remove epoll fd"));
VIR_DEBUG(":fail");
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
goto cleanup;
}
console->hostEpoll = 0;
@@ -1034,7 +1039,7 @@ static void
virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s",
_("Unable to add epoll fd"));
VIR_DEBUG(":fail");
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
goto cleanup;
}
console->contEpoll = events;
@@ -1046,7 +1051,7 @@ static void
virLXCControllerConsoleUpdateWatch(virLXCControllerConsolePtr consol
virReportSystemError(errno, "%s",
_("Unable to remove epoll fd"));
VIR_DEBUG(":fail");
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
goto cleanup;
}
console->contEpoll = 0;
@@ -1075,7 +1080,7 @@ static void virLXCControllerConsoleEPoll(int watch, int fd, int
events, void *op
continue;
virReportSystemError(errno, "%s",
_("Unable to wait on epoll"));
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
goto cleanup;
}
@@ -1188,7 +1193,7 @@ static void virLXCControllerConsoleIO(int watch, int fd, int events,
void *opaqu
virEventRemoveHandle(console->contWatch);
virEventRemoveHandle(console->hostWatch);
console->contWatch = console->hostWatch = -1;
- virNetServerQuit(console->server);
+ virNetDaemonQuit(console->daemon);
virMutexUnlock(&lock);
}
@@ -1208,7 +1213,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
int rc = -1;
size_t i;
- if (virNetServerAddSignalHandler(ctrl->server,
+ if (virNetDaemonAddSignalHandler(ctrl->daemon,
SIGCHLD,
virLXCControllerSignalChildIO,
ctrl) < 0)
@@ -1254,7 +1259,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
}
}
- virNetServerRun(ctrl->server);
+ virNetDaemonRun(ctrl->daemon);
err = virGetLastError();
if (!err || err->code == VIR_ERR_OK)
@@ -2228,7 +2233,7 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl,
VIR_DEBUG("Waiting for client to complete dispatch");
ctrl->inShutdown = true;
virNetServerClientDelayedClose(ctrl->client);
- virNetServerRun(ctrl->server);
+ virNetDaemonRun(ctrl->daemon);
}
VIR_DEBUG("Client has gone away");
return 0;
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
new file mode 100644
index 000000000000..a6d6a4bd8446
--- /dev/null
+++ b/src/rpc/virnetdaemon.c
@@ -0,0 +1,749 @@
+/*
+ * 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(a)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);
+}
diff --git a/src/rpc/virnetdaemon.h b/src/rpc/virnetdaemon.h
new file mode 100644
index 000000000000..9e176d65ca6a
--- /dev/null
+++ b/src/rpc/virnetdaemon.h
@@ -0,0 +1,82 @@
+/*
+ * 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(a)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__ */
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 2af878977a1b..60a9714f6096 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -1,7 +1,7 @@
/*
* 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
*
* This library is free software; you can redistribute it and/or
@@ -23,40 +23,19 @@
#include <config.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-
#include "virnetserver.h"
#include "virlog.h"
#include "viralloc.h"
#include "virerror.h"
#include "virthread.h"
#include "virthreadpool.h"
-#include "virutil.h"
-#include "virfile.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 _virNetServerSignal virNetServerSignal;
-typedef virNetServerSignal *virNetServerSignalPtr;
-
-struct _virNetServerSignal {
- struct sigaction oldaction;
- int signum;
- virNetServerSignalFunc func;
- void *opaque;
-};
typedef struct _virNetServerJob virNetServerJob;
typedef virNetServerJob *virNetServerJobPtr;
@@ -72,14 +51,6 @@ struct _virNetServer {
virThreadPoolPtr workers;
- bool privileged;
-
- size_t nsignals;
- virNetServerSignalPtr *signals;
- int sigread;
- int sigwrite;
- int sigwatch;
-
char *mdnsGroupName;
virNetServerMDNSPtr mdns;
virNetServerMDNSGroupPtr mdnsGroup;
@@ -100,17 +71,10 @@ struct _virNetServer {
unsigned int keepaliveCount;
bool keepaliveRequired;
- bool quit;
-
#ifdef WITH_GNUTLS
virNetTLSContextPtr tls;
#endif
- unsigned int autoShutdownTimeout;
- size_t autoShutdownInhibitions;
- bool autoShutdownCallingInhibit;
- int autoShutdownInhibitFd;
-
virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
virFreeCallback clientPrivFree;
@@ -356,7 +320,6 @@ virNetServerPtr virNetServerNew(size_t min_workers,
void *clientPrivOpaque)
{
virNetServerPtr srv;
- struct sigaction sig_action;
if (virNetServerInitialize() < 0)
return NULL;
@@ -376,13 +339,10 @@ virNetServerPtr virNetServerNew(size_t min_workers,
srv->keepaliveInterval = keepaliveInterval;
srv->keepaliveCount = keepaliveCount;
srv->keepaliveRequired = keepaliveRequired;
- srv->sigwrite = srv->sigread = -1;
srv->clientPrivNew = clientPrivNew;
srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
srv->clientPrivFree = clientPrivFree;
srv->clientPrivOpaque = clientPrivOpaque;
- srv->privileged = geteuid() == 0;
- srv->autoShutdownInhibitFd = -1;
if (VIR_STRDUP(srv->mdnsGroupName, mdnsGroupName) < 0)
goto error;
@@ -394,15 +354,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
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;
-
error:
virObjectUnref(srv);
return NULL;
@@ -499,7 +451,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr
object,
goto error;
}
- n = virJSONValueArraySize(services);
+ n = virJSONValueArraySize(services);
if (n < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed services data in JSON document"));
@@ -532,7 +484,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr
object,
goto error;
}
- n = virJSONValueArraySize(clients);
+ n = virJSONValueArraySize(clients);
if (n < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed clients data in JSON document"));
@@ -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,
virNetServerServicePtr svc,
@@ -1023,22 +695,6 @@ int virNetServerSetTLSContext(virNetServerPtr srv,
#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
virNetServerUpdateServicesLocked(virNetServerPtr srv,
bool enabled)
@@ -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)
{
virNetServerPtr srv = obj;
size_t i;
- VIR_FORCE_CLOSE(srv->autoShutdownInhibitFd);
-
for (i = 0; i < srv->nservices; i++)
virNetServerServiceToggle(srv->services[i], false);
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++)
virObjectUnref(srv->services[i]);
VIR_FREE(srv->services);
@@ -1280,3 +825,62 @@ size_t virNetServerTrackCompletedAuth(virNetServerPtr srv)
virObjectUnlock(srv);
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);
+}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 4b452be5a1ad..5c28182ffd15 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -1,7 +1,7 @@
/*
* 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
*
* This library is free software; you can redistribute it and/or
@@ -24,8 +24,6 @@
#ifndef __VIR_NET_SERVER_H__
# define __VIR_NET_SERVER_H__
-# include <signal.h>
-
# ifdef WITH_GNUTLS
# include "virnettlscontext.h"
# endif
@@ -35,6 +33,9 @@
# include "virobject.h"
# include "virjson.h"
+typedef struct _virNetServer virNetServer;
+typedef virNetServer *virNetServerPtr;
+
virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers,
size_t priority_workers,
@@ -56,24 +57,9 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
virFreeCallback clientPrivFree,
void *clientPrivOpaque);
-virJSONValuePtr virNetServerPreExecRestart(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);
+void virNetServerClose(virNetServerPtr srv);
-int virNetServerAddSignalHandler(virNetServerPtr srv,
- int signum,
- virNetServerSignalFunc func,
- void *opaque);
+virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv);
int virNetServerAddService(virNetServerPtr srv,
virNetServerServicePtr svc,
@@ -90,18 +76,18 @@ int virNetServerSetTLSContext(virNetServerPtr srv,
virNetTLSContextPtr tls);
# endif
-void virNetServerUpdateServices(virNetServerPtr srv,
- bool enabled);
-
-void virNetServerRun(virNetServerPtr srv);
-
-void virNetServerQuit(virNetServerPtr srv);
-
-void virNetServerClose(virNetServerPtr srv);
-
bool virNetServerKeepAliveRequired(virNetServerPtr srv);
size_t virNetServerTrackPendingAuth(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__ */
diff --git a/src/rpc/virnetserverprogram.h b/src/rpc/virnetserverprogram.h
index c1ae17ee5f22..0ccc372e8d7d 100644
--- a/src/rpc/virnetserverprogram.h
+++ b/src/rpc/virnetserverprogram.h
@@ -28,6 +28,9 @@
# include "virnetserverclient.h"
# include "virobject.h"
+typedef struct _virNetDaemon virNetDaemon;
+typedef virNetDaemon *virNetDaemonPtr;
+
typedef struct _virNetServer virNetServer;
typedef virNetServer *virNetServerPtr;
--
2.4.3