[libvirt] [PATCH 01/13] Move daemon-related parts of virNetServer to virNetDaemon

Martin Kletzander mkletzan at redhat.com
Tue Jun 16 09:58:18 UTC 2015


This allows to have more servers in one daemon which helps isolating
some resources.

Signed-off-by: Martin Kletzander <mkletzan at 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 at 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 at 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




More information about the libvir-list mailing list