[Libvir] PATCH 13/20: create internal stateful driver API

Daniel P. Berrange berrange at redhat.com
Fri Jun 22 02:07:08 UTC 2007


Some drivers are stateless (Xen, test), while others are stateful (QEMU).
The later can only be accessed via the daemon. This patch adds a new internal
driver API to allow drivers to register a set of functions for performing
work on daemon startup, shutdown and reload. It makes the QEMU driver in
qemud/driver.c provide implementations of these funtions. It adapts the
qemud/qemud.c to call these new global driver functions. Finally it fixes
the idle timeout shutdown of the daemon disabled in an earlier patch.
NB this patch adds 3 new exported symbols for private use by the daemon.

 qemud/driver.c          |   32 +++++++++++++++++---
 qemud/driver.h          |    5 +--
 qemud/internal.h        |    1 
 qemud/qemud.c           |   51 ++++++++++++++++++++++++++++----
 src/driver.h            |   15 +++++++++
 src/internal.h          |    9 +++++
 src/libvirt.c           |   75 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_sym.version |    5 +++
 8 files changed, 180 insertions(+), 13 deletions(-)


Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
diff -r 968ca2c71e5f qemud/driver.c
--- a/qemud/driver.c	Thu Jun 21 21:20:57 2007 -0400
+++ b/qemud/driver.c	Thu Jun 21 21:20:58 2007 -0400
@@ -205,7 +205,7 @@ int qemudStartup(void) {
     return -1;
 }
 
-void qemudReload(void) {
+int qemudReload(void) {
     qemudScanConfigs(qemu_driver);
 
      if (qemu_driver->iptables) {
@@ -214,14 +214,28 @@ void qemudReload(void) {
     }
 
     qemudAutostartConfigs(qemu_driver);
-}
-
-void qemudShutdown() {
+
+    return 0;
+}
+
+int qemudActive(void) {
+    /* If we've any active networks or guests, then we
+     * mark this driver as active
+     */
+    if (qemu_driver->nactivenetworks &&
+        qemu_driver->nactivevms)
+        return 1;
+
+    /* Otherwise we're happy to deal with a shutdown */
+    return 0;
+}
+
+int qemudShutdown() {
     struct qemud_vm *vm;
     struct qemud_network *network;
 
     if (!qemu_driver)
-        return;
+        return -1;
 
     /* shutdown active VMs */
     vm = qemu_driver->vms;
@@ -279,6 +293,8 @@ void qemudShutdown() {
 
     free(qemu_driver);
     qemu_driver = NULL;
+
+    return 0;
 }
 
 static int
@@ -2510,6 +2526,12 @@ static virNetworkDriver qemuNetworkDrive
     qemudNetworkSetAutostart, /* networkSetAutostart */
 };
 
+static virStateDriver qemuStateDriver = {
+    qemudStartup,
+    qemudShutdown,
+    qemudReload,
+    qemudActive,
+};
 
 /*
  * Local variables:
diff -r 968ca2c71e5f qemud/driver.h
--- a/qemud/driver.h	Thu Jun 21 21:20:57 2007 -0400
+++ b/qemud/driver.h	Thu Jun 21 21:20:58 2007 -0400
@@ -29,8 +29,9 @@
 #include "../src/internal.h"
 
 int qemudStartup(void);
-void qemudReload(void);
-void qemudShutdown(void);
+int qemudReload(void);
+int qemudShutdown(void);
+int qemudActive(void);
 
 
 virDrvOpenStatus qemudOpen(virConnectPtr conn,
diff -r 968ca2c71e5f qemud/internal.h
--- a/qemud/internal.h	Thu Jun 21 21:20:57 2007 -0400
+++ b/qemud/internal.h	Thu Jun 21 21:20:58 2007 -0400
@@ -34,6 +34,7 @@
 #include "remote_protocol.h"
 #include "bridge.h"
 #include "iptables.h"
+#include "../config.h"
 
 #ifdef __GNUC__
 #ifdef HAVE_ANSIDECL_H
diff -r 968ca2c71e5f qemud/qemud.c
--- a/qemud/qemud.c	Thu Jun 21 21:20:57 2007 -0400
+++ b/qemud/qemud.c	Thu Jun 21 21:20:58 2007 -0400
@@ -54,6 +54,7 @@
 #include <libvirt/virterror.h>
 
 #include "internal.h"
+#include "../src/internal.h"
 #include "../src/remote_internal.h"
 #include "../src/conf.h"
 #include "dispatch.h"
@@ -206,6 +207,9 @@ static void qemudDispatchSignalEvent(int
     switch (sigc) {
     case SIGHUP:
         qemudLog(QEMUD_INFO, "Reloading configuration on SIGHUP");
+        if (virStateReload() < 0)
+            qemudLog(QEMUD_WARN, "Error while reloading drivers");
+
         if (!remote) {
             qemudReload();
         }
@@ -704,6 +708,8 @@ static struct qemud_server *qemudInitial
     if (roSockname[0] != '\0' && qemudListenUnix(server, roSockname, 1) < 0)
         goto cleanup;
 
+    virStateInitialize();
+
     if (!remote) /* qemud only */ {
         if (qemudStartup() < 0) {
             goto cleanup;
@@ -1478,13 +1484,45 @@ static int qemudOneLoop(void) {
     return 0;
 }
 
+static void qemudInactiveTimer(int timer ATTRIBUTE_UNUSED, void *data) {
+    struct qemud_server *server = (struct qemud_server *)data;
+    qemudDebug("Got inactive timer expiry");
+    if (!virStateActive()) {
+        qemudDebug("No state active, shutting down");
+        server->shutdown = 1;
+    }
+}
+
 static int qemudRunLoop(struct qemud_server *server) {
-    int ret;
-
-    while ((ret = qemudOneLoop()) == 0 && !server->shutdown)
-        ;
-
-    return ret == -1 ? -1 : 0;
+    int timerid = -1;
+
+    for (;;) {
+        /* A shutdown timeout is specified, so check
+         * if any drivers have active state, if not
+         * shutdown after timeout seconds
+         */
+        if (timeout > 0 && !virStateActive() && !server->clients) {
+            timerid = virEventAddTimeoutImpl(timeout*1000, qemudInactiveTimer, server);
+            qemudDebug("Scheduling shutdown timer %d", timerid);
+        }
+
+        if (qemudOneLoop() < 0)
+            break;
+
+        /* Unregister any timeout that's active, since we
+         * just had an event processed
+         */
+        if (timerid != -1) {
+            qemudDebug("Removing shutdown timer %d", timerid);
+            virEventRemoveTimeoutImpl(timerid);
+            timerid = -1;
+        }
+
+        if (server->shutdown)
+            return 0;
+    }
+
+    return -1;
 }
 
 static void qemudCleanup(struct qemud_server *server) {
@@ -1502,6 +1540,7 @@ static void qemudCleanup(struct qemud_se
 
 
     qemudShutdown();
+    virStateCleanup();
 
     free(server);
 }
diff -r 968ca2c71e5f src/driver.h
--- a/src/driver.h	Thu Jun 21 21:20:57 2007 -0400
+++ b/src/driver.h	Thu Jun 21 21:20:58 2007 -0400
@@ -316,6 +316,20 @@ struct _virNetworkDriver {
 	virDrvNetworkSetAutostart	networkSetAutostart;
 };
 
+typedef int (*virDrvStateInitialize) (void);
+typedef int (*virDrvStateCleanup) (void);
+typedef int (*virDrvStateReload) (void);
+typedef int (*virDrvStateActive) (void);
+
+typedef struct _virStateDriver virStateDriver;
+typedef virStateDriver *virStateDriverPtr;
+
+struct _virStateDriver {
+    virDrvStateInitialize  initialize;
+    virDrvStateCleanup     cleanup;
+    virDrvStateReload      reload;
+    virDrvStateActive      active;
+};
 
 /*
  * Registration
@@ -324,6 +338,7 @@ struct _virNetworkDriver {
  */
 int virRegisterDriver(virDriverPtr);
 int virRegisterNetworkDriver(virNetworkDriverPtr);
+int virRegisterStateDriver(virStateDriverPtr);
 
 #ifdef __cplusplus
 }
diff -r 968ca2c71e5f src/internal.h
--- a/src/internal.h	Thu Jun 21 21:20:57 2007 -0400
+++ b/src/internal.h	Thu Jun 21 21:20:58 2007 -0400
@@ -214,6 +214,15 @@ int		virFreeNetwork	(virConnectPtr conn,
 #define virGetDomain(c,n,u) __virGetDomain((c),(n),(u))
 #define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u))
 
+int __virStateInitialize(void);
+int __virStateCleanup(void);
+int __virStateReload(void);
+int __virStateActive(void);
+#define virStateInitialize() __virStateInitialize()
+#define virStateCleanup() __virStateCleanup()
+#define virStateReload() __virStateReload()
+#define virStateActive() __virStateActive()
+
 #ifdef __cplusplus
 }
 #endif                          /* __cplusplus */
diff -r 968ca2c71e5f src/libvirt.c
--- a/src/libvirt.c	Thu Jun 21 21:20:57 2007 -0400
+++ b/src/libvirt.c	Thu Jun 21 21:20:58 2007 -0400
@@ -40,6 +40,8 @@ static int virDriverTabCount = 0;
 static int virDriverTabCount = 0;
 static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
 static int virNetworkDriverTabCount = 0;
+static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
+static int virStateDriverTabCount = 0;
 static int initialized = 0;
 
 /**
@@ -239,6 +241,79 @@ virRegisterDriver(virDriverPtr driver)
     virDriverTab[virDriverTabCount] = driver;
     return virDriverTabCount++;
 }
+
+/**
+ * virRegisterStateDriver:
+ * @driver: pointer to a driver block
+ *
+ * Register a virtualization driver
+ *
+ * Returns the driver priority or -1 in case of error.
+ */
+int
+virRegisterStateDriver(virStateDriverPtr driver)
+{
+    if (virInitialize() < 0)
+      return -1;
+
+    if (driver == NULL) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+
+    if (virStateDriverTabCount >= MAX_DRIVERS) {
+    	virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+
+    virStateDriverTab[virStateDriverTabCount] = driver;
+    return virStateDriverTabCount++;
+}
+
+int __virStateInitialize(void) {
+    int i, ret = 0;
+
+    if (virInitialize() < 0)
+        return -1;
+
+    for (i = 0 ; i < virStateDriverTabCount ; i++) {
+        if (virStateDriverTab[i]->initialize() < 0)
+            ret = -1;
+    }
+    return ret;
+}
+
+int __virStateCleanup(void) {
+    int i, ret = 0;
+
+    for (i = 0 ; i < virStateDriverTabCount ; i++) {
+        if (virStateDriverTab[i]->cleanup() < 0)
+            ret = -1;
+    }
+    return ret;
+}
+
+int __virStateReload(void) {
+    int i, ret = 0;
+
+    for (i = 0 ; i < virStateDriverTabCount ; i++) {
+        if (virStateDriverTab[i]->reload() < 0)
+            ret = -1;
+    }
+    return ret;
+}
+
+int __virStateActive(void) {
+    int i, ret = 0;
+
+    for (i = 0 ; i < virStateDriverTabCount ; i++) {
+        if (virStateDriverTab[i]->active())
+            ret = 1;
+    }
+    return ret;
+}
+
+
 
 /**
  * virGetVersion:
diff -r 968ca2c71e5f src/libvirt_sym.version
--- a/src/libvirt_sym.version	Thu Jun 21 21:20:57 2007 -0400
+++ b/src/libvirt_sym.version	Thu Jun 21 21:20:58 2007 -0400
@@ -101,5 +101,10 @@
 
 	__virEventRegisterImpl;
 
+ 	__virStateInitialize;
+ 	__virStateCleanup;
+ 	__virStateReload;
+ 	__virStateActive;
+
     local: *;
 };


More information about the libvir-list mailing list