From 70da0494c131b344d88893f7d090754ee3192d39 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 26 Jun 2007 22:56:14 +0000 Subject: [PATCH] Add driver API for global startup/shutdown/reload hooks --- ChangeLog | 7 ++++ qemud/driver.c | 28 +++++++++++++-- qemud/driver.h | 5 +-- qemud/internal.h | 1 + qemud/qemud.c | 47 +++++++++++++++++++++++--- src/driver.h | 15 +++++++++ src/internal.h | 9 +++++ src/libvirt.c | 75 +++++++++++++++++++++++++++++++++++++++++ src/libvirt_sym.version | 5 +++ 9 files changed, 183 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index d75c37ca86..cd65bb3dfe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Jun 26 18:53:00 EST 2007 Daniel P. Berrange + + * src/internal.h, src/libvirt.c, src/driver.h, src/libvirt_sym.version + Added internal driver API hooks for global shutdown/startup/reload + * qemud/driver.c, qemud/driver.h, qemud/internal.h, qemud/qemud.c + Adapt to make use of new driver API for startup/shutdown + Tue Jun 26 18:47:00 EST 2007 Daniel P. Berrange * src/event.h, src/event.c, src/Makefile.am, src/libvirt_sym.version: diff --git a/qemud/driver.c b/qemud/driver.c index 7f0d113e16..62b6ac2ed8 100644 --- a/qemud/driver.c +++ b/qemud/driver.c @@ -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); + + return 0; } -void qemudShutdown() { +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 @@ -2516,6 +2532,12 @@ static virNetworkDriver qemuNetworkDriver = { qemudNetworkSetAutostart, /* networkSetAutostart */ }; +static virStateDriver qemuStateDriver = { + qemudStartup, + qemudShutdown, + qemudReload, + qemudActive, +}; /* * Local variables: diff --git a/qemud/driver.h b/qemud/driver.h index b4228757e1..957754bb8d 100644 --- a/qemud/driver.h +++ b/qemud/driver.h @@ -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 --git a/qemud/internal.h b/qemud/internal.h index 73b38631d5..c709146fc0 100644 --- a/qemud/internal.h +++ b/qemud/internal.h @@ -34,6 +34,7 @@ #include "remote_protocol.h" #include "bridge.h" #include "iptables.h" +#include "../config.h" #ifdef __GNUC__ #ifdef HAVE_ANSIDECL_H diff --git a/qemud/qemud.c b/qemud/qemud.c index 669c61cf92..f33facbc06 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -54,6 +54,7 @@ #include #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 fd ATTRIBUTE_UNUSED, 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 *qemudInitialize(int sigread) { 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; + 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; - while ((ret = qemudOneLoop()) == 0 && !server->shutdown) - ; + /* 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; + } - return ret == -1 ? -1 : 0; + if (server->shutdown) + return 0; + } + + return -1; } static void qemudCleanup(struct qemud_server *server) { @@ -1502,6 +1540,7 @@ static void qemudCleanup(struct qemud_server *server) { qemudShutdown(); + virStateCleanup(); free(server); } diff --git a/src/driver.h b/src/driver.h index 077a4b4a4b..fe4f9e2439 100644 --- a/src/driver.h +++ b/src/driver.h @@ -322,6 +322,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 @@ -330,6 +344,7 @@ struct _virNetworkDriver { */ int virRegisterDriver(virDriverPtr); int virRegisterNetworkDriver(virNetworkDriverPtr); +int virRegisterStateDriver(virStateDriverPtr); #ifdef __cplusplus } diff --git a/src/internal.h b/src/internal.h index a0a074de52..ee7b17e336 100644 --- a/src/internal.h +++ b/src/internal.h @@ -220,6 +220,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 --git a/src/libvirt.c b/src/libvirt.c index e473e533bf..e8ca9173be 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -40,6 +40,8 @@ static virDriverPtr virDriverTab[MAX_DRIVERS]; 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; /** @@ -240,6 +242,79 @@ virRegisterDriver(virDriverPtr 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: * @libVer: return value for the library version (OUT) diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version index d71ca8e197..f32deae9e0 100644 --- a/src/libvirt_sym.version +++ b/src/libvirt_sym.version @@ -111,5 +111,10 @@ __virEventRegisterImpl; + __virStateInitialize; + __virStateCleanup; + __virStateReload; + __virStateActive; + local: *; }; -- GitLab