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 -=|
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: *; };