}
-static int daemonShutdownCheck(virNetServerPtr srv ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- if (virStateActive())
- return 0;
-
- return 1;
-}
-
-
/*
* Set up the logging environment
* By default if daemonized all errors go to the logfile libvirtd.log,
return 0;
}
+
+static void daemonInhibitCallback(bool inhibit, void *opaque)
+{
+ virNetServerPtr srv = opaque;
+
+ if (inhibit)
+ virNetServerAddShutdownInhibition(srv);
+ else
+ virNetServerRemoveShutdownInhibition(srv);
+}
+
+
static void daemonRunStateInit(void *opaque)
{
virNetServerPtr srv = opaque;
* 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)) < 0) {
+ if (virStateInitialize(virNetServerIsPrivileged(srv),
+ daemonInhibitCallback,
+ srv) < 0) {
VIR_ERROR(_("Driver state initialization failed"));
/* Ensure the main event loop quits */
kill(getpid(), SIGTERM);
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
virNetServerAutoShutdown(srv,
- timeout,
- daemonShutdownCheck,
- NULL);
+ timeout);
}
if ((daemonSetupSignals(srv)) < 0) {
rpc/virnetserver.h rpc/virnetserver.c
libvirt_net_rpc_server_la_CFLAGS = \
$(AVAHI_CFLAGS) \
+ $(DBUS_CFLAGS) \
$(XDR_CFLAGS) \
$(AM_CFLAGS) \
$(POLKIT_CFLAGS)
libvirt_net_rpc_server_la_LDFLAGS = \
$(AM_LDFLAGS) \
$(AVAHI_LIBS) \
+ $(DBUS_LIBS) \
$(POLKIT_LIBS) \
$(CYGWIN_EXTRA_LDFLAGS) \
$(MINGW_EXTRA_LDFLAGS)
};
# ifdef WITH_LIBVIRTD
-typedef int (*virDrvStateInitialize) (bool privileged);
+
+typedef int (*virDrvStateInitialize) (bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque);
typedef int (*virDrvStateCleanup) (void);
typedef int (*virDrvStateReload) (void);
-typedef int (*virDrvStateActive) (void);
typedef int (*virDrvStateStop) (void);
typedef struct _virStateDriver virStateDriver;
virDrvStateInitialize initialize;
virDrvStateCleanup cleanup;
virDrvStateReload reload;
- virDrvStateActive active;
virDrvStateStop stop;
};
# endif
/**
* virStateInitialize:
* @privileged: set to true if running with root privilege, false otherwise
+ * @callback: callback to invoke to inhibit shutdown of the daemon
+ * @opaque: data to pass to @callback
*
* Initialize all virtualization drivers.
*
* Returns 0 if all succeed, -1 upon any failure.
*/
-int virStateInitialize(bool privileged) {
+int virStateInitialize(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
+{
int i;
if (virInitialize() < 0)
if (virStateDriverTab[i]->initialize) {
VIR_DEBUG("Running global init for %s state driver",
virStateDriverTab[i]->name);
- if (virStateDriverTab[i]->initialize(privileged) < 0) {
+ if (virStateDriverTab[i]->initialize(privileged,
+ callback,
+ opaque) < 0) {
VIR_ERROR(_("Initialization of %s state driver failed"),
virStateDriverTab[i]->name);
return -1;
return ret;
}
-/**
- * virStateActive:
- *
- * Run each virtualization driver's "active" method.
- *
- * Returns 0 if none are active, 1 if at least one is.
- */
-int virStateActive(void) {
- int i, ret = 0;
-
- for (i = 0 ; i < virStateDriverTabCount ; i++) {
- if (virStateDriverTab[i]->active &&
- virStateDriverTab[i]->active())
- ret = 1;
- }
- return ret;
-}
-
/**
* virStateStop:
*
# include "internal.h"
# ifdef WITH_LIBVIRTD
-int virStateInitialize(bool privileged);
+typedef void (*virStateInhibitCallback)(bool inhibit,
+ void *opaque);
+
+int virStateInitialize(bool privileged,
+ virStateInhibitCallback inhibit,
+ void *opaque);
int virStateCleanup(void);
int virStateReload(void);
-int virStateActive(void);
int virStateStop(void);
# endif
# virnetserver.h
virNetServerAddProgram;
virNetServerAddService;
+virNetServerAddShutdownInhibition;
virNetServerAddSignalHandler;
virNetServerAutoShutdown;
virNetServerClose;
virNetServerNewPostExecRestart;
virNetServerPreExecRestart;
virNetServerQuit;
+virNetServerRemoveShutdownInhibition;
virNetServerRun;
virNetServerSetTLSContext;
virNetServerUpdateServices;
libxl_ctx ctx;
virBitmapPtr reservedVNCPorts;
+
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
virDomainEventStatePtr domainEventState;
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
}
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport) {
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto error;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
restore_fd < 0 ?
VIR_DOMAIN_EVENT_STARTED_BOOTED :
vm->def->id = d_info.domid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
/* Recreate domain death et. al. events */
libxlCreateDomEvents(vm);
virDomainObjUnlock(vm);
}
static int
-libxlStartup(bool privileged) {
+libxlStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
const libxl_version_info *ver_info;
char *log_file = NULL;
virCommandPtr cmd;
return 0;
}
-static int
-libxlActive(void)
-{
- if (!libxl_driver)
- return 0;
-
- return 1;
-}
static virDrvOpenStatus
libxlOpen(virConnectPtr conn,
.initialize = libxlStartup,
.cleanup = libxlShutdown,
.reload = libxlReload,
- .active = libxlActive,
};
virCapsPtr caps;
virCgroupPtr cgroup;
+
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
char *configDir;
char *autostartDir;
#define LXC_NB_MEM_PARAM 3
-static int lxcStartup(bool privileged);
+static int lxcStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque);
static int lxcShutdown(void);
virLXCDriverPtr lxc_driver = NULL;
}
-static int lxcStartup(bool privileged)
+static int lxcStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *ld;
int rc;
return 0;
}
-/**
- * lxcActive:
- *
- * Checks if the LXC daemon is active, i.e. has an active domain
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-lxcActive(void) {
- int active;
-
- if (lxc_driver == NULL)
- return 0;
-
- lxcDriverLock(lxc_driver);
- active = virDomainObjListNumOfDomains(&lxc_driver->domains, 1);
- lxcDriverUnlock(lxc_driver);
-
- return active;
-}
static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
{
.name = LXC_DRIVER_NAME,
.initialize = lxcStartup,
.cleanup = lxcShutdown,
- .active = lxcActive,
.reload = lxcReload,
};
vm->pid = -1;
vm->def->id = -1;
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
for (i = 0 ; i < vm->def->nnets ; i++) {
virDomainNetDefPtr iface = vm->def->nets[i];
vport = virDomainNetGetActualVirtPortProfile(iface);
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
priv->doneStopEvent = false;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
char out[1024];
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
goto error;
* Initialization function for the QEmu daemon
*/
static int
-networkStartup(bool privileged) {
+networkStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
char *base = NULL;
#ifdef HAVE_FIREWALLD
DBusConnection *sysbus = NULL;
}
-
-
-static int halDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED)
+static int halDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
LibHalContext *hal_ctx = NULL;
char **udi = NULL;
return ret;
}
-static int udevDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED)
+static int udevDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
udevPrivate *priv = NULL;
struct udev *udev = NULL;
* Initialization function for the QEmu daemon
*/
static int
-nwfilterDriverStartup(bool privileged)
+nwfilterDriverStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
DBusConnection *sysbus = NULL;
int cgroupControllers;
char **cgroupDeviceACL;
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
/* These four directories are ones libvirtd uses (so must be root:root
* Initialization function for the QEmu daemon
*/
static int
-qemuStartup(bool privileged) {
+qemuStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
+{
char *base = NULL;
char *driverConf = NULL;
int rc;
qemu_driver->privileged = privileged;
qemu_driver->uri = privileged ? "qemu:///system" : "qemu:///session";
+ qemu_driver->inhibitCallback = callback;
+ qemu_driver->inhibitOpaque = opaque;
/* Don't have a dom0 so start from 1 */
qemu_driver->nextvmid = 1;
return 0;
}
-/**
- * qemuActive:
- *
- * Checks if the QEmu daemon is active, i.e. has an active domain or
- * an active network
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-qemuActive(void) {
- int active = 0;
-
- if (!qemu_driver)
- return 0;
-
- /* XXX having to iterate here is not great because it requires many locks */
- qemuDriverLock(qemu_driver);
- active = virDomainObjListNumOfDomains(&qemu_driver->domains, 1);
- qemuDriverUnlock(qemu_driver);
- return active;
-}
-
/*
* qemuStop:
.initialize = qemuStartup,
.cleanup = qemuShutdown,
.reload = qemuReload,
- .active = qemuActive,
.stop = qemuStop,
};
goto error;
}
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
endjob:
if (!qemuDomainObjEndJob(driver, obj))
obj = NULL;
qemuDomainSetFakeReboot(driver, vm, false);
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
/* Run an early hook to set-up missing devices */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
*/
vm->def->id = -1;
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) {
/* To not break the normal domain shutdown process, skip the
* timestamp log writing if failed on opening log file. */
vm->def->id = driver->nextvmid++;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (virFileMakePath(driver->logDir) < 0) {
virReportSystemError(errno,
_("cannot create log directory %s"),
#ifdef WITH_LIBVIRTD
static int
-remoteStartup(bool privileged ATTRIBUTE_UNUSED)
+remoteStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
/* Mark that we're inside the daemon so we can avoid
* re-entering ourselves
virNetTLSContextPtr tls;
unsigned int autoShutdownTimeout;
- virNetServerAutoShutdownFunc autoShutdownFunc;
- void *autoShutdownOpaque;
+ size_t autoShutdownInhibitions;
virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque)
+ unsigned int timeout)
{
virNetServerLock(srv);
srv->autoShutdownTimeout = timeout;
- srv->autoShutdownFunc = func;
- srv->autoShutdownOpaque = opaque;
virNetServerUnlock(srv);
}
+
+void virNetServerAddShutdownInhibition(virNetServerPtr srv)
+{
+ virNetServerLock(srv);
+ srv->autoShutdownInhibitions++;
+ virNetServerUnlock(srv);
+}
+
+
+void virNetServerRemoveShutdownInhibition(virNetServerPtr srv)
+{
+ virNetServerLock(srv);
+ srv->autoShutdownInhibitions--;
+ virNetServerUnlock(srv);
+}
+
+
+
static sig_atomic_t sigErrors = 0;
static int sigLastErrno = 0;
static int sigWrite = -1;
virNetServerLock(srv);
- if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) {
+ if (!srv->autoShutdownInhibitions) {
VIR_DEBUG("Automatic shutdown triggered");
srv->quit = 1;
}
bool virNetServerIsPrivileged(virNetServerPtr srv);
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque);
+ unsigned int timeout);
+
+void virNetServerAddShutdownInhibition(virNetServerPtr srv);
+void virNetServerRemoveShutdownInhibition(virNetServerPtr srv);
typedef void (*virNetServerSignalFunc)(virNetServerPtr srv, siginfo_t *info, void *opaque);
}
static int
-secretDriverStartup(bool privileged)
+secretDriverStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
.initialize = secretDriverStartup,
.cleanup = secretDriverCleanup,
.reload = secretDriverReload,
- .active = NULL /* All persistent state is immediately saved to disk */
};
int
* Initialization function for the QEmu daemon
*/
static int
-storageDriverStartup(bool privileged)
+storageDriverStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
virMutex lock;
bool privileged;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
unsigned long umlVersion;
int nextvmid;
virDomainObjList domains;
+ size_t nactive;
char *configDir;
char *autostartDir;
}
dom->def->id = driver->nextvmid++;
+
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_BOOTED);
* Initialization function for the Uml daemon
*/
static int
-umlStartup(bool privileged)
+umlStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
{
char *base = NULL;
char *userdir = NULL;
return -1;
uml_driver->privileged = privileged;
+ uml_driver->inhibitCallback = callback;
+ uml_driver->inhibitOpaque = opaque;
if (virMutexInit(¨_driver->lock) < 0) {
VIR_FREE(uml_driver);
return 0;
}
-/**
- * umlActive:
- *
- * Checks if the Uml daemon is active, i.e. has an active domain or
- * an active network
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-umlActive(void) {
- int active = 0;
-
- if (!uml_driver)
- return 0;
-
- umlDriverLock(uml_driver);
- active = virDomainObjListNumOfDomains(¨_driver->domains, 1);
- umlDriverUnlock(uml_driver);
-
- return active;
-}
static void
umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
vm->def->id = -1;
vm->newDef = NULL;
}
+
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
}
.initialize = umlStartup,
.cleanup = umlShutdown,
.reload = umlReload,
- .active = umlActive,
};
int umlRegister(void) {
#ifdef WITH_LIBVIRTD
static int
-xenInitialize(bool privileged ATTRIBUTE_UNUSED)
+xenInitialize(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
inside_daemon = true;
return 0;