mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
Move daemon-related parts of virNetServer to virNetDaemon
This allows to have more servers in one daemon which helps isolating some resources. Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
parent
387cb8c6b2
commit
fa14207368
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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,13 +237,24 @@ virLockDaemonNewPostExecRestart(virJSONValuePtr object, bool privileged)
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
if (!(lockd->dmn = virNetDaemonNewPostExecRestart(child)))
|
||||
goto error;
|
||||
|
||||
if (!(lockd->srv = virNetDaemonAddServerPostExec(lockd->dmn,
|
||||
virLockDaemonClientNew,
|
||||
virLockDaemonClientNewPostExecRestart,
|
||||
virLockDaemonClientPreExecRestart,
|
||||
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
@ -128,8 +128,7 @@ struct _virLXCController {
|
||||
|
||||
virSecurityManagerPtr securityManager;
|
||||
|
||||
/* Server socket */
|
||||
virNetServerPtr server;
|
||||
virNetDaemonPtr daemon;
|
||||
bool firstClient;
|
||||
virNetServerClientPtr client;
|
||||
virNetServerProgramPtr prog;
|
||||
@ -152,7 +151,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);
|
||||
}
|
||||
|
||||
|
||||
@ -283,7 +282,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
|
||||
if (ctrl->timerShutdown != -1)
|
||||
virEventRemoveTimeout(ctrl->timerShutdown);
|
||||
|
||||
virObjectUnref(ctrl->server);
|
||||
virObjectUnref(ctrl->daemon);
|
||||
virLXCControllerFreeFuse(ctrl);
|
||||
|
||||
VIR_FREE(ctrl->nbdpids);
|
||||
@ -301,7 +300,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;
|
||||
|
||||
@ -902,6 +901,7 @@ static void *virLXCControllerClientPrivateNew(virNetServerClientPtr client,
|
||||
|
||||
static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
|
||||
{
|
||||
virNetServerPtr srv = NULL;
|
||||
virNetServerServicePtr svc = NULL;
|
||||
char *sockpath;
|
||||
|
||||
@ -909,7 +909,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
|
||||
LXC_STATE_DIR, ctrl->name) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(ctrl->server = virNetServerNew(0, 0, 0, 1,
|
||||
if (!(srv = virNetServerNew(0, 0, 0, 1,
|
||||
0, -1, 0, false,
|
||||
NULL,
|
||||
virLXCControllerClientPrivateNew,
|
||||
@ -936,7 +936,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;
|
||||
@ -947,14 +947,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;
|
||||
}
|
||||
@ -982,7 +987,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)
|
||||
{
|
||||
@ -993,7 +998,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) {
|
||||
@ -1052,7 +1057,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;
|
||||
@ -1064,7 +1069,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;
|
||||
@ -1090,7 +1095,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;
|
||||
@ -1102,7 +1107,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;
|
||||
@ -1131,7 +1136,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;
|
||||
}
|
||||
|
||||
@ -1244,7 +1249,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);
|
||||
}
|
||||
|
||||
@ -1264,7 +1269,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
|
||||
int rc = -1;
|
||||
size_t i;
|
||||
|
||||
if (virNetServerAddSignalHandler(ctrl->server,
|
||||
if (virNetDaemonAddSignalHandler(ctrl->daemon,
|
||||
SIGCHLD,
|
||||
virLXCControllerSignalChildIO,
|
||||
ctrl) < 0)
|
||||
@ -1310,7 +1315,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
|
||||
}
|
||||
}
|
||||
|
||||
virNetServerRun(ctrl->server);
|
||||
virNetDaemonRun(ctrl->daemon);
|
||||
|
||||
err = virGetLastError();
|
||||
if (!err || err->code == VIR_ERR_OK)
|
||||
@ -2284,7 +2289,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;
|
||||
|
749
src/rpc/virnetdaemon.c
Normal file
749
src/rpc/virnetdaemon.c
Normal file
@ -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@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);
|
||||
}
|
82
src/rpc/virnetdaemon.h
Normal file
82
src/rpc/virnetdaemon.h
Normal file
@ -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@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__ */
|
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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,25 +57,10 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr object,
|
||||
virFreeCallback clientPrivFree,
|
||||
void *clientPrivOpaque);
|
||||
|
||||
void virNetServerClose(virNetServerPtr srv);
|
||||
|
||||
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);
|
||||
|
||||
int virNetServerAddSignalHandler(virNetServerPtr srv,
|
||||
int signum,
|
||||
virNetServerSignalFunc func,
|
||||
void *opaque);
|
||||
|
||||
int virNetServerAddService(virNetServerPtr srv,
|
||||
virNetServerServicePtr svc,
|
||||
const char *mdnsEntryName);
|
||||
@ -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__ */
|
||||
|
@ -28,6 +28,9 @@
|
||||
# include "virnetserverclient.h"
|
||||
# include "virobject.h"
|
||||
|
||||
typedef struct _virNetDaemon virNetDaemon;
|
||||
typedef virNetDaemon *virNetDaemonPtr;
|
||||
|
||||
typedef struct _virNetServer virNetServer;
|
||||
typedef virNetServer *virNetServerPtr;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user