]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Replace polling for active VMs with signalling by drivers
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 31 Oct 2012 19:03:55 +0000 (19:03 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 4 Dec 2012 12:14:04 +0000 (12:14 +0000)
Currently to deal with auto-shutdown libvirtd must periodically
poll all stateful drivers. Thus sucks because it requires
acquiring both the driver lock and locks on every single virtual
machine. Instead pass in a "inhibit" callback to virStateInitialize
which drivers can invoke whenever they want to inhibit shutdown
due to existance of active VMs.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
26 files changed:
daemon/libvirtd.c
src/Makefile.am
src/driver.h
src/libvirt.c
src/libvirt_internal.h
src/libvirt_private.syms
src/libxl/libxl_conf.h
src/libxl/libxl_driver.c
src/lxc/lxc_conf.h
src/lxc/lxc_driver.c
src/lxc/lxc_process.c
src/network/bridge_driver.c
src/node_device/node_device_hal.c
src/node_device/node_device_udev.c
src/nwfilter/nwfilter_driver.c
src/qemu/qemu_conf.h
src/qemu/qemu_driver.c
src/qemu/qemu_process.c
src/remote/remote_driver.c
src/rpc/virnetserver.c
src/rpc/virnetserver.h
src/secret/secret_driver.c
src/storage/storage_driver.c
src/uml/uml_conf.h
src/uml/uml_driver.c
src/xen/xen_driver.c

index 1ebbac1d95c3908221b10600e2e2255d795957f5..f7046f619f6f1f2419caed62d9d7647e43afa110 100644 (file)
@@ -584,16 +584,6 @@ error:
 }
 
 
-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,
@@ -772,6 +762,18 @@ static int daemonSetupSignals(virNetServerPtr srv)
     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;
@@ -780,7 +782,9 @@ static void daemonRunStateInit(void *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);
@@ -1270,9 +1274,7 @@ int main(int argc, char **argv) {
     if (timeout != -1) {
         VIR_DEBUG("Registering shutdown timeout %d", timeout);
         virNetServerAutoShutdown(srv,
-                                 timeout,
-                                 daemonShutdownCheck,
-                                 NULL);
+                                 timeout);
     }
 
     if ((daemonSetupSignals(srv)) < 0) {
index 01cb9954c3c5b1c4f973c97e6246502f2df3eb9d..54e9611383d87fc28a802e370e2b992f079cc37a 100644 (file)
@@ -1603,12 +1603,14 @@ libvirt_net_rpc_server_la_SOURCES = \
        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)
index e64f07dc2dc8b76a585444f10aa6293f2328e35a..64d652f82929a2666a7919a92b57d6cbce2cbbf4 100644 (file)
@@ -1500,10 +1500,12 @@ struct _virStorageDriver {
 };
 
 # 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;
@@ -1514,7 +1516,6 @@ struct _virStateDriver {
     virDrvStateInitialize  initialize;
     virDrvStateCleanup     cleanup;
     virDrvStateReload      reload;
-    virDrvStateActive      active;
     virDrvStateStop        stop;
 };
 # endif
index 13048535191366a2cab2b51a776221bf2a53eb5e..4b7baab188a752a73d2f8cbf8ffb7b2b3db0d309 100644 (file)
@@ -790,12 +790,17 @@ virRegisterStateDriver(virStateDriverPtr driver)
 /**
  * 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)
@@ -805,7 +810,9 @@ int virStateInitialize(bool privileged) {
         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;
@@ -851,24 +858,6 @@ int virStateReload(void) {
     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:
  *
index b85a29d5174df6785454021612fe2c921ddd0f58..2eda156bd684afd513dd27cab0a614ca18fc0064 100644 (file)
 # 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
 
index 41e262900caf5e42a85703d6da11b09e821e92fc..df54f1e73c9df721f3afa9f5c56cb1e702313cb2 100644 (file)
@@ -1595,6 +1595,7 @@ xdr_virNetMessageError;
 # virnetserver.h
 virNetServerAddProgram;
 virNetServerAddService;
+virNetServerAddShutdownInhibition;
 virNetServerAddSignalHandler;
 virNetServerAutoShutdown;
 virNetServerClose;
@@ -1604,6 +1605,7 @@ virNetServerNew;
 virNetServerNewPostExecRestart;
 virNetServerPreExecRestart;
 virNetServerQuit;
+virNetServerRemoveShutdownInhibition;
 virNetServerRun;
 virNetServerSetTLSContext;
 virNetServerUpdateServices;
index 56bf85c1af92e1ea8e567dc1175bfd015121a364..189a4e9284c379883de51419877fae7d02d656ef 100644 (file)
@@ -61,6 +61,11 @@ struct _libxlDriverPrivate {
     libxl_ctx ctx;
 
     virBitmapPtr reservedVNCPorts;
+
+    size_t nactive;
+    virStateInhibitCallback inhibitCallback;
+    void *inhibitOpaque;
+
     virDomainObjList domains;
 
     virDomainEventStatePtr domainEventState;
index ae4451a5198d713877ff8153f365ccd96044c865..c67d95ad3e500a2ff32c431388952ba01357a05d 100644 (file)
@@ -312,6 +312,10 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
         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) {
@@ -717,6 +721,10 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
     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 :
@@ -782,6 +790,10 @@ libxlReconnectDomain(void *payload,
     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);
@@ -834,7 +846,10 @@ libxlShutdown(void)
 }
 
 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;
@@ -1030,14 +1045,6 @@ libxlReload(void)
     return 0;
 }
 
-static int
-libxlActive(void)
-{
-    if (!libxl_driver)
-        return 0;
-
-    return 1;
-}
 
 static virDrvOpenStatus
 libxlOpen(virConnectPtr conn,
@@ -3969,7 +3976,6 @@ static virStateDriver libxlStateDriver = {
     .initialize = libxlStartup,
     .cleanup = libxlShutdown,
     .reload = libxlReload,
-    .active = libxlActive,
 };
 
 
index 4ae0c5e8f8af6055c0b388536bfdba1da43cff60..ea345bede2865ecd440130a11c7a599315333cb1 100644 (file)
@@ -52,6 +52,11 @@ struct _virLXCDriver {
     virCapsPtr caps;
 
     virCgroupPtr cgroup;
+
+    size_t nactive;
+    virStateInhibitCallback inhibitCallback;
+    void *inhibitOpaque;
+
     virDomainObjList domains;
     char *configDir;
     char *autostartDir;
index 75c4f52543a987f1df428294c8be041f844e603f..e0e76e6da8bde67b9e813182c8326869cd2890d7 100644 (file)
@@ -70,7 +70,9 @@
 
 #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;
 
@@ -1398,7 +1400,9 @@ error:
 }
 
 
-static int lxcStartup(bool privileged)
+static int lxcStartup(bool privileged,
+                      virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+                      void *opaque ATTRIBUTE_UNUSED)
 {
     char *ld;
     int rc;
@@ -1564,26 +1568,6 @@ static int lxcShutdown(void)
     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)
 {
@@ -3014,7 +2998,6 @@ static virStateDriver lxcStateDriver = {
     .name = LXC_DRIVER_NAME,
     .initialize = lxcStartup,
     .cleanup = lxcShutdown,
-    .active = lxcActive,
     .reload = lxcReload,
 };
 
index 8b9d02fb3f97facbbd0db5f312e93cde1183dcdb..50c61c5f9c1ddf14dccdd588b69a064f0747f541 100644 (file)
@@ -252,6 +252,10 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
     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);
@@ -1139,6 +1143,10 @@ int virLXCProcessStart(virConnectPtr conn,
     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];
 
@@ -1313,6 +1321,10 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v
         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;
 
index 03ba4c61b2aa714e994f7cd707e80dc378963ba0..e8be00adb564bd8b3098dc13f40be23452eb7140 100644 (file)
@@ -332,7 +332,10 @@ firewalld_dbus_filter_bridge(DBusConnection *connection ATTRIBUTE_UNUSED,
  * 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;
index 96d23a4e8c7144c4798886d6d56d501440bb5a45..080aaeda45a3620249f8e85487cfbfac8faf5a75 100644 (file)
@@ -586,9 +586,9 @@ static void device_prop_modified(LibHalContext *ctx ATTRIBUTE_UNUSED,
 }
 
 
-
-
-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;
index 393fe20b82785d28d90e1eec12400bd6a6c30690..c9ca00c9f1344e45902b5a2a0088a2893e24cdc9 100644 (file)
@@ -1604,7 +1604,9 @@ out:
     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;
index ddf0bbd98d593412f8e5907d36ab192afe7078cc..3aa026ae4d50389c20de2e64ab562d9b8ce54d43 100644 (file)
@@ -165,7 +165,9 @@ nwfilterDriverInstallDBusMatches(DBusConnection *sysbus ATTRIBUTE_UNUSED)
  * 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;
index e1966319f833f41ad999c333d5ec06c9ff25182c..d0d25ceb2f7d02ebbf3a65a17b2a8cc295cfb6d4 100644 (file)
@@ -73,6 +73,10 @@ struct _virQEMUDriver {
     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
index 9f851497b6ae9f432b3d1c7831d3e5ee9df11785..bb1ec059a2ab01fc75307b68261cea5d1e7f93e1 100644 (file)
@@ -610,7 +610,10 @@ qemuDomainFindMaxID(void *payload,
  * 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;
@@ -631,6 +634,8 @@ qemuStartup(bool privileged) {
 
     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;
@@ -974,28 +979,6 @@ qemuReload(void) {
     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:
@@ -15066,7 +15049,6 @@ static virStateDriver qemuStateDriver = {
     .initialize = qemuStartup,
     .cleanup = qemuShutdown,
     .reload = qemuReload,
-    .active = qemuActive,
     .stop = qemuStop,
 };
 
index d4dad1fc29b5768bdbe695af423a1bf07fbfa16c..ab045995a7cc3732ffcf52def08e68b3e126b38e 100644 (file)
@@ -3228,6 +3228,10 @@ qemuProcessReconnect(void *opaque)
             goto error;
     }
 
+    if (!driver->nactive && driver->inhibitCallback)
+        driver->inhibitCallback(true, driver->inhibitOpaque);
+    driver->nactive++;
+
 endjob:
     if (!qemuDomainObjEndJob(driver, obj))
         obj = NULL;
@@ -3436,6 +3440,10 @@ int qemuProcessStart(virConnectPtr conn,
     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);
@@ -4002,6 +4010,10 @@ void qemuProcessStop(virQEMUDriverPtr driver,
      */
     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. */
@@ -4233,6 +4245,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
 
     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"),
index 2b846eae82ecd104fb5af193fc0abbc403284473..e5d4af3070a500de3e564313fae414f130bbfd85 100644 (file)
@@ -150,7 +150,9 @@ static char *get_transport_from_scheme(char *scheme);
 
 #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
index cf15240d88b6c93bec3ce0348dc3dd03ad9de933..b10839933bc3ab8b2fd45ef7b72d1beadf8a6c7e 100644 (file)
@@ -101,8 +101,7 @@ struct _virNetServer {
     virNetTLSContextPtr tls;
 
     unsigned int autoShutdownTimeout;
-    virNetServerAutoShutdownFunc autoShutdownFunc;
-    void *autoShutdownOpaque;
+    size_t autoShutdownInhibitions;
 
     virNetServerClientPrivNew clientPrivNew;
     virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
@@ -707,19 +706,33 @@ bool virNetServerIsPrivileged(virNetServerPtr srv)
 
 
 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;
@@ -932,7 +945,7 @@ static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
 
     virNetServerLock(srv);
 
-    if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) {
+    if (!srv->autoShutdownInhibitions) {
         VIR_DEBUG("Automatic shutdown triggered");
         srv->quit = 1;
     }
index ff2dc942ea54d8b84887f999cf1a5a826d940c8f..38cccfe77bff984d0226f769ef3dfa8d47791868 100644 (file)
@@ -60,9 +60,10 @@ typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
 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);
 
index c7aabfcf28c64884f952cbaa088905410bcd2196..d9ba42bc2654fbc807ab25e7df709a2276a0b350 100644 (file)
@@ -1073,7 +1073,9 @@ secretDriverCleanup(void)
 }
 
 static int
-secretDriverStartup(bool privileged)
+secretDriverStartup(bool privileged,
+                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+                    void *opaque ATTRIBUTE_UNUSED)
 {
     char *base = NULL;
 
@@ -1166,7 +1168,6 @@ static virStateDriver stateDriver = {
     .initialize = secretDriverStartup,
     .cleanup = secretDriverCleanup,
     .reload = secretDriverReload,
-    .active = NULL      /* All persistent state is immediately saved to disk */
 };
 
 int
index 55177337d2c136c934fdcc85e6bf62c6e13e8dc0..3cb231243ee79ff6a5407aa5118a5e5dcd04dba2 100644 (file)
@@ -128,7 +128,9 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
  * 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;
 
index ebae24e4bc66a04d017ccb50154f87fa9ad036aa..9bddedcf856e8f6bff3deb6e3a199bce525a9dad 100644 (file)
@@ -45,11 +45,14 @@ struct uml_driver {
     virMutex lock;
 
     bool privileged;
+    virStateInhibitCallback inhibitCallback;
+    void *inhibitOpaque;
 
     unsigned long umlVersion;
     int nextvmid;
 
     virDomainObjList domains;
+    size_t nactive;
 
     char *configDir;
     char *autostartDir;
index 5a87e3191a5ffe9a730fe4c62b60409b0b0ccb2b..7eedaf1ce91918499f7414966dbfcecddd1ea885 100644 (file)
@@ -372,6 +372,11 @@ reread:
             }
 
             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);
 
@@ -419,7 +424,9 @@ cleanup:
  * Initialization function for the Uml daemon
  */
 static int
-umlStartup(bool privileged)
+umlStartup(bool privileged,
+           virStateInhibitCallback callback,
+           void *opaque)
 {
     char *base = NULL;
     char *userdir = NULL;
@@ -428,6 +435,8 @@ umlStartup(bool privileged)
         return -1;
 
     uml_driver->privileged = privileged;
+    uml_driver->inhibitCallback = callback;
+    uml_driver->inhibitOpaque = opaque;
 
     if (virMutexInit(&uml_driver->lock) < 0) {
         VIR_FREE(uml_driver);
@@ -585,27 +594,6 @@ umlReload(void) {
     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(&uml_driver->domains, 1);
-    umlDriverUnlock(uml_driver);
-
-    return active;
-}
 
 static void
 umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
@@ -1154,6 +1142,10 @@ static void umlShutdownVMDaemon(struct uml_driver *driver,
         vm->def->id = -1;
         vm->newDef = NULL;
     }
+
+    driver->nactive--;
+    if (!driver->nactive && driver->inhibitCallback)
+        driver->inhibitCallback(false, driver->inhibitOpaque);
 }
 
 
@@ -2634,7 +2626,6 @@ static virStateDriver umlStateDriver = {
     .initialize = umlStartup,
     .cleanup = umlShutdown,
     .reload = umlReload,
-    .active = umlActive,
 };
 
 int umlRegister(void) {
index 5a407577c0b79ad8335f9436bcee0151e2526738..15e760d6065bf9ffd6e2764a953dede037c887cb 100644 (file)
@@ -201,7 +201,9 @@ done:
 #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;