[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