This allows to have more servers in one daemon which helps isolating some resources. Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> --- 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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + */ + +#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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list