[libvirt] [PATCH 0/2] Network events feature

These changes are all about bringing events for network object like the ones existing for domains. This feature is needed for virt-manager to refresh its UI when networks are started/destroyed/defined/undefined. The first commit is a refactoring of the domain events internal functions to extract the reusable parts of them. The second commit adds network events based on those now-common event functions. The network events are implemented in the test and bridge network drivers ATM. Cédric Bosdonnat (2): virDomainEvent refactoring to separate generic things from domain ones Added network events API and unit tests .gitignore | 2 + daemon/libvirtd.h | 1 + daemon/remote.c | 175 +++- include/libvirt/libvirt.h.in | 85 ++ python/generator.py | 2 + python/libvirt-override-virConnect.py | 34 + python/libvirt-override.c | 150 ++++ src/Makefile.am | 6 + src/conf/domain_event.c | 1431 ++++++--------------------------- src/conf/domain_event.h | 134 ++- src/conf/object_event.c | 1008 +++++++++++++++++++++++ src/conf/object_event.h | 114 +++ src/conf/object_event_private.h | 167 ++++ src/driver.h | 14 + src/libvirt.c | 133 +++ src/libvirt_private.syms | 18 +- src/libvirt_public.syms | 6 + src/libxl/libxl_conf.h | 2 +- src/libxl/libxl_driver.c | 28 +- src/lxc/lxc_conf.h | 2 +- src/lxc/lxc_driver.c | 38 +- src/lxc/lxc_process.c | 12 +- src/network/bridge_driver.c | 91 ++- src/network/bridge_driver_platform.h | 3 + src/parallels/parallels_utils.h | 2 +- src/qemu/qemu_conf.h | 2 +- src/qemu/qemu_domain.c | 6 +- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_driver.c | 50 +- src/qemu/qemu_hotplug.c | 10 +- src/qemu/qemu_migration.c | 12 +- src/qemu/qemu_process.c | 48 +- src/remote/remote_driver.c | 173 +++- src/remote/remote_protocol.x | 46 +- src/test/test_driver.c | 166 ++-- src/uml/uml_conf.h | 2 +- src/uml/uml_driver.c | 26 +- src/vbox/vbox_tmpl.c | 20 +- src/xen/xen_driver.c | 10 +- src/xen/xen_driver.h | 4 +- src/xen/xen_inotify.c | 8 +- src/xen/xs_internal.c | 4 +- tests/Makefile.am | 7 + tests/objecteventtest.c | 228 ++++++ tests/qemuhotplugtest.c | 2 +- 45 files changed, 2974 insertions(+), 1510 deletions(-) create mode 100644 src/conf/object_event.c create mode 100644 src/conf/object_event.h create mode 100644 src/conf/object_event_private.h create mode 100644 tests/objecteventtest.c -- 1.8.4.2

The idea behind this commit is to make use of the Domain event mechanism for other events like network ones. This introduces some renaming from virDomainEvent* to virOjbectEvent*. --- .gitignore | 1 + include/libvirt/libvirt.h.in | 8 + src/Makefile.am | 6 + src/conf/domain_event.c | 1431 +++++++-------------------------------- src/conf/domain_event.h | 134 ++-- src/conf/object_event.c | 918 +++++++++++++++++++++++++ src/conf/object_event.h | 93 +++ src/conf/object_event_private.h | 160 +++++ src/libvirt_private.syms | 15 +- src/libxl/libxl_conf.h | 2 +- src/libxl/libxl_driver.c | 28 +- src/lxc/lxc_conf.h | 2 +- src/lxc/lxc_driver.c | 38 +- src/lxc/lxc_process.c | 12 +- src/parallels/parallels_utils.h | 2 +- src/qemu/qemu_conf.h | 2 +- src/qemu/qemu_domain.c | 6 +- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_driver.c | 50 +- src/qemu/qemu_hotplug.c | 10 +- src/qemu/qemu_migration.c | 12 +- src/qemu/qemu_process.c | 48 +- src/remote/remote_driver.c | 50 +- src/test/test_driver.c | 50 +- src/uml/uml_conf.h | 2 +- src/uml/uml_driver.c | 26 +- src/vbox/vbox_tmpl.c | 20 +- src/xen/xen_driver.c | 10 +- src/xen/xen_driver.h | 4 +- src/xen/xen_inotify.c | 8 +- src/xen/xs_internal.c | 4 +- tests/qemuhotplugtest.c | 2 +- 32 files changed, 1687 insertions(+), 1469 deletions(-) create mode 100644 src/conf/object_event.c create mode 100644 src/conf/object_event.h create mode 100644 src/conf/object_event_private.h diff --git a/.gitignore b/.gitignore index 6b024e7..05be8a7 100644 --- a/.gitignore +++ b/.gitignore @@ -170,6 +170,7 @@ /tests/networkxml2argvtest /tests/nodeinfotest /tests/nwfilterxml2xmltest +/tests/objecteventtest /tests/object-locking /tests/object-locking-files.txt /tests/object-locking.cm[ix] diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 146a59b..b13118d 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -4959,6 +4959,14 @@ typedef enum { } virDomainEventID; +/** Event IDs are computed in the following way: + virEventNamespaceID << 8 + vir*EventId + */ +typedef enum { + VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */ +} virEventNamespaceID; + + /* Use VIR_DOMAIN_EVENT_CALLBACK() to cast the 'cb' parameter */ int virConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, /* Optional, to filter */ diff --git a/src/Makefile.am b/src/Makefile.am index ad39b74..8507b55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -241,6 +241,10 @@ DOMAIN_CONF_SOURCES = \ conf/domain_nwfilter.c conf/domain_nwfilter.h \ conf/snapshot_conf.c conf/snapshot_conf.h +OBJECT_EVENT_SOURCES = \ + conf/object_event.h conf/object_event.c \ + conf/objec_event_private.h + DOMAIN_EVENT_SOURCES = \ conf/domain_event.c conf/domain_event.h @@ -292,6 +296,7 @@ DEVICE_CONF_SOURCES = \ CONF_SOURCES = \ $(NETDEV_CONF_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ + $(OBJECT_EVENT_SOURCES) \ $(DOMAIN_EVENT_SOURCES) \ $(NETWORK_CONF_SOURCES) \ $(NWFILTER_CONF_SOURCES) \ @@ -2010,6 +2015,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \ util/virutil.c \ util/viruuid.c \ conf/domain_event.c \ + conf/object_event.c \ rpc/virnetsocket.c \ rpc/virnetsocket.h \ rpc/virnetmessage.h \ diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 19e3920..4a6038a 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -23,6 +23,8 @@ #include <config.h> +#include "object_event.h" +#include "object_event_private.h" #include "domain_event.h" #include "virlog.h" #include "datatypes.h" @@ -32,163 +34,93 @@ #define VIR_FROM_THIS VIR_FROM_NONE -struct _virDomainMeta { - int id; - char *name; - unsigned char uuid[VIR_UUID_BUFLEN]; -}; -typedef struct _virDomainMeta virDomainMeta; -typedef virDomainMeta *virDomainMetaPtr; - -struct _virDomainEventCallbackList { - unsigned int nextID; - unsigned int count; - virDomainEventCallbackPtr *callbacks; -}; - -struct _virDomainEventQueue { - unsigned int count; - virDomainEventPtr *events; -}; - -struct _virDomainEventState { - /* The list of domain event callbacks */ - virDomainEventCallbackListPtr callbacks; - /* The queue of domain events */ - virDomainEventQueuePtr queue; - /* Timer for flushing events queue */ - int timer; - /* Flag if we're in process of dispatching */ - bool isDispatching; - virMutex lock; -}; - -struct _virDomainEventCallback { - int callbackID; - int eventID; - virConnectPtr conn; - virDomainMetaPtr dom; - virConnectDomainEventGenericCallback cb; - void *opaque; - virFreeCallback freecb; - int deleted; -}; - -struct _virDomainEvent { - int eventID; - - virDomainMeta dom; - - union { - struct { - int type; - int detail; - } lifecycle; - struct { - long long offset; - } rtcChange; - struct { - int action; - } watchdog; - struct { - char *srcPath; - char *devAlias; - int action; - char *reason; - } ioError; - struct { - int phase; - virDomainEventGraphicsAddressPtr local; - virDomainEventGraphicsAddressPtr remote; - char *authScheme; - virDomainEventGraphicsSubjectPtr subject; - } graphics; - struct { - char *path; - int type; - int status; - } blockJob; - struct { - char *oldSrcPath; - char *newSrcPath; - char *devAlias; - int reason; - } diskChange; - struct { - char *devAlias; - int reason; - } trayChange; - struct { - /* In unit of 1024 bytes */ - unsigned long long actual; - } balloonChange; - struct { - char *devAlias; - } deviceRemoved; - } data; -}; /** - * virDomainEventCallbackListFree: - * @list: event callback list head + * virDomainEventCallbackListAdd: + * @conn: pointer to the connection + * @cbList: the list + * @callback: the callback to add + * @opaque: opaque data tio pass to callback * - * Free the memory in the domain event callback list + * Internal function to add a callback from a virObjectEventCallbackListPtr */ -static void -virDomainEventCallbackListFree(virDomainEventCallbackListPtr list) +static int +virDomainEventCallbackListAdd(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) { - size_t i; - if (!list) - return; - - for (i=0; i<list->count; i++) { - virFreeCallback freecb = list->callbacks[i]->freecb; - if (freecb) - (*freecb)(list->callbacks[i]->opaque); - VIR_FREE(list->callbacks[i]); - } - VIR_FREE(list->callbacks); - VIR_FREE(list); + return virObjectEventCallbackListAddID(conn, cbList, NULL, NULL, 0, + VIR_DOMAIN_EVENT_ID_LIFECYCLE, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, NULL); } /** - * virDomainEventCallbackListRemove: - * @conn: pointer to the connection - * @cbList: the list - * @callback: the callback to remove + * virDomainEventStateRegister: + * @conn: connection to associate with callback + * @state: object event state + * @callback: function to remove from event + * @opaque: data blob to pass to callback + * @freecb: callback to free @opaque * - * Internal function to remove a callback from a virDomainEventCallbackListPtr + * Register the function @callback with connection @conn, + * from @state, for lifecycle events. + * + * Returns: the number of lifecycle callbacks now registered, or -1 on error */ +int +virDomainEventStateRegister(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) +{ + int ret = -1; + + virObjectEventStateLock(state); + + if ((state->callbacks->count == 0) && + (state->timer == -1) && + (state->timer = virEventAddTimeout(-1, + virObjectEventTimer, + state, + NULL)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not initialize domain event timer")); + goto cleanup; + } + + ret = virDomainEventCallbackListAdd(conn, state->callbacks, + callback, opaque, freecb); + + if (ret == -1 && + state->callbacks->count == 0 && + state->timer != -1) { + virEventRemoveTimeout(state->timer); + state->timer = -1; + } + +cleanup: + virObjectEventStateUnlock(state); + return ret; +} + + static int -virDomainEventCallbackListRemove(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback) +virDomainEventCallbackListMarkDelete(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + virConnectDomainEventCallback callback) { int ret = 0; size_t i; for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) && + if (cbList->callbacks[i]->cb == VIR_OBJECT_EVENT_CALLBACK(callback) && cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE && cbList->callbacks[i]->conn == conn) { - virFreeCallback freecb = cbList->callbacks[i]->freecb; - if (freecb) - (*freecb)(cbList->callbacks[i]->opaque); - virObjectUnref(cbList->callbacks[i]->conn); - VIR_FREE(cbList->callbacks[i]); - - if (i < (cbList->count - 1)) - memmove(cbList->callbacks + i, - cbList->callbacks + i + 1, - sizeof(*(cbList->callbacks)) * - (cbList->count - (i + 1))); - - if (VIR_REALLOC_N(cbList->callbacks, - cbList->count - 1) < 0) { - ; /* Failure to reduce memory allocation isn't fatal */ - } - cbList->count--; - + cbList->callbacks[i]->deleted = 1; for (i = 0; i < cbList->count; i++) { if (!cbList->callbacks[i]->deleted) ret++; @@ -198,28 +130,29 @@ virDomainEventCallbackListRemove(virConnectPtr conn, } virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not find event callback for removal")); + _("could not find event callback for deletion")); return -1; } /** - * virDomainEventCallbackListRemoveID: + * virDomainEventCallbackListRemove: * @conn: pointer to the connection * @cbList: the list * @callback: the callback to remove * - * Internal function to remove a callback from a virDomainEventCallbackListPtr + * Internal function to remove a callback from a virObjectEventCallbackListPtr */ static int -virDomainEventCallbackListRemoveID(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - int callbackID) +virDomainEventCallbackListRemove(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + virConnectDomainEventCallback callback) { int ret = 0; size_t i; for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->callbackID == callbackID && + if (cbList->callbacks[i]->cb == VIR_OBJECT_EVENT_CALLBACK(callback) && + cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE && cbList->callbacks[i]->conn == conn) { virFreeCallback freecb = cbList->callbacks[i]->freecb; if (freecb) @@ -253,543 +186,159 @@ virDomainEventCallbackListRemoveID(virConnectPtr conn, } -static int -virDomainEventCallbackListMarkDelete(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback) -{ - int ret = 0; - size_t i; - for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) && - cbList->callbacks[i]->eventID == VIR_DOMAIN_EVENT_ID_LIFECYCLE && - cbList->callbacks[i]->conn == conn) { - cbList->callbacks[i]->deleted = 1; - for (i = 0; i < cbList->count; i++) { - if (!cbList->callbacks[i]->deleted) - ret++; - } - return ret; - } - } - - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not find event callback for deletion")); - return -1; -} - - -static int -virDomainEventCallbackListMarkDeleteID(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - int callbackID) -{ - int ret = 0; - size_t i; - for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->callbackID == callbackID && - cbList->callbacks[i]->conn == conn) { - cbList->callbacks[i]->deleted = 1; - for (i = 0; i < cbList->count; i++) { - if (!cbList->callbacks[i]->deleted) - ret++; - } - return ret; - } - } - - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not find event callback for deletion")); - return -1; -} - - -static int -virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList) -{ - int old_count = cbList->count; - int n; - for (n = 0; n < cbList->count; n++) { - if (cbList->callbacks[n]->deleted) { - virFreeCallback freecb = cbList->callbacks[n]->freecb; - if (freecb) - (*freecb)(cbList->callbacks[n]->opaque); - virObjectUnref(cbList->callbacks[n]->conn); - VIR_FREE(cbList->callbacks[n]); - - if (n < (cbList->count - 1)) - memmove(cbList->callbacks + n, - cbList->callbacks + n + 1, - sizeof(*(cbList->callbacks)) * - (cbList->count - (n + 1))); - cbList->count--; - n--; - } - } - if (cbList->count < old_count && - VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) { - ; /* Failure to reduce memory allocation isn't fatal */ - } - return 0; -} - - -/** - * virDomainEventCallbackListAddID: - * @conn: pointer to the connection - * @cbList: the list - * @eventID: the event ID - * @callback: the callback to add - * @opaque: opaque data tio pass to callback - * @callbackID: filled with callback ID - * - * Internal function to add a callback from a virDomainEventCallbackListPtr - */ -static int -virDomainEventCallbackListAddID(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virDomainPtr dom, - int eventID, - virConnectDomainEventGenericCallback callback, - void *opaque, - virFreeCallback freecb, - int *callbackID) -{ - virDomainEventCallbackPtr event; - size_t i; - int ret = 0; - - /* Check incoming */ - if (!cbList) { - return -1; - } - - /* check if we already have this callback on our list */ - for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) && - cbList->callbacks[i]->eventID == eventID && - cbList->callbacks[i]->conn == conn && - ((dom && cbList->callbacks[i]->dom && - memcmp(cbList->callbacks[i]->dom->uuid, - dom->uuid, VIR_UUID_BUFLEN) == 0) || - (!dom && !cbList->callbacks[i]->dom))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("event callback already tracked")); - return -1; - } - } - /* Allocate new event */ - if (VIR_ALLOC(event) < 0) - goto error; - event->conn = conn; - event->cb = callback; - event->eventID = eventID; - event->opaque = opaque; - event->freecb = freecb; - - if (dom) { - if (VIR_ALLOC(event->dom) < 0) - goto error; - if (VIR_STRDUP(event->dom->name, dom->name) < 0) - goto error; - memcpy(event->dom->uuid, dom->uuid, VIR_UUID_BUFLEN); - event->dom->id = dom->id; - } - - /* Make space on list */ - if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0) - goto error; - - virObjectRef(event->conn); - - cbList->callbacks[cbList->count] = event; - cbList->count++; - - event->callbackID = cbList->nextID++; - - for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->eventID == eventID && - cbList->callbacks[i]->conn == conn && - !cbList->callbacks[i]->deleted) - ret++; - } - - if (callbackID) - *callbackID = event->callbackID; - - return ret; - -error: - if (event) { - if (event->dom) - VIR_FREE(event->dom->name); - VIR_FREE(event->dom); - } - VIR_FREE(event); - return -1; -} - - /** - * virDomainEventCallbackListAdd: - * @conn: pointer to the connection - * @cbList: the list - * @callback: the callback to add - * @opaque: opaque data tio pass to callback - * - * Internal function to add a callback from a virDomainEventCallbackListPtr - */ -static int -virDomainEventCallbackListAdd(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) -{ - return virDomainEventCallbackListAddID(conn, cbList, NULL, - VIR_DOMAIN_EVENT_ID_LIFECYCLE, - VIR_DOMAIN_EVENT_CALLBACK(callback), - opaque, freecb, NULL); -} - - - -static int -virDomainEventCallbackListEventID(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - int callbackID) -{ - size_t i; - - for (i = 0; i < cbList->count; i++) { - if (cbList->callbacks[i]->deleted) - continue; - - if (cbList->callbacks[i]->callbackID == callbackID && - cbList->callbacks[i]->conn == conn) - return cbList->callbacks[i]->eventID; - } - - return -1; -} - - -void virDomainEventFree(virDomainEventPtr event) -{ - if (!event) - return; - - switch (event->eventID) { - case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: - case VIR_DOMAIN_EVENT_ID_IO_ERROR: - VIR_FREE(event->data.ioError.srcPath); - VIR_FREE(event->data.ioError.devAlias); - VIR_FREE(event->data.ioError.reason); - break; - - case VIR_DOMAIN_EVENT_ID_GRAPHICS: - if (event->data.graphics.local) { - VIR_FREE(event->data.graphics.local->node); - VIR_FREE(event->data.graphics.local->service); - VIR_FREE(event->data.graphics.local); - } - if (event->data.graphics.remote) { - VIR_FREE(event->data.graphics.remote->node); - VIR_FREE(event->data.graphics.remote->service); - VIR_FREE(event->data.graphics.remote); - } - VIR_FREE(event->data.graphics.authScheme); - if (event->data.graphics.subject) { - size_t i; - for (i = 0; i < event->data.graphics.subject->nidentity; i++) { - VIR_FREE(event->data.graphics.subject->identities[i].type); - VIR_FREE(event->data.graphics.subject->identities[i].name); - } - VIR_FREE(event->data.graphics.subject); - } - break; - - case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: - VIR_FREE(event->data.blockJob.path); - break; - - case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: - VIR_FREE(event->data.diskChange.oldSrcPath); - VIR_FREE(event->data.diskChange.newSrcPath); - VIR_FREE(event->data.diskChange.devAlias); - break; - case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: - VIR_FREE(event->data.trayChange.devAlias); - break; - case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: - VIR_FREE(event->data.deviceRemoved.devAlias); - break; - } - - VIR_FREE(event->dom.name); - VIR_FREE(event); -} - -/** - * virDomainEventQueueClear: - * @queue: pointer to the queue - * - * Removes all elements from the queue - */ -static void -virDomainEventQueueClear(virDomainEventQueuePtr queue) -{ - size_t i; - if (!queue) - return; - - for (i = 0; i < queue->count; i++) { - virDomainEventFree(queue->events[i]); - } - VIR_FREE(queue->events); - queue->count = 0; -} - -/** - * virDomainEventQueueFree: - * @queue: pointer to the queue - * - * Free the memory in the queue. We process this like a list here - */ -static void -virDomainEventQueueFree(virDomainEventQueuePtr queue) -{ - if (!queue) - return; - - virDomainEventQueueClear(queue); - VIR_FREE(queue); -} - -static virDomainEventQueuePtr -virDomainEventQueueNew(void) -{ - virDomainEventQueuePtr ret; - - ignore_value(VIR_ALLOC(ret)); - return ret; -} - -static void -virDomainEventStateLock(virDomainEventStatePtr state) -{ - virMutexLock(&state->lock); -} - -static void -virDomainEventStateUnlock(virDomainEventStatePtr state) -{ - virMutexUnlock(&state->lock); -} - -/** - * virDomainEventStateFree: - * @list: virDomainEventStatePtr to free - * - * Free a virDomainEventStatePtr and its members, and unregister the timer. - */ -void -virDomainEventStateFree(virDomainEventStatePtr state) -{ - if (!state) - return; - - virDomainEventCallbackListFree(state->callbacks); - virDomainEventQueueFree(state->queue); - - if (state->timer != -1) - virEventRemoveTimeout(state->timer); - - virMutexDestroy(&state->lock); - VIR_FREE(state); -} - - -static void virDomainEventStateFlush(virDomainEventStatePtr state); - -static void -virDomainEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque) -{ - virDomainEventStatePtr state = opaque; - - virDomainEventStateFlush(state); -} - -/** - * virDomainEventStateNew: - */ -virDomainEventStatePtr -virDomainEventStateNew(void) -{ - virDomainEventStatePtr state = NULL; - - if (VIR_ALLOC(state) < 0) - goto error; - - if (virMutexInit(&state->lock) < 0) { - virReportSystemError(errno, "%s", - _("unable to initialize state mutex")); - VIR_FREE(state); - goto error; - } - - if (VIR_ALLOC(state->callbacks) < 0) - goto error; - - if (!(state->queue = virDomainEventQueueNew())) - goto error; - - state->timer = -1; - - return state; - -error: - virDomainEventStateFree(state); - return NULL; -} - -static virDomainEventPtr virDomainEventNewInternal(int eventID, - int id, - const char *name, - const unsigned char *uuid) + * virDomainEventStateDeregister: + * @conn: connection to associate with callback + * @state: object event state + * @callback: function to remove from event + * + * Unregister the function @callback with connection @conn, + * from @state, for lifecycle events. + * + * Returns: the number of lifecycle callbacks still registered, or -1 on error + */ +int +virDomainEventStateDeregister(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback) { - virDomainEventPtr event; + int ret; - if (VIR_ALLOC(event) < 0) - return NULL; + virObjectEventStateLock(state); + if (state->isDispatching) + ret = virDomainEventCallbackListMarkDelete(conn, + state->callbacks, callback); + else + ret = virDomainEventCallbackListRemove(conn, state->callbacks, callback); - event->eventID = eventID; - if (VIR_STRDUP(event->dom.name, name) < 0) { - VIR_FREE(event); - return NULL; + if (state->callbacks->count == 0 && + state->timer != -1) { + virEventRemoveTimeout(state->timer); + state->timer = -1; + virObjectEventQueueClear(state->queue); } - event->dom.id = id; - memcpy(event->dom.uuid, uuid, VIR_UUID_BUFLEN); - return event; + virObjectEventStateUnlock(state); + return ret; } -virDomainEventPtr virDomainEventNew(int id, const char *name, + +virObjectEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail) { - virDomainEventPtr event = virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_LIFECYCLE, + virObjectEventPtr event = virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_LIFECYCLE, id, name, uuid); if (event) { - event->data.lifecycle.type = type; - event->data.lifecycle.detail = detail; + event->data.domainData.lifecycle.type = type; + event->data.domainData.lifecycle.detail = detail; } return event; } -virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail) +virObjectEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail) { return virDomainEventNew(dom->id, dom->name, dom->uuid, type, detail); } -virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail) +virObjectEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail) { return virDomainEventNewFromDef(obj->def, type, detail); } -virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail) +virObjectEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail) { return virDomainEventNew(def->id, def->name, def->uuid, type, detail); } -virDomainEventPtr virDomainEventRebootNew(int id, const char *name, +virObjectEventPtr virDomainEventRebootNew(int id, const char *name, const unsigned char *uuid) { - return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, + return virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, id, name, uuid); } -virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom) +virObjectEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom) { - return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, + return virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, dom->id, dom->name, dom->uuid); } -virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj) +virObjectEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj) { - return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, + return virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, obj->def->id, obj->def->name, obj->def->uuid); } -virDomainEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, long long offset) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, dom->id, dom->name, dom->uuid); if (ev) - ev->data.rtcChange.offset = offset; + ev->data.domainData.rtcChange.offset = offset; return ev; } -virDomainEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, long long offset) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_RTC_CHANGE, obj->def->id, obj->def->name, obj->def->uuid); if (ev) - ev->data.rtcChange.offset = offset; + ev->data.domainData.rtcChange.offset = offset; return ev; } -virDomainEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG, dom->id, dom->name, dom->uuid); if (ev) - ev->data.watchdog.action = action; + ev->data.domainData.watchdog.action = action; return ev; } -virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_WATCHDOG, obj->def->id, obj->def->name, obj->def->uuid); if (ev) - ev->data.watchdog.action = action; + ev->data.domainData.watchdog.action = action; return ev; } -static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event, +static virObjectEventPtr virDomainEventIOErrorNewFromDomImpl(int event, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, const char *reason) { - virDomainEventPtr ev = - virDomainEventNewInternal(event, + virObjectEventPtr ev = + virObjectEventNewInternal(event, dom->id, dom->name, dom->uuid); if (ev) { - ev->data.ioError.action = action; - if (VIR_STRDUP(ev->data.ioError.srcPath, srcPath) < 0 || - VIR_STRDUP(ev->data.ioError.devAlias, devAlias) < 0 || - VIR_STRDUP(ev->data.ioError.reason, reason) < 0) { - virDomainEventFree(ev); + ev->data.domainData.ioError.action = action; + if (VIR_STRDUP(ev->data.domainData.ioError.srcPath, srcPath) < 0 || + VIR_STRDUP(ev->data.domainData.ioError.devAlias, devAlias) < 0 || + VIR_STRDUP(ev->data.domainData.ioError.reason, reason) < 0) { + virObjectEventFree(ev); ev = NULL; } } @@ -797,23 +346,23 @@ static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event, return ev; } -static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event, +static virObjectEventPtr virDomainEventIOErrorNewFromObjImpl(int event, virDomainObjPtr obj, const char *srcPath, const char *devAlias, int action, const char *reason) { - virDomainEventPtr ev = - virDomainEventNewInternal(event, + virObjectEventPtr ev = + virObjectEventNewInternal(event, obj->def->id, obj->def->name, obj->def->uuid); if (ev) { - ev->data.ioError.action = action; - if (VIR_STRDUP(ev->data.ioError.srcPath, srcPath) < 0 || - VIR_STRDUP(ev->data.ioError.devAlias, devAlias) < 0 || - VIR_STRDUP(ev->data.ioError.reason, reason) < 0) { - virDomainEventFree(ev); + ev->data.domainData.ioError.action = action; + if (VIR_STRDUP(ev->data.domainData.ioError.srcPath, srcPath) < 0 || + VIR_STRDUP(ev->data.domainData.ioError.devAlias, devAlias) < 0 || + VIR_STRDUP(ev->data.domainData.ioError.reason, reason) < 0) { + virObjectEventFree(ev); ev = NULL; } } @@ -821,7 +370,7 @@ static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event, return ev; } -virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, const char *srcPath, const char *devAlias, int action) @@ -831,7 +380,7 @@ virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, action, NULL); } -virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, const char *srcPath, const char *devAlias, int action) @@ -841,7 +390,7 @@ virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, action, NULL); } -virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, const char *srcPath, const char *devAlias, int action, @@ -852,7 +401,7 @@ virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, action, reason); } -virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, const char *srcPath, const char *devAlias, int action, @@ -864,77 +413,77 @@ virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, } -virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS, dom->id, dom->name, dom->uuid); if (ev) { - ev->data.graphics.phase = phase; - if (VIR_STRDUP(ev->data.graphics.authScheme, authScheme) < 0) { - virDomainEventFree(ev); + ev->data.domainData.graphics.phase = phase; + if (VIR_STRDUP(ev->data.domainData.graphics.authScheme, authScheme) < 0) { + virObjectEventFree(ev); return NULL; } - ev->data.graphics.local = local; - ev->data.graphics.remote = remote; - ev->data.graphics.subject = subject; + ev->data.domainData.graphics.local = local; + ev->data.domainData.graphics.remote = remote; + ev->data.domainData.graphics.subject = subject; } return ev; } -virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS, obj->def->id, obj->def->name, obj->def->uuid); if (ev) { - ev->data.graphics.phase = phase; - if (VIR_STRDUP(ev->data.graphics.authScheme, authScheme) < 0) { - virDomainEventFree(ev); + ev->data.domainData.graphics.phase = phase; + if (VIR_STRDUP(ev->data.domainData.graphics.authScheme, authScheme) < 0) { + virObjectEventFree(ev); return NULL; } - ev->data.graphics.local = local; - ev->data.graphics.remote = remote; - ev->data.graphics.subject = subject; + ev->data.domainData.graphics.local = local; + ev->data.domainData.graphics.remote = remote; + ev->data.domainData.graphics.subject = subject; } return ev; } -static virDomainEventPtr +static virObjectEventPtr virDomainEventBlockJobNew(int id, const char *name, unsigned char *uuid, const char *path, int type, int status) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BLOCK_JOB, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_BLOCK_JOB, id, name, uuid); if (ev) { - if (VIR_STRDUP(ev->data.blockJob.path, path) < 0) { - virDomainEventFree(ev); + if (VIR_STRDUP(ev->data.domainData.blockJob.path, path) < 0) { + virObjectEventFree(ev); return NULL; } - ev->data.blockJob.type = type; - ev->data.blockJob.status = status; + ev->data.domainData.blockJob.type = type; + ev->data.domainData.blockJob.status = status; } return ev; } -virDomainEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, const char *path, int type, int status) @@ -943,7 +492,7 @@ virDomainEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, obj->def->uuid, path, type, status); } -virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, const char *path, int type, int status) @@ -952,55 +501,55 @@ virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, path, type, status); } -virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) +virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, dom->id, dom->name, dom->uuid); return ev; } -virDomainEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj) +virObjectEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, obj->def->id, obj->def->name, obj->def->uuid); return ev; } -static virDomainEventPtr +static virObjectEventPtr virDomainEventDiskChangeNew(int id, const char *name, unsigned char *uuid, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, int reason) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DISK_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_DISK_CHANGE, id, name, uuid); if (ev) { - if (VIR_STRDUP(ev->data.diskChange.devAlias, devAlias) < 0) + if (VIR_STRDUP(ev->data.domainData.diskChange.devAlias, devAlias) < 0) goto error; - if (VIR_STRDUP(ev->data.diskChange.oldSrcPath, oldSrcPath) < 0) + if (VIR_STRDUP(ev->data.domainData.diskChange.oldSrcPath, oldSrcPath) < 0) goto error; - if (VIR_STRDUP(ev->data.diskChange.newSrcPath, newSrcPath) < 0) + if (VIR_STRDUP(ev->data.domainData.diskChange.newSrcPath, newSrcPath) < 0) goto error; - ev->data.diskChange.reason = reason; + ev->data.domainData.diskChange.reason = reason; } return ev; error: - virDomainEventFree(ev); + virObjectEventFree(ev); return NULL; } -virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, @@ -1011,7 +560,7 @@ virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, newSrcPath, devAlias, reason); } -virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, @@ -1022,31 +571,31 @@ virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, devAlias, reason); } -static virDomainEventPtr +static virObjectEventPtr virDomainEventTrayChangeNew(int id, const char *name, unsigned char *uuid, const char *devAlias, int reason) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, id, name, uuid); if (ev) { - if (VIR_STRDUP(ev->data.trayChange.devAlias, devAlias) < 0) + if (VIR_STRDUP(ev->data.domainData.trayChange.devAlias, devAlias) < 0) goto error; - ev->data.trayChange.reason = reason; + ev->data.domainData.trayChange.reason = reason; } return ev; error: - virDomainEventFree(ev); + virObjectEventFree(ev); return NULL; } -virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, const char *devAlias, int reason) { @@ -1057,7 +606,7 @@ virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, reason); } -virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, const char *devAlias, int reason) { @@ -1065,18 +614,18 @@ virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, devAlias, reason); } -static virDomainEventPtr +static virObjectEventPtr virDomainEventPMWakeupNew(int id, const char *name, unsigned char *uuid) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_PMWAKEUP, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_PMWAKEUP, id, name, uuid); return ev; } -virDomainEventPtr +virObjectEventPtr virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj) { return virDomainEventPMWakeupNew(obj->def->id, @@ -1084,24 +633,24 @@ virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj) obj->def->uuid); } -virDomainEventPtr +virObjectEventPtr virDomainEventPMWakeupNewFromDom(virDomainPtr dom) { return virDomainEventPMWakeupNew(dom->id, dom->name, dom->uuid); } -static virDomainEventPtr +static virObjectEventPtr virDomainEventPMSuspendNew(int id, const char *name, unsigned char *uuid) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_PMSUSPEND, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_PMSUSPEND, id, name, uuid); return ev; } -virDomainEventPtr +virObjectEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj) { return virDomainEventPMSuspendNew(obj->def->id, @@ -1109,23 +658,23 @@ virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj) obj->def->uuid); } -virDomainEventPtr +virObjectEventPtr virDomainEventPMSuspendNewFromDom(virDomainPtr dom) { return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid); } -static virDomainEventPtr +static virObjectEventPtr virDomainEventPMSuspendDiskNew(int id, const char *name, unsigned char *uuid) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, id, name, uuid); return ev; } -virDomainEventPtr +virObjectEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj) { return virDomainEventPMSuspendDiskNew(obj->def->id, @@ -1133,60 +682,60 @@ virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj) obj->def->uuid); } -virDomainEventPtr +virObjectEventPtr virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom) { return virDomainEventPMSuspendDiskNew(dom->id, dom->name, dom->uuid); } -virDomainEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, unsigned long long actual) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, dom->id, dom->name, dom->uuid); if (ev) - ev->data.balloonChange.actual = actual; + ev->data.domainData.balloonChange.actual = actual; return ev; } -virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, unsigned long long actual) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, obj->def->id, obj->def->name, obj->def->uuid); if (ev) - ev->data.balloonChange.actual = actual; + ev->data.domainData.balloonChange.actual = actual; return ev; } -static virDomainEventPtr +static virObjectEventPtr virDomainEventDeviceRemovedNew(int id, const char *name, unsigned char *uuid, const char *devAlias) { - virDomainEventPtr ev = - virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, + virObjectEventPtr ev = + virObjectEventNewInternal(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, id, name, uuid); if (ev) { - if (VIR_STRDUP(ev->data.deviceRemoved.devAlias, devAlias) < 0) + if (VIR_STRDUP(ev->data.domainData.deviceRemoved.devAlias, devAlias) < 0) goto error; } return ev; error: - virDomainEventFree(ev); + virObjectEventFree(ev); return NULL; } -virDomainEventPtr +virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, const char *devAlias) { @@ -1194,7 +743,7 @@ virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, obj->def->uuid, devAlias); } -virDomainEventPtr +virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, const char *devAlias) { @@ -1202,373 +751,11 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, devAlias); } -/** - * virDomainEventQueuePush: - * @evtQueue: the dom event queue - * @event: the event to add - * - * Internal function to push to the back of a virDomainEventQueue - * - * Returns: 0 on success, -1 on failure - */ -static int -virDomainEventQueuePush(virDomainEventQueuePtr evtQueue, - virDomainEventPtr event) -{ - if (!evtQueue) { - return -1; - } - - /* Make space on queue */ - if (VIR_REALLOC_N(evtQueue->events, - evtQueue->count + 1) < 0) - return -1; - - evtQueue->events[evtQueue->count] = event; - evtQueue->count++; - return 0; -} - - -typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn, - virDomainEventPtr event, - virConnectDomainEventGenericCallback cb, - void *cbopaque, - void *opaque); - - -static void -virDomainEventDispatchDefaultFunc(virConnectPtr conn, - virDomainEventPtr event, - virConnectDomainEventGenericCallback cb, - void *cbopaque, - void *opaque ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = virGetDomain(conn, event->dom.name, event->dom.uuid); - if (!dom) - return; - dom->id = event->dom.id; - - switch ((virDomainEventID) event->eventID) { - case VIR_DOMAIN_EVENT_ID_LIFECYCLE: - ((virConnectDomainEventCallback)cb)(conn, dom, - event->data.lifecycle.type, - event->data.lifecycle.detail, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_REBOOT: - (cb)(conn, dom, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_RTC_CHANGE: - ((virConnectDomainEventRTCChangeCallback)cb)(conn, dom, - event->data.rtcChange.offset, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_WATCHDOG: - ((virConnectDomainEventWatchdogCallback)cb)(conn, dom, - event->data.watchdog.action, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_IO_ERROR: - ((virConnectDomainEventIOErrorCallback)cb)(conn, dom, - event->data.ioError.srcPath, - event->data.ioError.devAlias, - event->data.ioError.action, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: - ((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom, - event->data.ioError.srcPath, - event->data.ioError.devAlias, - event->data.ioError.action, - event->data.ioError.reason, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_GRAPHICS: - ((virConnectDomainEventGraphicsCallback)cb)(conn, dom, - event->data.graphics.phase, - event->data.graphics.local, - event->data.graphics.remote, - event->data.graphics.authScheme, - event->data.graphics.subject, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR: - (cb)(conn, dom, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: - ((virConnectDomainEventBlockJobCallback)cb)(conn, dom, - event->data.blockJob.path, - event->data.blockJob.type, - event->data.blockJob.status, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: - ((virConnectDomainEventDiskChangeCallback)cb)(conn, dom, - event->data.diskChange.oldSrcPath, - event->data.diskChange.newSrcPath, - event->data.diskChange.devAlias, - event->data.diskChange.reason, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: - ((virConnectDomainEventTrayChangeCallback)cb)(conn, dom, - event->data.trayChange.devAlias, - event->data.trayChange.reason, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_PMWAKEUP: - ((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_PMSUSPEND: - ((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE: - ((virConnectDomainEventBalloonChangeCallback)cb)(conn, dom, - event->data.balloonChange.actual, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: - ((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom, 0, cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: - ((virConnectDomainEventDeviceRemovedCallback)cb)(conn, dom, - event->data.deviceRemoved.devAlias, - cbopaque); - goto cleanup; - - case VIR_DOMAIN_EVENT_ID_LAST: - break; - } - - VIR_WARN("Unexpected event ID %d", event->eventID); - -cleanup: - virDomainFree(dom); -} - - -static int virDomainEventDispatchMatchCallback(virDomainEventPtr event, - virDomainEventCallbackPtr cb) -{ - if (!cb) - return 0; - if (cb->deleted) - return 0; - if (cb->eventID != event->eventID) - return 0; - - if (cb->dom) { - /* Deliberately ignoring 'id' for matching, since that - * will cause problems when a domain switches between - * running & shutoff states & ignoring 'name' since - * Xen sometimes renames guests during migration, thus - * leaving 'uuid' as the only truly reliable ID we can use*/ - - if (memcmp(event->dom.uuid, cb->dom->uuid, VIR_UUID_BUFLEN) == 0) - return 1; - - return 0; - } else { - return 1; - } -} - - -static void -virDomainEventDispatch(virDomainEventPtr event, - virDomainEventCallbackListPtr callbacks, - virDomainEventDispatchFunc dispatch, - void *opaque) -{ - size_t i; - /* Cache this now, since we may be dropping the lock, - and have more callbacks added. We're guaranteed not - to have any removed */ - int cbCount = callbacks->count; - - for (i = 0; i < cbCount; i++) { - if (!virDomainEventDispatchMatchCallback(event, callbacks->callbacks[i])) - continue; - - (*dispatch)(callbacks->callbacks[i]->conn, - event, - callbacks->callbacks[i]->cb, - callbacks->callbacks[i]->opaque, - opaque); - } -} - - -static void -virDomainEventQueueDispatch(virDomainEventQueuePtr queue, - virDomainEventCallbackListPtr callbacks, - virDomainEventDispatchFunc dispatch, - void *opaque) -{ - size_t i; - - for (i = 0; i < queue->count; i++) { - virDomainEventDispatch(queue->events[i], callbacks, dispatch, opaque); - virDomainEventFree(queue->events[i]); - } - VIR_FREE(queue->events); - queue->count = 0; -} - -void -virDomainEventStateQueue(virDomainEventStatePtr state, - virDomainEventPtr event) -{ - if (state->timer < 0) { - virDomainEventFree(event); - return; - } - - virDomainEventStateLock(state); - - if (virDomainEventQueuePush(state->queue, event) < 0) { - VIR_DEBUG("Error adding event to queue"); - virDomainEventFree(event); - } - - if (state->queue->count == 1) - virEventUpdateTimeout(state->timer, 0); - virDomainEventStateUnlock(state); -} - - -static void -virDomainEventStateDispatchFunc(virConnectPtr conn, - virDomainEventPtr event, - virConnectDomainEventGenericCallback cb, - void *cbopaque, - void *opaque) -{ - virDomainEventStatePtr state = opaque; - - /* Drop the lock whle dispatching, for sake of re-entrancy */ - virDomainEventStateUnlock(state); - virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); - virDomainEventStateLock(state); -} - - -static void -virDomainEventStateFlush(virDomainEventStatePtr state) -{ - virDomainEventQueue tempQueue; - - virDomainEventStateLock(state); - state->isDispatching = true; - - /* Copy the queue, so we're reentrant safe when dispatchFunc drops the - * driver lock */ - tempQueue.count = state->queue->count; - tempQueue.events = state->queue->events; - state->queue->count = 0; - state->queue->events = NULL; - virEventUpdateTimeout(state->timer, -1); - - virDomainEventQueueDispatch(&tempQueue, - state->callbacks, - virDomainEventStateDispatchFunc, - state); - - /* Purge any deleted callbacks */ - virDomainEventCallbackListPurgeMarked(state->callbacks); - - state->isDispatching = false; - virDomainEventStateUnlock(state); -} - - -/** - * virDomainEventStateRegister: - * @conn: connection to associate with callback - * @state: domain event state - * @callback: function to remove from event - * @opaque: data blob to pass to callback - * @freecb: callback to free @opaque - * - * Register the function @callback with connection @conn, - * from @state, for lifecycle events. - * - * Returns: the number of lifecycle callbacks now registered, or -1 on error - */ -int -virDomainEventStateRegister(virConnectPtr conn, - virDomainEventStatePtr state, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) -{ - int ret = -1; - - virDomainEventStateLock(state); - - if ((state->callbacks->count == 0) && - (state->timer == -1) && - (state->timer = virEventAddTimeout(-1, - virDomainEventTimer, - state, - NULL)) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not initialize domain event timer")); - goto cleanup; - } - - ret = virDomainEventCallbackListAdd(conn, state->callbacks, - callback, opaque, freecb); - - if (ret == -1 && - state->callbacks->count == 0 && - state->timer != -1) { - virEventRemoveTimeout(state->timer); - state->timer = -1; - } - -cleanup: - virDomainEventStateUnlock(state); - return ret; -} - -/** - * virDomainEventStateRegisterID: - * @conn: connection to associate with callback - * @state: domain event state - * @eventID: ID of the event type to register for - * @cb: function to remove from event - * @opaque: data blob to pass to callback - * @freecb: callback to free @opaque - * @callbackID: filled with callback ID - * - * Register the function @callbackID with connection @conn, - * from @state, for events of type @eventID. - * - * Returns: the number of callbacks now registered, or -1 on error - */ +/* Kept for compatibility reasons */ int virDomainEventStateRegisterID(virConnectPtr conn, - virDomainEventStatePtr state, + virObjectEventStatePtr state, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback cb, @@ -1576,134 +763,14 @@ virDomainEventStateRegisterID(virConnectPtr conn, virFreeCallback freecb, int *callbackID) { - int ret = -1; - - virDomainEventStateLock(state); - - if ((state->callbacks->count == 0) && - (state->timer == -1) && - (state->timer = virEventAddTimeout(-1, - virDomainEventTimer, - state, - NULL)) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not initialize domain event timer")); - goto cleanup; - } - - ret = virDomainEventCallbackListAddID(conn, state->callbacks, - dom, eventID, cb, opaque, freecb, - callbackID); - - if (ret == -1 && - state->callbacks->count == 0 && - state->timer != -1) { - virEventRemoveTimeout(state->timer); - state->timer = -1; - } - -cleanup: - virDomainEventStateUnlock(state); - return ret; -} - - -/** - * virDomainEventStateDeregister: - * @conn: connection to associate with callback - * @state: domain event state - * @callback: function to remove from event - * - * Unregister the function @callback with connection @conn, - * from @state, for lifecycle events. - * - * Returns: the number of lifecycle callbacks still registered, or -1 on error - */ -int -virDomainEventStateDeregister(virConnectPtr conn, - virDomainEventStatePtr state, - virConnectDomainEventCallback callback) -{ - int ret; - - virDomainEventStateLock(state); - if (state->isDispatching) - ret = virDomainEventCallbackListMarkDelete(conn, - state->callbacks, callback); - else - ret = virDomainEventCallbackListRemove(conn, state->callbacks, callback); - - if (state->callbacks->count == 0 && - state->timer != -1) { - virEventRemoveTimeout(state->timer); - state->timer = -1; - virDomainEventQueueClear(state->queue); - } - - virDomainEventStateUnlock(state); - return ret; -} - - -/** - * virDomainEventStateDeregisterID: - * @conn: connection to associate with callback - * @state: domain event state - * @callbackID: ID of the function to remove from event - * - * Unregister the function @callbackID with connection @conn, - * from @state, for events. - * - * Returns: the number of callbacks still registered, or -1 on error - */ -int -virDomainEventStateDeregisterID(virConnectPtr conn, - virDomainEventStatePtr state, - int callbackID) -{ - int ret; - - virDomainEventStateLock(state); - if (state->isDispatching) - ret = virDomainEventCallbackListMarkDeleteID(conn, - state->callbacks, callbackID); + if (dom) + return virObjectEventStateRegisterID(conn, state, dom->uuid, dom->name, + dom->id, eventID, + VIR_OBJECT_EVENT_CALLBACK(cb), + opaque, freecb, callbackID); else - ret = virDomainEventCallbackListRemoveID(conn, - state->callbacks, callbackID); - - if (state->callbacks->count == 0 && - state->timer != -1) { - virEventRemoveTimeout(state->timer); - state->timer = -1; - virDomainEventQueueClear(state->queue); - } - - virDomainEventStateUnlock(state); - return ret; -} - - -/** - * virDomainEventStateEventID: - * @conn: connection associated with the callback - * @state: domain event state - * @callbackID: the callback to query - * - * Query what event ID type is associated with the - * callback @callbackID for connection @conn - * - * Returns 0 on success, -1 on error - */ -int -virDomainEventStateEventID(virConnectPtr conn, - virDomainEventStatePtr state, - int callbackID) -{ - int ret; - - virDomainEventStateLock(state); - ret = virDomainEventCallbackListEventID(conn, - state->callbacks, callbackID); - virDomainEventStateUnlock(state); - return ret; + return virObjectEventStateRegisterID(conn, state, NULL, NULL, 0, + eventID, + VIR_OBJECT_EVENT_CALLBACK(cb), + opaque, freecb, callbackID); } diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index f6b957d..c8928c7 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -26,135 +26,112 @@ #ifndef __DOMAIN_EVENT_H__ # define __DOMAIN_EVENT_H__ +# include "object_event.h" # include "domain_conf.h" -typedef struct _virDomainEventCallback virDomainEventCallback; -typedef virDomainEventCallback *virDomainEventCallbackPtr; - -typedef struct _virDomainEventCallbackList virDomainEventCallbackList; -typedef virDomainEventCallbackList *virDomainEventCallbackListPtr; - -/** - * Dispatching domain events that come in while - * in a call / response rpc - */ -typedef struct _virDomainEvent virDomainEvent; -typedef virDomainEvent *virDomainEventPtr; - -typedef struct _virDomainEventQueue virDomainEventQueue; -typedef virDomainEventQueue *virDomainEventQueuePtr; - -typedef struct _virDomainEventState virDomainEventState; -typedef virDomainEventState *virDomainEventStatePtr; +int virDomainEventStateRegister(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +virDomainEventStateDeregister(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); -virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail); -virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail); -virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); -virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail); +virObjectEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail); +virObjectEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail); +virObjectEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); +virObjectEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail); -virDomainEventPtr virDomainEventRebootNew(int id, const char *name, const unsigned char *uuid); -virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom); -virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj); +virObjectEventPtr virDomainEventRebootNew(int id, const char *name, const unsigned char *uuid); +virObjectEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom); +virObjectEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj); -virDomainEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, long long offset); -virDomainEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, long long offset); +virObjectEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, long long offset); +virObjectEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, long long offset); -virDomainEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action); -virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action); +virObjectEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action); +virObjectEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action); -virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, const char *srcPath, const char *devAlias, int action); -virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, const char *srcPath, const char *devAlias, int action); -virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, const char *srcPath, const char *devAlias, int action, const char *reason); -virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, const char *srcPath, const char *devAlias, int action, const char *reason); -virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject); -virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject); -virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom); -virDomainEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj); +virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom); +virObjectEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj); -virDomainEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, const char *path, int type, int status); -virDomainEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, const char *path, int type, int status); -virDomainEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, int reason); -virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, int reason); -virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, const char *devAlias, int reason); -virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, const char *devAlias, int reason); -virDomainEventPtr virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj); -virDomainEventPtr virDomainEventPMWakeupNewFromDom(virDomainPtr dom); -virDomainEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj); -virDomainEventPtr virDomainEventPMSuspendNewFromDom(virDomainPtr dom); +virObjectEventPtr virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj); +virObjectEventPtr virDomainEventPMWakeupNewFromDom(virDomainPtr dom); +virObjectEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj); +virObjectEventPtr virDomainEventPMSuspendNewFromDom(virDomainPtr dom); -virDomainEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, unsigned long long actual); -virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, unsigned long long actual); +virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, unsigned long long actual); +virObjectEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, unsigned long long actual); -virDomainEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); -virDomainEventPtr virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); +virObjectEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); +virObjectEventPtr virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); -virDomainEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, +virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, const char *devAlias); -virDomainEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, +virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, const char *devAlias); - -void virDomainEventFree(virDomainEventPtr event); - -void virDomainEventStateFree(virDomainEventStatePtr state); -virDomainEventStatePtr -virDomainEventStateNew(void); - -void -virDomainEventStateQueue(virDomainEventStatePtr state, - virDomainEventPtr event) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int virDomainEventStateRegister(virConnectPtr conn, - virDomainEventStatePtr state, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int virDomainEventStateRegisterID(virConnectPtr conn, - virDomainEventStatePtr state, + virObjectEventStatePtr state, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback cb, @@ -162,20 +139,5 @@ int virDomainEventStateRegisterID(virConnectPtr conn, virFreeCallback freecb, int *callbackID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); -int -virDomainEventStateDeregister(virConnectPtr conn, - virDomainEventStatePtr state, - virConnectDomainEventCallback callback) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); -int -virDomainEventStateDeregisterID(virConnectPtr conn, - virDomainEventStatePtr state, - int callbackID) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int -virDomainEventStateEventID(virConnectPtr conn, - virDomainEventStatePtr state, - int callbackID) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); #endif diff --git a/src/conf/object_event.c b/src/conf/object_event.c new file mode 100644 index 0000000..46eb677 --- /dev/null +++ b/src/conf/object_event.c @@ -0,0 +1,918 @@ +/* + * domain_event.c: domain event queue processing helpers + * + * Copyright (C) 2010-2013 Red Hat, Inc. + * Copyright (C) 2008 VirtualIron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Ben Guthro + */ + +#include <config.h> + +#include "object_event.h" +#include "object_event_private.h" +#include "virlog.h" +#include "viralloc.h" +#include "virerror.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + + +/** + * virObjectEventCallbackListFree: + * @list: event callback list head + * + * Free the memory in the domain event callback list + */ +static void +virObjectEventCallbackListFree(virObjectEventCallbackListPtr list) +{ + size_t i; + if (!list) + return; + + for (i=0; i<list->count; i++) { + virFreeCallback freecb = list->callbacks[i]->freecb; + if (freecb) + (*freecb)(list->callbacks[i]->opaque); + VIR_FREE(list->callbacks[i]); + } + VIR_FREE(list->callbacks); + VIR_FREE(list); +} + + +/** + * virObjectEventCallbackListRemoveID: + * @conn: pointer to the connection + * @cbList: the list + * @callback: the callback to remove + * + * Internal function to remove a callback from a virObjectEventCallbackListPtr + */ +static int +virObjectEventCallbackListRemoveID(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + int callbackID) +{ + int ret = 0; + size_t i; + for (i = 0; i < cbList->count; i++) { + if (cbList->callbacks[i]->callbackID == callbackID && + cbList->callbacks[i]->conn == conn) { + virFreeCallback freecb = cbList->callbacks[i]->freecb; + if (freecb) + (*freecb)(cbList->callbacks[i]->opaque); + virObjectUnref(cbList->callbacks[i]->conn); + VIR_FREE(cbList->callbacks[i]); + + if (i < (cbList->count - 1)) + memmove(cbList->callbacks + i, + cbList->callbacks + i + 1, + sizeof(*(cbList->callbacks)) * + (cbList->count - (i + 1))); + + if (VIR_REALLOC_N(cbList->callbacks, + cbList->count - 1) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + cbList->count--; + + for (i = 0; i < cbList->count; i++) { + if (!cbList->callbacks[i]->deleted) + ret++; + } + return ret; + } + } + + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not find event callback for removal")); + return -1; +} + + +static int +virObjectEventCallbackListMarkDeleteID(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + int callbackID) +{ + int ret = 0; + size_t i; + for (i = 0; i < cbList->count; i++) { + if (cbList->callbacks[i]->callbackID == callbackID && + cbList->callbacks[i]->conn == conn) { + cbList->callbacks[i]->deleted = 1; + for (i = 0; i < cbList->count; i++) { + if (!cbList->callbacks[i]->deleted) + ret++; + } + return ret; + } + } + + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not find event callback for deletion")); + return -1; +} + + +static int +virObjectEventCallbackListPurgeMarked(virObjectEventCallbackListPtr cbList) +{ + int old_count = cbList->count; + int n; + for (n = 0; n < cbList->count; n++) { + if (cbList->callbacks[n]->deleted) { + virFreeCallback freecb = cbList->callbacks[n]->freecb; + if (freecb) + (*freecb)(cbList->callbacks[n]->opaque); + virObjectUnref(cbList->callbacks[n]->conn); + VIR_FREE(cbList->callbacks[n]); + + if (n < (cbList->count - 1)) + memmove(cbList->callbacks + n, + cbList->callbacks + n + 1, + sizeof(*(cbList->callbacks)) * + (cbList->count - (n + 1))); + cbList->count--; + n--; + } + } + if (cbList->count < old_count && + VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + return 0; +} + + +/** + * virObjectEventCallbackListAddID: + * @conn: pointer to the connection + * @cbList: the list + * @eventID: the event ID + * @callback: the callback to add + * @opaque: opaque data tio pass to callback + * @callbackID: filled with callback ID + * + * Internal function to add a callback from a virObjectEventCallbackListPtr + */ +int +virObjectEventCallbackListAddID(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + unsigned char uuid[VIR_UUID_BUFLEN], + const char *name, + int id, + int eventID, + virConnectObjectEventGenericCallback callback, + void *opaque, + virFreeCallback freecb, + int *callbackID) +{ + virObjectEventCallbackPtr event; + size_t i; + int ret = 0; + + /* Check incoming */ + if (!cbList) { + return -1; + } + + /* check if we already have this callback on our list */ + for (i = 0; i < cbList->count; i++) { + if (cbList->callbacks[i]->cb == VIR_OBJECT_EVENT_CALLBACK(callback) && + cbList->callbacks[i]->eventID == eventID && + cbList->callbacks[i]->conn == conn && + ((uuid && cbList->callbacks[i]->dom && + memcmp(cbList->callbacks[i]->dom->uuid, + uuid, VIR_UUID_BUFLEN) == 0) || + (!uuid && !cbList->callbacks[i]->dom))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("event callback already tracked")); + return -1; + } + } + /* Allocate new event */ + if (VIR_ALLOC(event) < 0) + goto error; + event->conn = conn; + event->cb = callback; + event->eventID = eventID; + event->opaque = opaque; + event->freecb = freecb; + + if (name && uuid && id > 0) { + if (VIR_ALLOC(event->dom) < 0) + goto error; + if (VIR_STRDUP(event->dom->name, name) < 0) + goto error; + memcpy(event->dom->uuid, uuid, VIR_UUID_BUFLEN); + event->dom->id = id; + } + + /* Make space on list */ + if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0) + goto error; + + virObjectRef(event->conn); + + cbList->callbacks[cbList->count] = event; + cbList->count++; + + event->callbackID = cbList->nextID++; + + for (i = 0; i < cbList->count; i++) { + if (cbList->callbacks[i]->eventID == eventID && + cbList->callbacks[i]->conn == conn && + !cbList->callbacks[i]->deleted) + ret++; + } + + if (callbackID) + *callbackID = event->callbackID; + + return ret; + +error: + if (event) { + if (event->dom) + VIR_FREE(event->dom->name); + VIR_FREE(event->dom); + } + VIR_FREE(event); + return -1; +} + +static int +virObjectEventCallbackListEventID(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + int callbackID) +{ + size_t i; + + for (i = 0; i < cbList->count; i++) { + if (cbList->callbacks[i]->deleted) + continue; + + if (cbList->callbacks[i]->callbackID == callbackID && + cbList->callbacks[i]->conn == conn) + return cbList->callbacks[i]->eventID; + } + + return -1; +} + +static void +virDomainEventDataFree(virObjectEventPtr event) +{ + switch (event->eventID) { + case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: + case VIR_DOMAIN_EVENT_ID_IO_ERROR: + VIR_FREE(event->data.domainData.ioError.srcPath); + VIR_FREE(event->data.domainData.ioError.devAlias); + VIR_FREE(event->data.domainData.ioError.reason); + break; + + case VIR_DOMAIN_EVENT_ID_GRAPHICS: + if (event->data.domainData.graphics.local) { + VIR_FREE(event->data.domainData.graphics.local->node); + VIR_FREE(event->data.domainData.graphics.local->service); + VIR_FREE(event->data.domainData.graphics.local); + } + if (event->data.domainData.graphics.remote) { + VIR_FREE(event->data.domainData.graphics.remote->node); + VIR_FREE(event->data.domainData.graphics.remote->service); + VIR_FREE(event->data.domainData.graphics.remote); + } + VIR_FREE(event->data.domainData.graphics.authScheme); + if (event->data.domainData.graphics.subject) { + size_t i; + for (i = 0; i < event->data.domainData.graphics.subject->nidentity; i++) { + VIR_FREE(event->data.domainData.graphics.subject->identities[i].type); + VIR_FREE(event->data.domainData.graphics.subject->identities[i].name); + } + VIR_FREE(event->data.domainData.graphics.subject); + } + break; + + case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: + VIR_FREE(event->data.domainData.blockJob.path); + break; + + case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: + VIR_FREE(event->data.domainData.diskChange.oldSrcPath); + VIR_FREE(event->data.domainData.diskChange.newSrcPath); + VIR_FREE(event->data.domainData.diskChange.devAlias); + break; + case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: + VIR_FREE(event->data.domainData.trayChange.devAlias); + break; + case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: + VIR_FREE(event->data.domainData.deviceRemoved.devAlias); + break; + } +} + +void virObjectEventFree(virObjectEventPtr event) +{ + if (!event) + return; + + int namespace = (event->eventID & 0xFF00) >> 8; + switch (namespace) + { + case VIR_EVENT_NAMESPACE_DOMAIN: + virDomainEventDataFree(event); + break; + } + + VIR_FREE(event->dom.name); + VIR_FREE(event); +} + +/** + * virObjectEventQueueClear: + * @queue: pointer to the queue + * + * Removes all elements from the queue + */ +void +virObjectEventQueueClear(virObjectEventQueuePtr queue) +{ + size_t i; + if (!queue) + return; + + for (i = 0; i < queue->count; i++) { + virObjectEventFree(queue->events[i]); + } + VIR_FREE(queue->events); + queue->count = 0; +} + +/** + * virObjectEventQueueFree: + * @queue: pointer to the queue + * + * Free the memory in the queue. We process this like a list here + */ +static void +virObjectEventQueueFree(virObjectEventQueuePtr queue) +{ + if (!queue) + return; + + virObjectEventQueueClear(queue); + VIR_FREE(queue); +} + +static virObjectEventQueuePtr +virObjectEventQueueNew(void) +{ + virObjectEventQueuePtr ret; + + ignore_value(VIR_ALLOC(ret)); + return ret; +} + +void +virObjectEventStateLock(virObjectEventStatePtr state) +{ + virMutexLock(&state->lock); +} + +void +virObjectEventStateUnlock(virObjectEventStatePtr state) +{ + virMutexUnlock(&state->lock); +} + +/** + * virObjectEventStateFree: + * @list: virObjectEventStatePtr to free + * + * Free a virObjectEventStatePtr and its members, and unregister the timer. + */ +void +virObjectEventStateFree(virObjectEventStatePtr state) +{ + if (!state) + return; + + virObjectEventCallbackListFree(state->callbacks); + virObjectEventQueueFree(state->queue); + + if (state->timer != -1) + virEventRemoveTimeout(state->timer); + + virMutexDestroy(&state->lock); + VIR_FREE(state); +} + + +static void virObjectEventStateFlush(virObjectEventStatePtr state); + +void +virObjectEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + virObjectEventStatePtr state = opaque; + + virObjectEventStateFlush(state); +} + +/** + * virObjectEventStateNew: + */ +virObjectEventStatePtr +virObjectEventStateNew(void) +{ + virObjectEventStatePtr state = NULL; + + if (VIR_ALLOC(state) < 0) + goto error; + + if (virMutexInit(&state->lock) < 0) { + virReportSystemError(errno, "%s", + _("unable to initialize state mutex")); + VIR_FREE(state); + goto error; + } + + if (VIR_ALLOC(state->callbacks) < 0) + goto error; + + if (!(state->queue = virObjectEventQueueNew())) + goto error; + + state->timer = -1; + + return state; + +error: + virObjectEventStateFree(state); + return NULL; +} + +virObjectEventPtr virObjectEventNewInternal(int eventID, + int id, + const char *name, + const unsigned char *uuid) +{ + virObjectEventPtr event; + + if (VIR_ALLOC(event) < 0) + return NULL; + + event->eventID = eventID; + if (VIR_STRDUP(event->dom.name, name) < 0) { + VIR_FREE(event); + return NULL; + } + event->dom.id = id; + memcpy(event->dom.uuid, uuid, VIR_UUID_BUFLEN); + + return event; +} + + +/** + * virObjectEventQueuePush: + * @evtQueue: the dom event queue + * @event: the event to add + * + * Internal function to push to the back of a virObjectEventQueue + * + * Returns: 0 on success, -1 on failure + */ +static int +virObjectEventQueuePush(virObjectEventQueuePtr evtQueue, + virObjectEventPtr event) +{ + if (!evtQueue) { + return -1; + } + + /* Make space on queue */ + if (VIR_REALLOC_N(evtQueue->events, + evtQueue->count + 1) < 0) + return -1; + + evtQueue->events[evtQueue->count] = event; + evtQueue->count++; + return 0; +} + + +typedef void (*virObjectEventDispatchFunc)(virConnectPtr conn, + virObjectEventPtr event, + virConnectObjectEventGenericCallback cb, + void *cbopaque, + void *opaque); + + +static void +virDomainEventDispatchDefaultFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectDomainEventGenericCallback cb, + void *cbopaque, + void *opaque ATTRIBUTE_UNUSED) +{ + virDomainPtr dom = virGetDomain(conn, event->dom.name, event->dom.uuid); + if (!dom) + return; + dom->id = event->dom.id; + + switch ((virDomainEventID) event->eventID) { + case VIR_DOMAIN_EVENT_ID_LIFECYCLE: + ((virConnectDomainEventCallback)cb)(conn, dom, + event->data.domainData.lifecycle.type, + event->data.domainData.lifecycle.detail, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_REBOOT: + (cb)(conn, dom, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_RTC_CHANGE: + ((virConnectDomainEventRTCChangeCallback)cb)(conn, dom, + event->data.domainData.rtcChange.offset, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_WATCHDOG: + ((virConnectDomainEventWatchdogCallback)cb)(conn, dom, + event->data.domainData.watchdog.action, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_IO_ERROR: + ((virConnectDomainEventIOErrorCallback)cb)(conn, dom, + event->data.domainData.ioError.srcPath, + event->data.domainData.ioError.devAlias, + event->data.domainData.ioError.action, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: + ((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom, + event->data.domainData.ioError.srcPath, + event->data.domainData.ioError.devAlias, + event->data.domainData.ioError.action, + event->data.domainData.ioError.reason, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_GRAPHICS: + ((virConnectDomainEventGraphicsCallback)cb)(conn, dom, + event->data.domainData.graphics.phase, + event->data.domainData.graphics.local, + event->data.domainData.graphics.remote, + event->data.domainData.graphics.authScheme, + event->data.domainData.graphics.subject, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR: + (cb)(conn, dom, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: + ((virConnectDomainEventBlockJobCallback)cb)(conn, dom, + event->data.domainData.blockJob.path, + event->data.domainData.blockJob.type, + event->data.domainData.blockJob.status, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: + ((virConnectDomainEventDiskChangeCallback)cb)(conn, dom, + event->data.domainData.diskChange.oldSrcPath, + event->data.domainData.diskChange.newSrcPath, + event->data.domainData.diskChange.devAlias, + event->data.domainData.diskChange.reason, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: + ((virConnectDomainEventTrayChangeCallback)cb)(conn, dom, + event->data.domainData.trayChange.devAlias, + event->data.domainData.trayChange.reason, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_PMWAKEUP: + ((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, 0, cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_PMSUSPEND: + ((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE: + ((virConnectDomainEventBalloonChangeCallback)cb)(conn, dom, + event->data.domainData.balloonChange.actual, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: + ((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom, 0, cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: + ((virConnectDomainEventDeviceRemovedCallback)cb)(conn, dom, + event->data.domainData.deviceRemoved.devAlias, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_LAST: + break; + } + VIR_WARN("Unexpected event ID %d", event->eventID); + +cleanup: + virDomainFree(dom); +} + + +static int virObjectEventDispatchMatchCallback(virObjectEventPtr event, + virObjectEventCallbackPtr cb) +{ + if (!cb) + return 0; + if (cb->deleted) + return 0; + if (cb->eventID != event->eventID) + return 0; + + if (cb->dom) { + /* Deliberately ignoring 'id' for matching, since that + * will cause problems when a domain switches between + * running & shutoff states & ignoring 'name' since + * Xen sometimes renames guests during migration, thus + * leaving 'uuid' as the only truly reliable ID we can use*/ + + if (memcmp(event->dom.uuid, cb->dom->uuid, VIR_UUID_BUFLEN) == 0) + return 1; + + return 0; + } else { + return 1; + } +} + + +static void +virObjectEventDispatch(virObjectEventPtr event, + virObjectEventCallbackListPtr callbacks, + virObjectEventDispatchFunc dispatch, + void *opaque) +{ + size_t i; + /* Cache this now, since we may be dropping the lock, + and have more callbacks added. We're guaranteed not + to have any removed */ + int cbCount = callbacks->count; + + for (i = 0; i < cbCount; i++) { + if (!virObjectEventDispatchMatchCallback(event, callbacks->callbacks[i])) + continue; + + (*dispatch)(callbacks->callbacks[i]->conn, + event, + callbacks->callbacks[i]->cb, + callbacks->callbacks[i]->opaque, + opaque); + } +} + + +static void +virObjectEventQueueDispatch(virObjectEventQueuePtr queue, + virObjectEventCallbackListPtr callbacks, + virObjectEventDispatchFunc dispatch, + void *opaque) +{ + size_t i; + + for (i = 0; i < queue->count; i++) { + virObjectEventDispatch(queue->events[i], callbacks, dispatch, opaque); + virObjectEventFree(queue->events[i]); + } + VIR_FREE(queue->events); + queue->count = 0; +} + +void +virObjectEventStateQueue(virObjectEventStatePtr state, + virObjectEventPtr event) +{ + if (state->timer < 0) { + virObjectEventFree(event); + return; + } + + virObjectEventStateLock(state); + + if (virObjectEventQueuePush(state->queue, event) < 0) { + VIR_DEBUG("Error adding event to queue"); + virObjectEventFree(event); + } + + if (state->queue->count == 1) + virEventUpdateTimeout(state->timer, 0); + virObjectEventStateUnlock(state); +} + + +static void +virObjectEventStateDispatchFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectObjectEventGenericCallback cb, + void *cbopaque, + void *opaque) +{ + virObjectEventStatePtr state = opaque; + virEventNamespaceID namespace = (event->eventID & 0xFF00) >> 8; + + /* Drop the lock whle dispatching, for sake of re-entrancy */ + virObjectEventStateUnlock(state); + switch (namespace) + { + case VIR_EVENT_NAMESPACE_DOMAIN: + virDomainEventDispatchDefaultFunc(conn, event, + VIR_DOMAIN_EVENT_CALLBACK(cb), cbopaque, NULL); + break; + } + virObjectEventStateLock(state); +} + + +static void +virObjectEventStateFlush(virObjectEventStatePtr state) +{ + virObjectEventQueue tempQueue; + + virObjectEventStateLock(state); + state->isDispatching = true; + + /* Copy the queue, so we're reentrant safe when dispatchFunc drops the + * driver lock */ + tempQueue.count = state->queue->count; + tempQueue.events = state->queue->events; + state->queue->count = 0; + state->queue->events = NULL; + virEventUpdateTimeout(state->timer, -1); + + virObjectEventQueueDispatch(&tempQueue, + state->callbacks, + virObjectEventStateDispatchFunc, + state); + + /* Purge any deleted callbacks */ + virObjectEventCallbackListPurgeMarked(state->callbacks); + + state->isDispatching = false; + virObjectEventStateUnlock(state); +} + + +/** + * virObjectEventStateRegisterID: + * @conn: connection to associate with callback + * @state: domain event state + * @eventID: ID of the event type to register for + * @cb: function to remove from event + * @opaque: data blob to pass to callback + * @freecb: callback to free @opaque + * @callbackID: filled with callback ID + * + * Register the function @callbackID with connection @conn, + * from @state, for events of type @eventID. + * + * Returns: the number of callbacks now registered, or -1 on error + */ +int +virObjectEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + unsigned char uuid[VIR_UUID_BUFLEN], + const char *name, + int id, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) +{ + int ret = -1; + + virObjectEventStateLock(state); + + if ((state->callbacks->count == 0) && + (state->timer == -1) && + (state->timer = virEventAddTimeout(-1, + virObjectEventTimer, + state, + NULL)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not initialize domain event timer")); + goto cleanup; + } + + ret = virObjectEventCallbackListAddID(conn, state->callbacks, + uuid, name, id, eventID, cb, opaque, freecb, + callbackID); + + if (ret == -1 && + state->callbacks->count == 0 && + state->timer != -1) { + virEventRemoveTimeout(state->timer); + state->timer = -1; + } + +cleanup: + virObjectEventStateUnlock(state); + return ret; +} + + +/** + * virObjectEventStateDeregisterID: + * @conn: connection to associate with callback + * @state: domain event state + * @callbackID: ID of the function to remove from event + * + * Unregister the function @callbackID with connection @conn, + * from @state, for events. + * + * Returns: the number of callbacks still registered, or -1 on error + */ +int +virObjectEventStateDeregisterID(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID) +{ + int ret; + + virObjectEventStateLock(state); + if (state->isDispatching) + ret = virObjectEventCallbackListMarkDeleteID(conn, + state->callbacks, callbackID); + else + ret = virObjectEventCallbackListRemoveID(conn, + state->callbacks, callbackID); + + if (state->callbacks->count == 0 && + state->timer != -1) { + virEventRemoveTimeout(state->timer); + state->timer = -1; + virObjectEventQueueClear(state->queue); + } + + virObjectEventStateUnlock(state); + return ret; +} + + +/** + * virObjectEventStateEventID: + * @conn: connection associated with the callback + * @state: domain event state + * @callbackID: the callback to query + * + * Query what event ID type is associated with the + * callback @callbackID for connection @conn + * + * Returns 0 on success, -1 on error + */ +int +virObjectEventStateEventID(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID) +{ + int ret; + + virObjectEventStateLock(state); + ret = virObjectEventCallbackListEventID(conn, + state->callbacks, callbackID); + virObjectEventStateUnlock(state); + return ret; +} diff --git a/src/conf/object_event.h b/src/conf/object_event.h new file mode 100644 index 0000000..bf5727f --- /dev/null +++ b/src/conf/object_event.h @@ -0,0 +1,93 @@ +/* + * domain_event.h: domain event queue processing helpers + * + * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2008 VirtualIron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Ben Guthro + */ + +#include "internal.h" + +#ifndef __OBJECT_EVENT_H__ +# define __OBJECT_EVENT_H__ + +typedef struct _virObjectEventCallback virObjectEventCallback; +typedef virObjectEventCallback *virObjectEventCallbackPtr; + +typedef struct _virObjectEventCallbackList virObjectEventCallbackList; +typedef virObjectEventCallbackList *virObjectEventCallbackListPtr; + +/** + * Dispatching domain events that come in while + * in a call / response rpc + */ +typedef struct _virObjectEvent virObjectEvent; +typedef virObjectEvent *virObjectEventPtr; + +typedef struct _virObjectEventQueue virObjectEventQueue; +typedef virObjectEventQueue *virObjectEventQueuePtr; + +typedef struct _virObjectEventState virObjectEventState; +typedef virObjectEventState *virObjectEventStatePtr; + +void virObjectEventFree(virObjectEventPtr event); + +void virObjectEventStateFree(virObjectEventStatePtr state); +virObjectEventStatePtr +virObjectEventStateNew(void); + +/* + * virConnectObjectEventGenericCallback: + * @conn: the connection pointer + * @obj: the object pointer + * @opaque: application specified data + * + * A generic object event callback handler. Specific events usually + * have a customization with extra parameters + */ +typedef void (*virConnectObjectEventGenericCallback)(virConnectPtr conn, + void *obj, + void *opaque); + +void +virObjectEventStateQueue(virObjectEventStatePtr state, + virObjectEventPtr event) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int virObjectEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + unsigned char uuid[VIR_UUID_BUFLEN], + const char *name, + int id, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(7); +int +virObjectEventStateDeregisterID(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +virObjectEventStateEventID(virConnectPtr conn, + virObjectEventStatePtr state, + int callbackID) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +#endif diff --git a/src/conf/object_event_private.h b/src/conf/object_event_private.h new file mode 100644 index 0000000..8089155 --- /dev/null +++ b/src/conf/object_event_private.h @@ -0,0 +1,160 @@ +/* + * domain_event.h: domain event queue processing helpers + * + * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2008 VirtualIron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Ben Guthro + */ + +#ifndef __OBJECT_EVENT_PRIVATE_H__ +# define __OBJECT_EVENT_PRIVATE_H__ + +#include "datatypes.h" + +#define VIR_OBJECT_EVENT_CALLBACK(cb) ((virConnectObjectEventGenericCallback)(cb)) + +struct _virObjectMeta { + int id; + char *name; + unsigned char uuid[VIR_UUID_BUFLEN]; +}; +typedef struct _virObjectMeta virObjectMeta; +typedef virObjectMeta *virObjectMetaPtr; + +struct _virObjectEventCallbackList { + unsigned int nextID; + unsigned int count; + virObjectEventCallbackPtr *callbacks; +}; + +struct _virObjectEventQueue { + unsigned int count; + virObjectEventPtr *events; +}; + +struct _virObjectEventState { + /* The list of domain event callbacks */ + virObjectEventCallbackListPtr callbacks; + /* The queue of domain events */ + virObjectEventQueuePtr queue; + /* Timer for flushing events queue */ + int timer; + /* Flag if we're in process of dispatching */ + bool isDispatching; + virMutex lock; +}; + +struct _virObjectEventCallback { + int callbackID; + int eventID; + virConnectPtr conn; + virObjectMetaPtr dom; + virConnectObjectEventGenericCallback cb; + void *opaque; + virFreeCallback freecb; + int deleted; +}; + +union virDomainEventData { + struct { + int type; + int detail; + } lifecycle; + struct { + long long offset; + } rtcChange; + struct { + int action; + } watchdog; + struct { + char *srcPath; + char *devAlias; + int action; + char *reason; + } ioError; + struct { + int phase; + virDomainEventGraphicsAddressPtr local; + virDomainEventGraphicsAddressPtr remote; + char *authScheme; + virDomainEventGraphicsSubjectPtr subject; + } graphics; + struct { + char *path; + int type; + int status; + } blockJob; + struct { + char *oldSrcPath; + char *newSrcPath; + char *devAlias; + int reason; + } diskChange; + struct { + char *devAlias; + int reason; + } trayChange; + struct { + /* In unit of 1024 bytes */ + unsigned long long actual; + } balloonChange; + struct { + char *devAlias; + } deviceRemoved; +}; + +struct _virObjectEvent { + int eventID; + + virObjectMeta dom; + + union { + union virDomainEventData domainData; + } data; +}; + +virObjectEventPtr virObjectEventNewInternal(int eventID, + int id, + const char *name, + const unsigned char *uuid); + +int +virObjectEventCallbackListAddID(virConnectPtr conn, + virObjectEventCallbackListPtr cbList, + unsigned char uuid[VIR_UUID_BUFLEN], + const char *name, + int id, + int eventID, + virConnectObjectEventGenericCallback callback, + void *opaque, + virFreeCallback freecb, + int *callbackID); + +void +virObjectEventStateLock(virObjectEventStatePtr state); + +void +virObjectEventStateUnlock(virObjectEventStatePtr state); + +void +virObjectEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque); + +void +virObjectEventQueueClear(virObjectEventQueuePtr queue); + +#endif diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a705c56..dc3882b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -421,7 +421,6 @@ virDomainEventDeviceRemovedNewFromDom; virDomainEventDeviceRemovedNewFromObj; virDomainEventDiskChangeNewFromDom; virDomainEventDiskChangeNewFromObj; -virDomainEventFree; virDomainEventGraphicsNewFromDom; virDomainEventGraphicsNewFromObj; virDomainEventIOErrorNewFromDom; @@ -444,11 +443,6 @@ virDomainEventRebootNewFromObj; virDomainEventRTCChangeNewFromDom; virDomainEventRTCChangeNewFromObj; virDomainEventStateDeregister; -virDomainEventStateDeregisterID; -virDomainEventStateEventID; -virDomainEventStateFree; -virDomainEventStateNew; -virDomainEventStateQueue; virDomainEventStateRegister; virDomainEventStateRegisterID; virDomainEventTrayChangeNewFromDom; @@ -625,6 +619,15 @@ virNWFilterVarValueGetCardinality; virNWFilterVarValueGetNthValue; virNWFilterVarValueGetSimple; +# conf/object_event.h +virObjectEventFree; +virObjectEventStateDeregisterID; +virObjectEventStateEventID; +virObjectEventStateFree; +virObjectEventStateNew; +virObjectEventStateQueue; +virObjectEventStateRegisterID; + # conf/secret_conf.h virSecretDefFormat; diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 8ba0ee4..ffa93bd 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -105,7 +105,7 @@ struct _libxlDriverPrivate { virDomainXMLOptionPtr xmlopt; /* Immutable pointer, self-locking APIs */ - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; /* Immutable pointer, self-locking APIs */ virPortAllocatorPtr reservedVNCPorts; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 7a75a04..8ead663 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -100,9 +100,9 @@ libxlDomObjFromDomain(virDomainPtr dom) } static void -libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event) +libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event) { - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } static int @@ -359,7 +359,7 @@ libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event) libxlDriverPrivatePtr driver = libxl_driver; libxlDomainObjPrivatePtr priv = ((virDomainObjPtr)data)->privateData; virDomainObjPtr vm = NULL; - virDomainEventPtr dom_event = NULL; + virObjectEventPtr dom_event = NULL; libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { @@ -546,7 +546,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, { libxl_domain_config d_config; virDomainDefPtr def = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; libxlSavefileHeader hdr; int ret; uint32_t domid = 0; @@ -778,7 +778,7 @@ libxlStateCleanup(void) virObjectUnref(libxl_driver->domains); virObjectUnref(libxl_driver->reservedVNCPorts); - virDomainEventStateFree(libxl_driver->domainEventState); + virObjectEventStateFree(libxl_driver->domainEventState); virSysinfoDefFree(libxl_driver->hostsysinfo); virMutexDestroy(&libxl_driver->lock); @@ -888,7 +888,7 @@ libxlStateInitialize(bool privileged, /* read the host sysinfo */ libxl_driver->hostsysinfo = virSysinfoRead(); - libxl_driver->domainEventState = virDomainEventStateNew(); + libxl_driver->domainEventState = virObjectEventStateNew(); if (!libxl_driver->domainEventState) goto error; @@ -1298,7 +1298,7 @@ libxlDomainSuspend(virDomainPtr dom) libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); virDomainObjPtr vm; libxlDomainObjPrivatePtr priv; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; if (!(vm = libxlDomObjFromDomain(dom))) @@ -1350,7 +1350,7 @@ libxlDomainResume(virDomainPtr dom) libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); virDomainObjPtr vm; libxlDomainObjPrivatePtr priv; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; if (!(vm = libxlDomObjFromDomain(dom))) @@ -1485,7 +1485,7 @@ libxlDomainDestroyFlags(virDomainPtr dom, libxlDriverPrivatePtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virCheckFlags(0, -1); @@ -1773,7 +1773,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm, { libxlDomainObjPrivatePtr priv = vm->privateData; libxlSavefileHeader hdr; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; char *xml = NULL; uint32_t xml_len; int fd = -1; @@ -1963,7 +1963,7 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags) libxlDriverPrivatePtr driver = dom->conn->privateData; libxlDomainObjPrivatePtr priv; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; bool paused = false; int ret = -1; @@ -2665,7 +2665,7 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml) virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainDefPtr oldDef = NULL; /* Lock the driver until the virDomainObj is created and locked */ @@ -2726,7 +2726,7 @@ libxlDomainUndefineFlags(virDomainPtr dom, libxlDriverPrivatePtr driver = dom->conn->privateData; libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; char *name = NULL; int ret = -1; @@ -4145,7 +4145,7 @@ libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID) if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) return -1; - ret = virDomainEventStateDeregisterID(conn, + ret = virObjectEventStateDeregisterID(conn, driver->domainEventState, callbackID); diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index a6208a2..f6cbfc9 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -97,7 +97,7 @@ struct _virLXCDriver { virUSBDeviceListPtr activeUsbHostdevs; /* Immutable pointer, self-locking APIs */ - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; /* Immutable pointer. self-locking APIs */ virSecurityManagerPtr securityManager; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 61a90ca..f65e7d6 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -441,7 +441,7 @@ static virDomainPtr lxcDomainDefineXML(virConnectPtr conn, const char *xml) virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainDefPtr oldDef = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); virCapsPtr caps = NULL; @@ -496,7 +496,7 @@ cleanup: if (vm) virObjectUnlock(vm); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); virObjectUnref(caps); virObjectUnref(cfg); return dom; @@ -507,7 +507,7 @@ static int lxcDomainUndefineFlags(virDomainPtr dom, { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); @@ -547,7 +547,7 @@ cleanup: if (vm) virObjectUnlock(vm); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); virObjectUnref(cfg); return ret; } @@ -902,7 +902,7 @@ static int lxcDomainCreateWithFiles(virDomainPtr dom, { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); @@ -944,7 +944,7 @@ cleanup: if (vm) virObjectUnlock(vm); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); virObjectUnref(cfg); return ret; } @@ -996,7 +996,7 @@ lxcDomainCreateXMLWithFiles(virConnectPtr conn, virDomainObjPtr vm = NULL; virDomainDefPtr def = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); virCapsPtr caps = NULL; @@ -1054,7 +1054,7 @@ cleanup: if (vm) virObjectUnlock(vm); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); virObjectUnref(caps); virObjectUnref(cfg); return dom; @@ -1245,7 +1245,7 @@ lxcConnectDomainEventDeregisterAny(virConnectPtr conn, if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) return -1; - ret = virDomainEventStateDeregisterID(conn, + ret = virObjectEventStateDeregisterID(conn, driver->domainEventState, callbackID); @@ -1268,7 +1268,7 @@ lxcDomainDestroyFlags(virDomainPtr dom, { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virLXCDomainObjPrivatePtr priv; @@ -1302,7 +1302,7 @@ cleanup: if (vm) virObjectUnlock(vm); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); return ret; } @@ -1398,7 +1398,7 @@ static int lxcStateInitialize(bool privileged, if (!(lxc_driver->domains = virDomainObjListNew())) goto cleanup; - lxc_driver->domainEventState = virDomainEventStateNew(); + lxc_driver->domainEventState = virObjectEventStateNew(); if (!lxc_driver->domainEventState) goto cleanup; @@ -1481,12 +1481,12 @@ static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque) virLXCDriverPtr driver = opaque; if (newVM) { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED, VIR_DOMAIN_EVENT_DEFINED_ADDED); if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } } @@ -1528,7 +1528,7 @@ static int lxcStateCleanup(void) virNWFilterUnRegisterCallbackDriver(&lxcCallbackDriver); virObjectUnref(lxc_driver->domains); - virDomainEventStateFree(lxc_driver->domainEventState); + virObjectEventStateFree(lxc_driver->domainEventState); virObjectUnref(lxc_driver->closeCallbacks); @@ -2337,7 +2337,7 @@ static int lxcDomainSuspend(virDomainPtr dom) { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); @@ -2372,7 +2372,7 @@ static int lxcDomainSuspend(virDomainPtr dom) cleanup: if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); if (vm) virObjectUnlock(vm); virObjectUnref(cfg); @@ -2383,7 +2383,7 @@ static int lxcDomainResume(virDomainPtr dom) { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virLXCDomainObjPrivatePtr priv; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); @@ -2422,7 +2422,7 @@ static int lxcDomainResume(virDomainPtr dom) cleanup: if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); if (vm) virObjectUnlock(vm); virObjectUnref(cfg); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index c51c4d5..db85863 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -62,7 +62,7 @@ lxcProcessAutoDestroy(virDomainObjPtr dom, void *opaque) { virLXCDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virLXCDomainObjPrivatePtr priv; VIR_DEBUG("driver=%p dom=%s conn=%p", driver, dom->def->name, conn); @@ -82,7 +82,7 @@ lxcProcessAutoDestroy(virDomainObjPtr dom, } if (event) - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); return dom; } @@ -490,7 +490,7 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon, virDomainObjPtr vm) { virLXCDriverPtr driver = lxc_driver; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virLXCDomainObjPrivatePtr priv; VIR_DEBUG("mon=%p vm=%p", mon, vm); @@ -533,7 +533,7 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon, if (vm) virObjectUnlock(vm); if (event) { - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } } @@ -1394,12 +1394,12 @@ virLXCProcessAutostartDomain(virDomainObjPtr vm, vm->def->name, err ? err->message : ""); } else { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_BOOTED); if (event) - virDomainEventStateQueue(data->driver->domainEventState, event); + virObjectEventStateQueue(data->driver->domainEventState, event); } } virObjectUnlock(vm); diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index 12403ea..6215553 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -44,7 +44,7 @@ struct _parallelsConn { virNetworkObjList networks; virCapsPtr caps; virDomainXMLOptionPtr xmlopt; - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; }; typedef struct _parallelsConn parallelsConn; diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index f9ff7af..f26f7b9 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -207,7 +207,7 @@ struct _virQEMUDriver { virQEMUCapsCachePtr qemuCapsCache; /* Immutable pointer, self-locking APIs */ - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; /* Immutable pointer. self-locking APIs */ virSecurityManagerPtr securityManager; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 81d0ba9..d4fd6d1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -118,9 +118,9 @@ qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job, void qemuDomainEventQueue(virQEMUDriverPtr driver, - virDomainEventPtr event) + virObjectEventPtr event) { - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } @@ -2114,7 +2114,7 @@ qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver, virDomainDiskDefPtr disk) { char uuid[VIR_UUID_STRING_BUFLEN]; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainDiskDefPtr del_disk = NULL; virUUIDFormat(vm->def->uuid, uuid); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 77e0c20..6a92351 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -196,7 +196,7 @@ int qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job, void qemuDomainEventFlush(int timer, void *opaque); void qemuDomainEventQueue(virQEMUDriverPtr driver, - virDomainEventPtr event); + virObjectEventPtr event); int qemuDomainObjBeginJob(virQEMUDriverPtr driver, virDomainObjPtr obj, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 378b542..6292cf2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -597,7 +597,7 @@ qemuStateInitialize(bool privileged, goto error; /* Init domain events */ - qemu_driver->domainEventState = virDomainEventStateNew(); + qemu_driver->domainEventState = virObjectEventStateNew(); if (!qemu_driver->domainEventState) goto error; @@ -878,7 +878,7 @@ static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque) virQEMUDriverPtr driver = opaque; if (newVM) { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED, VIR_DOMAIN_EVENT_DEFINED_ADDED); @@ -1015,7 +1015,7 @@ qemuStateCleanup(void) { ebtablesContextFree(qemu_driver->ebtables); /* Free domain callback list */ - virDomainEventStateFree(qemu_driver->domainEventState); + virObjectEventStateFree(qemu_driver->domainEventState); virLockManagerPluginUnref(qemu_driver->lockManager); @@ -1566,8 +1566,8 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; - virDomainEventPtr event2 = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr event2 = NULL; unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD; virQEMUCapsPtr qemuCaps = NULL; virCapsPtr caps = NULL; @@ -1668,7 +1668,7 @@ static int qemuDomainSuspend(virDomainPtr dom) { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv; virDomainPausedReason reason; int eventDetail; @@ -1749,7 +1749,7 @@ static int qemuDomainResume(virDomainPtr dom) { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int state; virQEMUDriverConfigPtr cfg = NULL; virCapsPtr caps = NULL; @@ -2074,7 +2074,7 @@ qemuDomainDestroyFlags(virDomainPtr dom, virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv; virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1); @@ -3037,7 +3037,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom, bool was_running = false; int ret = -1; int rc; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps; @@ -3517,7 +3517,7 @@ static int qemuDomainCoreDump(virDomainPtr dom, qemuDomainObjPrivatePtr priv; bool resume = false, paused = false; int ret = -1; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH | VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET | @@ -3822,7 +3822,7 @@ processGuestPanicEvent(virQEMUDriverPtr driver, int action) { qemuDomainObjPrivatePtr priv = vm->privateData; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); if (!virDomainObjIsActive(vm)) { @@ -5336,7 +5336,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, bool start_paused) { int ret = -1; - virDomainEventPtr event; + virObjectEventPtr event; int intermediatefd = -1; virCommandPtr cmd = NULL; char *errbuf = NULL; @@ -6056,7 +6056,7 @@ qemuDomainObjStart(virConnectPtr conn, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags); virDomainAuditStart(vm, "booted", ret >= 0); if (ret >= 0) { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_BOOTED); @@ -6131,7 +6131,7 @@ static virDomainPtr qemuDomainDefineXML(virConnectPtr conn, const char *xml) { virDomainDefPtr oldDef = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUCapsPtr qemuCaps = NULL; virQEMUDriverConfigPtr cfg; virCapsPtr caps = NULL; @@ -6224,7 +6224,7 @@ qemuDomainUndefineFlags(virDomainPtr dom, { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; char *name = NULL; int ret = -1; int nsnapshots; @@ -9949,7 +9949,7 @@ qemuConnectDomainEventDeregisterAny(virConnectPtr conn, if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) goto cleanup; - if (virDomainEventStateDeregisterID(conn, + if (virObjectEventStateDeregisterID(conn, driver->domainEventState, callbackID) < 0) goto cleanup; @@ -11661,7 +11661,7 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn, { virDomainObjPtr vm = *vmptr; qemuDomainObjPrivatePtr priv = vm->privateData; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; bool resume = false; int ret = -1; @@ -12247,7 +12247,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, /* the snapshot is complete now */ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) { - virDomainEventPtr event; + virObjectEventPtr event; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT); @@ -12265,7 +12265,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn, /* qemu 1.3 is unable to save a domain in pm-suspended (S3) * state; so we must emit an event stating that it was * converted to paused. */ - virDomainEventPtr event; + virObjectEventPtr event; virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_FROM_SNAPSHOT); @@ -12282,7 +12282,7 @@ endjob: qemuProcessStartCPUs(driver, vm, conn, VIR_DOMAIN_RUNNING_UNPAUSED, QEMU_ASYNC_JOB_SNAPSHOT) < 0) { - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); @@ -12942,8 +12942,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, virDomainObjPtr vm = NULL; int ret = -1; virDomainSnapshotObjPtr snap = NULL; - virDomainEventPtr event = NULL; - virDomainEventPtr event2 = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr event2 = NULL; int detail; qemuDomainObjPrivatePtr priv; int rc; @@ -13164,7 +13164,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, QEMU_ASYNC_JOB_NONE); if (rc < 0) goto endjob; - virDomainEventFree(event); + virObjectEventFree(event); event = NULL; if (was_stopped) { /* Transition 2 */ @@ -13898,7 +13898,7 @@ cleanup: qemuProcessStartCPUs(driver, vm, conn, VIR_DOMAIN_RUNNING_UNPAUSED, QEMU_ASYNC_JOB_NONE) < 0) { - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); @@ -13925,7 +13925,7 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, char *device = NULL; int ret = -1; bool async = false; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int idx; virDomainDiskDefPtr disk; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0d9a3aa..84c2055 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2406,7 +2406,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver, virDomainDiskDefPtr disk) { virDomainDeviceDef dev; - virDomainEventPtr event; + virObjectEventPtr event; size_t i; VIR_DEBUG("Removing disk %s from domain %p %s", @@ -2450,7 +2450,7 @@ qemuDomainRemoveControllerDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainControllerDefPtr controller) { - virDomainEventPtr event; + virObjectEventPtr event; size_t i; VIR_DEBUG("Removing controller %s from domain %p %s", @@ -2538,7 +2538,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virDomainNetDefPtr net = NULL; - virDomainEventPtr event; + virObjectEventPtr event; size_t i; VIR_DEBUG("Removing host device %s from domain %p %s", @@ -2609,7 +2609,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver, { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virNetDevVPortProfilePtr vport; - virDomainEventPtr event; + virObjectEventPtr event; size_t i; if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { @@ -2674,7 +2674,7 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainChrDefPtr chr) { - virDomainEventPtr event; + virObjectEventPtr event; VIR_DEBUG("Removing character device %s from domain %p %s", chr->info.alias, vm, vm->def->name); diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index e87ea85..b998667 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1511,7 +1511,7 @@ qemuMigrationSetOffline(virQEMUDriverPtr driver, ret = qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_MIGRATION, QEMU_ASYNC_JOB_MIGRATION_OUT); if (ret == 0) { - virDomainEventPtr event; + virObjectEventPtr event; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, @@ -2169,7 +2169,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, unsigned long flags) { virDomainObjPtr vm = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; int dataFD[2] = { -1, -1 }; qemuDomainObjPrivatePtr priv = NULL; @@ -2708,7 +2708,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver, int retcode) { qemuMigrationCookiePtr mig; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int rv = -1; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); @@ -4061,7 +4061,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver, unsigned long resource, bool v3proto) { - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; int resume = 0; virErrorPtr orig_err = NULL; @@ -4175,7 +4175,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver, unsigned long flags, unsigned long resource) { - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; bool resume; bool hasrefs; @@ -4371,7 +4371,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver, bool v3proto) { virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; bool newVM = true; qemuMigrationCookiePtr mig = NULL; virErrorPtr orig_err = NULL; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a26c079..e9b1246 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -286,7 +286,7 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; qemuDomainObjPrivatePtr priv; int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN; int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; @@ -348,7 +348,7 @@ qemuProcessHandleMonitorError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; VIR_DEBUG("Received error on %p '%s'", vm, vm->def->name); @@ -516,7 +516,7 @@ qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event; + virObjectEventPtr event; qemuDomainObjPrivatePtr priv; virObjectLock(vm); @@ -549,7 +549,7 @@ qemuProcessFakeReboot(void *opaque) virQEMUDriverPtr driver = qemu_driver; virDomainObjPtr vm = opaque; qemuDomainObjPrivatePtr priv = vm->privateData; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virDomainRunningReason reason = VIR_DOMAIN_RUNNING_BOOTED; int ret = -1; @@ -648,7 +648,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED, { virQEMUDriverPtr driver = opaque; qemuDomainObjPrivatePtr priv; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); VIR_DEBUG("vm=%p", vm); @@ -702,7 +702,7 @@ qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -749,7 +749,7 @@ qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -803,7 +803,7 @@ qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -844,8 +844,8 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr watchdogEvent = NULL; - virDomainEventPtr lifecycleEvent = NULL; + virObjectEventPtr watchdogEvent = NULL; + virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -911,9 +911,9 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr ioErrorEvent = NULL; - virDomainEventPtr ioErrorEvent2 = NULL; - virDomainEventPtr lifecycleEvent = NULL; + virObjectEventPtr ioErrorEvent = NULL; + virObjectEventPtr ioErrorEvent2 = NULL; + virObjectEventPtr lifecycleEvent = NULL; const char *srcPath; const char *devAlias; virDomainDiskDefPtr disk; @@ -972,7 +972,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; const char *path; virDomainDiskDefPtr disk; @@ -1025,7 +1025,7 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event; + virObjectEventPtr event; virDomainEventGraphicsAddressPtr localAddr = NULL; virDomainEventGraphicsAddressPtr remoteAddr = NULL; virDomainEventGraphicsSubjectPtr subject = NULL; @@ -1104,7 +1104,7 @@ qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainDiskDefPtr disk; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); @@ -1140,8 +1140,8 @@ qemuProcessHandlePMWakeup(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; - virDomainEventPtr lifecycleEvent = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -1181,8 +1181,8 @@ qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; - virDomainEventPtr lifecycleEvent = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -1226,7 +1226,7 @@ qemuProcessHandleBalloonChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -1253,8 +1253,8 @@ qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, void *opaque) { virQEMUDriverPtr driver = opaque; - virDomainEventPtr event = NULL; - virDomainEventPtr lifecycleEvent = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr lifecycleEvent = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virObjectLock(vm); @@ -4628,7 +4628,7 @@ qemuProcessAutoDestroy(virDomainObjPtr dom, { virQEMUDriverPtr driver = opaque; qemuDomainObjPrivatePtr priv = dom->privateData; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; VIR_DEBUG("vm=%s, conn=%p", dom->def->name, conn); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 7181949..0074f46 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -92,7 +92,7 @@ struct private_data { char *hostname; /* Original hostname */ bool serverKeepAlive; /* Does server support keepalive protocol? */ - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; }; enum { @@ -150,7 +150,7 @@ static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virSto static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src); static void make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src); static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src); -static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event); +static void remoteDomainEventQueue(struct private_data *priv, virObjectEventPtr event); /*----------------------------------------------------------------------*/ /* Helper functions for remoteOpen. */ @@ -880,7 +880,7 @@ doRemoteOpen(virConnectPtr conn, goto failed; } - if (!(priv->domainEventState = virDomainEventStateNew())) + if (!(priv->domainEventState = virObjectEventStateNew())) goto failed; /* Successful. */ @@ -1081,7 +1081,7 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv) /* See comment for remoteType. */ VIR_FREE(priv->type); - virDomainEventStateFree(priv->domainEventState); + virObjectEventStateFree(priv->domainEventState); priv->domainEventState = NULL; return ret; @@ -4369,7 +4369,7 @@ remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_lifecycle_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4391,7 +4391,7 @@ remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_reboot_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4413,7 +4413,7 @@ remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_rtc_change_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4435,7 +4435,7 @@ remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_watchdog_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4457,7 +4457,7 @@ remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_io_error_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4482,7 +4482,7 @@ remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED struct private_data *priv = conn->privateData; remote_domain_event_io_error_reason_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn,msg->dom); if (!dom) @@ -4508,7 +4508,7 @@ remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_block_job_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4531,7 +4531,7 @@ remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_graphics_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainEventGraphicsAddressPtr localAddr = NULL; virDomainEventGraphicsAddressPtr remoteAddr = NULL; virDomainEventGraphicsSubjectPtr subject = NULL; @@ -4611,7 +4611,7 @@ remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_control_error_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4634,7 +4634,7 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_disk_change_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4661,7 +4661,7 @@ remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_tray_change_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4685,7 +4685,7 @@ remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_pmwakeup_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4707,7 +4707,7 @@ remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, struct private_data *priv = conn->privateData; remote_domain_event_pmsuspend_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4730,7 +4730,7 @@ remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED struct private_data *priv = conn->privateData; remote_domain_event_balloon_change_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4752,7 +4752,7 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED struct private_data *priv = conn->privateData; remote_domain_event_pmsuspend_disk_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -4775,7 +4775,7 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED struct private_data *priv = conn->privateData; remote_domain_event_device_removed_msg *msg = evdata; virDomainPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; dom = get_nonnull_domain(conn, msg->dom); if (!dom) @@ -5111,7 +5111,7 @@ static int remoteConnectDomainEventRegisterAny(virConnectPtr conn, if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY, (xdrproc_t) xdr_remote_connect_domain_event_register_any_args, (char *) &args, (xdrproc_t) xdr_void, (char *)NULL) == -1) { - virDomainEventStateDeregisterID(conn, + virObjectEventStateDeregisterID(conn, priv->domainEventState, callbackID); goto done; @@ -5137,14 +5137,14 @@ static int remoteConnectDomainEventDeregisterAny(virConnectPtr conn, remoteDriverLock(priv); - if ((eventID = virDomainEventStateEventID(conn, + if ((eventID = virObjectEventStateEventID(conn, priv->domainEventState, callbackID)) < 0) { virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID); goto done; } - if ((count = virDomainEventStateDeregisterID(conn, + if ((count = virObjectEventStateDeregisterID(conn, priv->domainEventState, callbackID)) < 0) { virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID); @@ -6679,9 +6679,9 @@ done: } static void -remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event) +remoteDomainEventQueue(struct private_data *priv, virObjectEventPtr event) { - virDomainEventStateQueue(priv->domainEventState, event); + virObjectEventStateQueue(priv->domainEventState, event); } /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2678247..f472494 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -99,7 +99,7 @@ struct _testConn { int numCells; testCell cells[MAX_CELLS]; - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; }; typedef struct _testConn testConn; typedef struct _testConn *testConnPtr; @@ -122,7 +122,7 @@ static const virNodeInfo defaultNodeInfo = { static int testConnectClose(virConnectPtr conn); static void testDomainEventQueue(testConnPtr driver, - virDomainEventPtr event); + virObjectEventPtr event); static void testDriverLock(testConnPtr driver) @@ -1444,7 +1444,7 @@ static virDrvOpenStatus testConnectOpen(virConnectPtr conn, privconn = conn->privateData; testDriverLock(privconn); - privconn->domainEventState = virDomainEventStateNew(); + privconn->domainEventState = virObjectEventStateNew(); if (!privconn->domainEventState) { testDriverUnlock(privconn); testConnectClose(conn); @@ -1467,7 +1467,7 @@ static int testConnectClose(virConnectPtr conn) virNetworkObjListFree(&privconn->networks); virInterfaceObjListFree(&privconn->ifaces); virStoragePoolObjListFree(&privconn->pools); - virDomainEventStateFree(privconn->domainEventState); + virObjectEventStateFree(privconn->domainEventState); VIR_FREE(privconn->path); testDriverUnlock(privconn); @@ -1615,7 +1615,7 @@ testDomainCreateXML(virConnectPtr conn, const char *xml, virDomainPtr ret = NULL; virDomainDefPtr def; virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virCheckFlags(0, NULL); @@ -1753,7 +1753,7 @@ static int testDomainDestroy(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; testDriverLock(privconn); @@ -1790,7 +1790,7 @@ static int testDomainResume(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; testDriverLock(privconn); @@ -1831,7 +1831,7 @@ static int testDomainSuspend(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; int state; @@ -1875,7 +1875,7 @@ static int testDomainShutdownFlags(virDomainPtr domain, { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -1927,7 +1927,7 @@ static int testDomainReboot(virDomainPtr domain, { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; testDriverLock(privconn); @@ -2071,7 +2071,7 @@ testDomainSaveFlags(virDomainPtr domain, const char *path, int fd = -1; int len; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -2184,7 +2184,7 @@ testDomainRestoreFlags(virConnectPtr conn, int len; virDomainDefPtr def = NULL; virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -2284,7 +2284,7 @@ static int testDomainCoreDump(virDomainPtr domain, testConnPtr privconn = domain->conn->privateData; int fd = -1; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(VIR_DUMP_CRASH, -1); @@ -2783,7 +2783,7 @@ static virDomainPtr testDomainDefineXML(virConnectPtr conn, virDomainPtr ret = NULL; virDomainDefPtr def; virDomainObjPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virDomainDefPtr oldDef = NULL; testDriverLock(privconn); @@ -2921,7 +2921,7 @@ cleanup: static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -2969,7 +2969,7 @@ static int testDomainUndefineFlags(virDomainPtr domain, { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int nsnapshots; int ret = -1; @@ -6018,7 +6018,7 @@ testConnectDomainEventDeregisterAny(virConnectPtr conn, int ret; testDriverLock(driver); - ret = virDomainEventStateDeregisterID(conn, + ret = virObjectEventStateDeregisterID(conn, driver->domainEventState, callbackID); testDriverUnlock(driver); @@ -6029,9 +6029,9 @@ testConnectDomainEventDeregisterAny(virConnectPtr conn, /* driver must be locked before calling */ static void testDomainEventQueue(testConnPtr driver, - virDomainEventPtr event) + virObjectEventPtr event) { - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } static virDrvOpenStatus testSecretOpen(virConnectPtr conn, @@ -6151,7 +6151,7 @@ testDomainManagedSave(virDomainPtr dom, unsigned int flags) { testConnPtr privconn = dom->conn->privateData; virDomainObjPtr vm = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE | @@ -6641,7 +6641,7 @@ testDomainSnapshotCreateXML(virDomainPtr domain, virDomainSnapshotDefPtr def = NULL; virDomainSnapshotObjPtr snap = NULL; virDomainSnapshotPtr snapshot = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; char *xml = NULL; bool update_current = true; bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE; @@ -6890,8 +6890,8 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, testConnPtr privconn = snapshot->domain->conn->privateData; virDomainObjPtr vm = NULL; virDomainSnapshotObjPtr snap = NULL; - virDomainEventPtr event = NULL; - virDomainEventPtr event2 = NULL; + virObjectEventPtr event = NULL; + virObjectEventPtr event2 = NULL; virDomainDefPtr config = NULL; int ret = -1; @@ -7035,7 +7035,7 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, } /* else transition 6 and 9 use event as-is */ } else { /* Transitions 2, 5, 8 */ - virDomainEventFree(event); + virObjectEventFree(event); event = NULL; if (was_stopped) { @@ -7089,7 +7089,7 @@ cleanup: if (event2) testDomainEventQueue(privconn, event2); } else { - virDomainEventFree(event2); + virObjectEventFree(event2); } virObjectUnlock(vm); testDriverUnlock(privconn); diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h index 7f7ea05..c23a177 100644 --- a/src/uml/uml_conf.h +++ b/src/uml/uml_conf.h @@ -66,7 +66,7 @@ struct uml_driver { virDomainXMLOptionPtr xmlopt; /* Event handling */ - virDomainEventStatePtr domainEventState; + virObjectEventStatePtr domainEventState; /* Mapping of 'char *uuidstr' -> virConnectPtr * of guests which will be automatically killed diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 9ac896a..382a670 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -128,7 +128,7 @@ static int umlOpenMonitor(struct uml_driver *driver, static int umlReadPidFile(struct uml_driver *driver, virDomainObjPtr vm); static void umlDomainEventQueue(struct uml_driver *driver, - virDomainEventPtr event); + virObjectEventPtr event); static int umlStartVMDaemon(virConnectPtr conn, struct uml_driver *driver, @@ -194,7 +194,7 @@ umlAutostartDomain(virDomainObjPtr vm, VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, err ? err->message : _("unknown error")); } else { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_BOOTED); @@ -301,7 +301,7 @@ umlInotifyEvent(int watch, char *tmp, *name; struct uml_driver *driver = data; virDomainObjPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; umlDriverLock(driver); if (watch != driver->inotifyWatch) @@ -475,7 +475,7 @@ umlStateInitialize(bool privileged, if (!(uml_driver->domains = virDomainObjListNew())) goto error; - uml_driver->domainEventState = virDomainEventStateNew(); + uml_driver->domainEventState = virObjectEventStateNew(); if (!uml_driver->domainEventState) goto error; @@ -604,7 +604,7 @@ static void umlNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque) struct uml_driver *driver = opaque; if (newVM) { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED, VIR_DOMAIN_EVENT_DEFINED_ADDED); @@ -677,7 +677,7 @@ umlStateCleanup(void) { virObjectUnref(uml_driver->domains); - virDomainEventStateFree(uml_driver->domainEventState); + virObjectEventStateFree(uml_driver->domainEventState); VIR_FREE(uml_driver->logDir); VIR_FREE(uml_driver->configDir); @@ -716,7 +716,7 @@ static void umlProcessAutoDestroyDom(void *payload, const char *uuidstr = name; unsigned char uuid[VIR_UUID_BUFLEN]; virDomainObjPtr dom; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn); @@ -1571,7 +1571,7 @@ static virDomainPtr umlDomainCreateXML(virConnectPtr conn, const char *xml, virDomainDefPtr def; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL); @@ -1667,7 +1667,7 @@ umlDomainDestroyFlags(virDomainPtr dom, { struct uml_driver *driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -1993,7 +1993,7 @@ static int umlConnectNumOfDefinedDomains(virConnectPtr conn) { static int umlDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) { struct uml_driver *driver = dom->conn->privateData; virDomainObjPtr vm; - virDomainEventPtr event = NULL; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1); @@ -2680,7 +2680,7 @@ umlConnectDomainEventDeregisterAny(virConnectPtr conn, return -1; umlDriverLock(driver); - ret = virDomainEventStateDeregisterID(conn, + ret = virObjectEventStateDeregisterID(conn, driver->domainEventState, callbackID); umlDriverUnlock(driver); @@ -2691,9 +2691,9 @@ umlConnectDomainEventDeregisterAny(virConnectPtr conn, /* driver must be locked before calling */ static void umlDomainEventQueue(struct uml_driver *driver, - virDomainEventPtr event) + virObjectEventPtr event) { - virDomainEventStateQueue(driver->domainEventState, event); + virObjectEventStateQueue(driver->domainEventState, event); } static int umlConnectListAllDomains(virConnectPtr conn, diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3807a6d..b7c63b3 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -211,7 +211,7 @@ typedef struct { #else /* !(VBOX_API_VERSION == 2002) */ /* Async event handling */ - virDomainEventStatePtr domainEvents; + virObjectEventStatePtr domainEvents; int fdWatch; # if VBOX_API_VERSION <= 3002 @@ -988,7 +988,7 @@ static void vboxUninitialize(vboxGlobalData *data) { #if VBOX_API_VERSION == 2002 /* No domainEventCallbacks in 2.2.* version */ #else /* !(VBOX_API_VERSION == 2002) */ - virDomainEventStateFree(data->domainEvents); + virObjectEventStateFree(data->domainEvents); #endif /* !(VBOX_API_VERSION == 2002) */ VIR_FREE(data); } @@ -1053,7 +1053,7 @@ static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, #else /* !(VBOX_API_VERSION == 2002) */ - if (!(data->domainEvents = virDomainEventStateNew())) { + if (!(data->domainEvents = virObjectEventStateNew())) { vboxUninitialize(data); return VIR_DRV_OPEN_ERROR; } @@ -6878,7 +6878,7 @@ vboxCallbackOnMachineStateChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED, dom = vboxDomainLookupByUUID(g_pVBoxGlobalData->conn, uuid); if (dom) { - virDomainEventPtr ev; + virObjectEventPtr ev; if (state == MachineState_Starting) { event = VIR_DOMAIN_EVENT_STARTED; @@ -6912,7 +6912,7 @@ vboxCallbackOnMachineStateChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED, ev = virDomainEventNewFromDom(dom, event, detail); if (ev) - virDomainEventStateQueue(g_pVBoxGlobalData->domainEvents, ev); + virObjectEventStateQueue(g_pVBoxGlobalData->domainEvents, ev); } } @@ -6997,7 +6997,7 @@ vboxCallbackOnMachineRegistered(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED, dom = vboxDomainLookupByUUID(g_pVBoxGlobalData->conn, uuid); if (dom) { - virDomainEventPtr ev; + virObjectEventPtr ev; /* CURRENT LIMITATION: we never get the VIR_DOMAIN_EVENT_UNDEFINED * event because the when the machine is de-registered the call @@ -7016,7 +7016,7 @@ vboxCallbackOnMachineRegistered(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED, ev = virDomainEventNewFromDom(dom, event, detail); if (ev) - virDomainEventStateQueue(g_pVBoxGlobalData->domainEvents, ev); + virObjectEventStateQueue(g_pVBoxGlobalData->domainEvents, ev); } } @@ -7241,7 +7241,7 @@ static int vboxConnectDomainEventRegister(virConnectPtr conn, ret = virDomainEventStateRegister(conn, data->domainEvents, callback, opaque, freecb); - VIR_DEBUG("virDomainEventStateRegister (ret = %d) (conn: %p, " + VIR_DEBUG("virObjectEventStateRegister (ret = %d) (conn: %p, " "callback: %p, opaque: %p, " "freecb: %p)", ret, conn, callback, opaque, freecb); @@ -7335,7 +7335,7 @@ static int vboxConnectDomainEventRegisterAny(virConnectPtr conn, dom, eventID, callback, opaque, freecb, &ret) < 0) ret = -1; - VIR_DEBUG("virDomainEventStateRegisterID (ret = %d) (conn: %p, " + VIR_DEBUG("virObjectEventStateRegisterID (ret = %d) (conn: %p, " "callback: %p, opaque: %p, " "freecb: %p)", ret, conn, callback, opaque, freecb); @@ -7364,7 +7364,7 @@ static int vboxConnectDomainEventDeregisterAny(virConnectPtr conn, */ vboxDriverLock(data); - cnt = virDomainEventStateDeregisterID(conn, data->domainEvents, + cnt = virObjectEventStateDeregisterID(conn, data->domainEvents, callbackID); if (data->vboxCallback && cnt == 0) { diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9ba1b10..4103dc9 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -453,7 +453,7 @@ xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int f return VIR_DRV_OPEN_ERROR; } - if (!(priv->domainEvents = virDomainEventStateNew())) { + if (!(priv->domainEvents = virObjectEventStateNew())) { virMutexDestroy(&priv->lock); VIR_FREE(priv); return VIR_DRV_OPEN_ERROR; @@ -551,7 +551,7 @@ xenUnifiedConnectClose(virConnectPtr conn) virObjectUnref(priv->caps); virObjectUnref(priv->xmlopt); - virDomainEventStateFree(priv->domainEvents); + virObjectEventStateFree(priv->domainEvents); #if WITH_XEN_INOTIFY if (priv->opened[XEN_UNIFIED_INOTIFY_OFFSET]) @@ -2409,7 +2409,7 @@ xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn, return -1; } - ret = virDomainEventStateDeregisterID(conn, + ret = virObjectEventStateDeregisterID(conn, priv->domainEvents, callbackID); @@ -2946,12 +2946,12 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list, * */ void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv, - virDomainEventPtr event) + virObjectEventPtr event) { if (!priv) return; - virDomainEventStateQueue(priv->domainEvents, event); + virObjectEventStateQueue(priv->domainEvents, event); } void xenUnifiedLock(xenUnifiedPrivatePtr priv) diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h index a363161..b8c1c27 100644 --- a/src/xen/xen_driver.h +++ b/src/xen/xen_driver.h @@ -159,7 +159,7 @@ struct _xenUnifiedPrivate { int nbNodeCells; int nbNodeCpus; - virDomainEventStatePtr domainEvents; + virObjectEventStatePtr domainEvents; /* Location of config files, either /etc * or /var/lib/xen */ @@ -199,7 +199,7 @@ int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info, int id, char *name, unsigned char *uuid); void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, - virDomainEventPtr event); + virObjectEventPtr event); unsigned long xenUnifiedVersion(void); int xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type); diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 755be8f..b67178e 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -135,13 +135,13 @@ xenInotifyDomainLookup(virConnectPtr conn, return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid); } -static virDomainEventPtr +static virObjectEventPtr xenInotifyDomainEventFromFile(virConnectPtr conn, const char *filename, int type, int detail) { - virDomainEventPtr event; + virObjectEventPtr event; char *name = NULL; unsigned char uuid[VIR_UUID_BUFLEN]; @@ -290,7 +290,7 @@ reread: priv->configDir, name); if (e->mask & (IN_DELETE | IN_MOVED_FROM)) { - virDomainEventPtr event = + virObjectEventPtr event = xenInotifyDomainEventFromFile(conn, fname, VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); @@ -306,7 +306,7 @@ reread: goto cleanup; } } else if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) { - virDomainEventPtr event; + virObjectEventPtr event; if (xenInotifyAddDomainConfigInfo(conn, fname) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config cache")); diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index 4368f85..e66b6ad 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -835,7 +835,7 @@ retry: } if (!found) { - virDomainEventPtr event; + virObjectEventPtr event; char *name; unsigned char uuid[VIR_UUID_BUFLEN]; @@ -918,7 +918,7 @@ retry: } if (!found) { - virDomainEventPtr event = + virObjectEventPtr event = virDomainEventNew(-1, priv->activeDomainList->doms[j]->name, priv->activeDomainList->doms[j]->uuid, diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 961dfc6..8036adc 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -344,7 +344,7 @@ mymain(void) if (VIR_STRDUP_QUIET(driver.config->spicePassword, "123456") < 0) return EXIT_FAILURE; - if (!(driver.domainEventState = virDomainEventStateNew())) + if (!(driver.domainEventState = virObjectEventStateNew())) return EXIT_FAILURE; driver.lockManager = virLockManagerPluginNew("nop", "qemu", -- 1.8.4.2

On 11/19/2013 10:43 AM, Cédric Bosdonnat wrote:
The idea behind this commit is to make use of the Domain event mechanism for other events like network ones. This introduces some renaming from virDomainEvent* to virOjbectEvent*. ---
diff --git a/src/Makefile.am b/src/Makefile.am index ad39b74..8507b55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -241,6 +241,10 @@ DOMAIN_CONF_SOURCES = \ conf/domain_nwfilter.c conf/domain_nwfilter.h \ conf/snapshot_conf.c conf/snapshot_conf.h
+OBJECT_EVENT_SOURCES = \ + conf/object_event.h conf/object_event.c \ + conf/objec_event_private.h +
I didn't fully review this patch, but I did notice the typo here ('objec' vs 'object'). Make sure to run 'make distcheck' before resubmitting, I assume it would have caught this. - Cole

On Tue, Nov 19, 2013 at 04:43:13PM +0100, Cédric Bosdonnat wrote:
The idea behind this commit is to make use of the Domain event mechanism for other events like network ones. This introduces some renaming from virDomainEvent* to virOjbectEvent*.
[snip]
-struct _virDomainMeta { - int id; - char *name; - unsigned char uuid[VIR_UUID_BUFLEN]; -}; -typedef struct _virDomainMeta virDomainMeta; -typedef virDomainMeta *virDomainMetaPtr; - -struct _virDomainEventCallbackList { - unsigned int nextID; - unsigned int count; - virDomainEventCallbackPtr *callbacks; -}; - -struct _virDomainEventQueue { - unsigned int count; - virDomainEventPtr *events; -}; - -struct _virDomainEventState { - /* The list of domain event callbacks */ - virDomainEventCallbackListPtr callbacks; - /* The queue of domain events */ - virDomainEventQueuePtr queue; - /* Timer for flushing events queue */ - int timer; - /* Flag if we're in process of dispatching */ - bool isDispatching; - virMutex lock; -}; - -struct _virDomainEventCallback { - int callbackID; - int eventID; - virConnectPtr conn; - virDomainMetaPtr dom; - virConnectDomainEventGenericCallback cb; - void *opaque; - virFreeCallback freecb; - int deleted; -}; - -struct _virDomainEvent { - int eventID; - - virDomainMeta dom; - - union { - struct { - int type; - int detail; - } lifecycle; - struct { - long long offset; - } rtcChange; - struct { - int action; - } watchdog; - struct { - char *srcPath; - char *devAlias; - int action; - char *reason; - } ioError; - struct { - int phase; - virDomainEventGraphicsAddressPtr local; - virDomainEventGraphicsAddressPtr remote; - char *authScheme; - virDomainEventGraphicsSubjectPtr subject; - } graphics; - struct { - char *path; - int type; - int status; - } blockJob; - struct { - char *oldSrcPath; - char *newSrcPath; - char *devAlias; - int reason; - } diskChange; - struct { - char *devAlias; - int reason; - } trayChange; - struct { - /* In unit of 1024 bytes */ - unsigned long long actual; - } balloonChange; - struct { - char *devAlias; - } deviceRemoved; - } data; -};
One of the things that I think was very sub-optimal about our design originally was this approach of using huge unions for the event specific data. This only gets worse because we now also need unions for the virDomainMeta structure too. Since we originally designed this events code, we have gained the ability to have a simple object hierchies. As such I think I'd be inclined to make use of this to make the code a bit more modular, which may also help us avoid some of this bulk renaming you had todo. I'd say we go for a base class of virObjectEvent which just contains a unique integer event ID value. We then have a virDomainEvent which inherits from this and adds the virDomainMeta identity information Finally we can have subclasses for each event type eg virDomainEventGraphics, virDomainEventLifecycle and so on, which contain the event specific data. The way you've split the methods between domain_event.h and object_event.h makes sense here. To make patch easier to review though, I'd suggest that you have one patch which only renames the methods: s/virDomainEventState/virObjectEventState/ then another patch which replaces the union approach with a virObject subclass based approach, again all in domain_conf.h. Then finally move the bits named virObjectEventXXXX into the new object_event.h file. The key idea being to just keep code movement separate from code renaming. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Network events are now supported by the bridge and test drivers. To distinguish the network event IDs from the domain ones, the event IDs are prefixed with namespace bits. So any event id follows this rule: VIR_EVENT_NAMESPACE_XXX << 8 & EVENT_ID. With the namespace of domains being 0, compatibility is kept for previous client code. To use the new network events API, see the virConnectNetworkEvent*Any functions. At the moment, the network events report about network definition, undefinition, start and stop. Other events may be provided later. --- .gitignore | 1 + daemon/libvirtd.h | 1 + daemon/remote.c | 175 +++++++++++++++++++++++--- include/libvirt/libvirt.h.in | 77 ++++++++++++ python/generator.py | 2 + python/libvirt-override-virConnect.py | 34 +++++ python/libvirt-override.c | 150 ++++++++++++++++++++++ src/conf/object_event.c | 92 +++++++++++++- src/conf/object_event.h | 21 ++++ src/conf/object_event_private.h | 7 ++ src/driver.h | 14 +++ src/libvirt.c | 133 ++++++++++++++++++++ src/libvirt_private.syms | 3 + src/libvirt_public.syms | 6 + src/network/bridge_driver.c | 91 +++++++++++++- src/network/bridge_driver_platform.h | 3 + src/remote/remote_driver.c | 123 ++++++++++++++++++ src/remote/remote_protocol.x | 46 ++++++- src/test/test_driver.c | 116 +++++++++++++---- tests/Makefile.am | 7 ++ tests/objecteventtest.c | 228 ++++++++++++++++++++++++++++++++++ 21 files changed, 1288 insertions(+), 42 deletions(-) create mode 100644 tests/objecteventtest.c diff --git a/.gitignore b/.gitignore index 05be8a7..fcf5d1f 100644 --- a/.gitignore +++ b/.gitignore @@ -174,6 +174,7 @@ /tests/object-locking /tests/object-locking-files.txt /tests/object-locking.cm[ix] +/tests/objecteventtest /tests/openvzutilstest /tests/qemuagenttest /tests/qemuargv2xmltest diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index d0afdc8..47f2589 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -50,6 +50,7 @@ struct daemonClientPrivate { virMutex lock; int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST]; + int networkEventCallbackID[VIR_NETWORK_EVENT_ID_LAST]; # if WITH_SASL virNetSASLSessionPtr sasl; diff --git a/daemon/remote.c b/daemon/remote.c index decaecc..6281d08 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -108,7 +108,7 @@ remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors, /* Prototypes */ static void -remoteDispatchDomainEventSend(virNetServerClientPtr client, +remoteDispatchObjectEventSend(virNetServerClientPtr client, virNetServerProgramPtr program, int procnr, xdrproc_t proc, @@ -134,7 +134,7 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, data.event = event; data.detail = detail; - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE, (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data); @@ -157,7 +157,7 @@ static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_REBOOT, (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data); @@ -183,7 +183,7 @@ static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); data.offset = offset; - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data); @@ -209,7 +209,7 @@ static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_WATCHDOG, (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data); @@ -240,7 +240,7 @@ static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); data.action = action; - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); @@ -279,7 +279,7 @@ static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUS make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON, (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data); @@ -342,7 +342,7 @@ static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, } make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_GRAPHICS, (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data); @@ -388,7 +388,7 @@ static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, data.status = status; make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB, (xdrproc_t)xdr_remote_domain_event_block_job_msg, &data); @@ -415,7 +415,7 @@ static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSE memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR, (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data); @@ -461,7 +461,7 @@ static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE, (xdrproc_t)xdr_remote_domain_event_disk_change_msg, &data); @@ -497,7 +497,7 @@ static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE, (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data); @@ -520,7 +520,7 @@ static int remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP, (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg, &data); @@ -543,7 +543,7 @@ static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND, (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg, &data); @@ -569,7 +569,7 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); data.actual = actual; - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE, (xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data); @@ -593,7 +593,7 @@ static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUS memset(&data, 0, sizeof(data)); make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK, (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg, &data); @@ -623,7 +623,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, make_nonnull_domain(&data.dom, dom); - remoteDispatchDomainEventSend(client, remoteProgram, + remoteDispatchObjectEventSend(client, remoteProgram, REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, (xdrproc_t)xdr_remote_domain_event_device_removed_msg, &data); @@ -653,6 +653,37 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); +static int remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net, + int event, + void *opaque) +{ + virNetServerClientPtr client = opaque; + remote_network_event_lifecycle_msg data; + + if (!client) + return -1; + + VIR_DEBUG("Relaying network lifecycle event %d", event); + + /* build return data */ + memset(&data, 0, sizeof(data)); + make_nonnull_network(&data.net, net); + data.event = event; + + remoteDispatchObjectEventSend(client, remoteProgram, + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE, + (xdrproc_t)xdr_remote_network_event_lifecycle_msg, &data); + + return 0; +} + +static virConnectNetworkEventGenericCallback networkEventCallbacks[] = { + VIR_NETWORK_EVENT_CALLBACK(remoteRelayNetworkEventLifecycle), +}; + +verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST); + /* * You must hold lock for at least the client * We don't free stuff here, merely disconnect the client's @@ -680,6 +711,15 @@ void remoteClientFreeFunc(void *data) priv->domainEventCallbackID[i] = -1; } + for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++) { + if (priv->networkEventCallbackID[i] != -1) { + VIR_DEBUG("Deregistering to relay remote events %zu", i); + virConnectNetworkEventDeregisterAny(priv->conn, + priv->networkEventCallbackID[i]); + } + priv->networkEventCallbackID[i] = -1; + } + virConnectClose(priv->conn); virIdentitySetCurrent(NULL); @@ -716,6 +756,9 @@ void *remoteClientInitHook(virNetServerClientPtr client, for (i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i++) priv->domainEventCallbackID[i] = -1; + for (i = 0; i < VIR_NETWORK_EVENT_ID_LAST; i++) + priv->networkEventCallbackID[i] = -1; + virNetServerClientSetCloseHook(client, remoteClientCloseFunc); return priv; } @@ -3158,7 +3201,7 @@ cleanup: } static void -remoteDispatchDomainEventSend(virNetServerClientPtr client, +remoteDispatchObjectEventSend(virNetServerClientPtr client, virNetServerProgramPtr program, int procnr, xdrproc_t proc, @@ -5216,6 +5259,102 @@ cleanup: } +static int +remoteDispatchConnectNetworkEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + remote_connect_network_event_register_any_args *args, + remote_connect_network_event_register_any_ret *ret ATTRIBUTE_UNUSED) +{ + int callbackID; + int rv = -1; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + virMutexLock(&priv->lock); + + if ((args->eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST || + ((args->eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); + goto cleanup; + } + + if (priv->networkEventCallbackID[args->eventID & 0xFF] != -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d already registered"), args->eventID); + goto cleanup; + } + + if ((callbackID = virConnectNetworkEventRegisterAny(priv->conn, + NULL, + args->eventID, + networkEventCallbacks[args->eventID & 0xFF], + client, NULL)) < 0) + goto cleanup; + + priv->networkEventCallbackID[args->eventID & 0xFF] = callbackID; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virMutexUnlock(&priv->lock); + return rv; +} + + +static int +remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED, + remote_connect_network_event_deregister_any_args *args, + remote_connect_network_event_deregister_any_ret *ret ATTRIBUTE_UNUSED) +{ + int callbackID = -1; + int rv = -1; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + virMutexLock(&priv->lock); + + if ((args->eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST || + ((args->eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); + goto cleanup; + } + + callbackID = priv->networkEventCallbackID[args->eventID & 0xFF]; + if (callbackID < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("network event %d not registered"), args->eventID); + goto cleanup; + } + + if (virConnectNetworkEventDeregisterAny(priv->conn, callbackID) < 0) + goto cleanup; + + priv->networkEventCallbackID[args->eventID & 0xFF] = -1; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virMutexUnlock(&priv->lock); + return rv; +} + /*----- Helpers. -----*/ diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index b13118d..4e7f651 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -4964,6 +4964,7 @@ typedef enum { */ typedef enum { VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */ + VIR_EVENT_NAMESPACE_NETWORK = 1, } virEventNamespaceID; @@ -4977,7 +4978,83 @@ int virConnectDomainEventRegisterAny(virConnectPtr conn, int virConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID); +/** + * virNetworkEventLifecycleType: + * + * a virNetworkEventLifecycleType is emitted during network lifecycle events + */ +typedef enum { + VIR_NETWORK_EVENT_DEFINED = 0, + VIR_NETWORK_EVENT_UNDEFINED = 1, + VIR_NETWORK_EVENT_STARTED = 2, + VIR_NETWORK_EVENT_STOPPED = 3, + +#ifdef VIR_ENUM_SENTINELS + VIR_NETWORK_EVENT_LAST +#endif +} virNetworkEventLifecycleType; + +/** + * virConnectNetworkEventLifecycleCallback: + * @conn: connection object + * @net: network on which the event occurred + * @event: The specific virNetworkEventLifeCycleType which occurred + * @opaque: application specified data + * + * This callback occurs when the network is started or stopped. + * + * The callback signature to use when registering for an event of type + * VIR_NETWORK_EVENT_ID_LIFECYCLE with virConnectNetworkEventRegisterAny() + */ +typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn, + virNetworkPtr net, + int event, + void *opaque); + +/** + * VIR_NETWORK_EVENT_CALLBACK: + * + * Used to cast the event specific callback into the generic one + * for use for virNetworkEventRegister + */ +#define VIR_NETWORK_EVENT_CALLBACK(cb) ((virConnectNetworkEventGenericCallback)(cb)) + +typedef enum { + VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback */ + +#ifdef VIR_ENUM_SENTINELS + VIR_NETWORK_EVENT_ID_LAST + /* + * NB: this enum value will increase over time as new events are + * added to the libvirt API. It reflects the last event ID supported + * by this version of the libvirt API. + */ +#endif +} virNetworkEventID; + +/* + * virConnectNetworkEventGenericCallback: + * @conn: the connection pointer + * @net: the network pointer + * @opaque: application specified data + * + * A generic network event callback handler. Specific events usually + * have a customization with extra parameters + */ +typedef void (*virConnectNetworkEventGenericCallback)(virConnectPtr conn, + virNetworkPtr net, + void *opaque); + +/* Use VIR_NETWORK_EVENT_CALLBACK() to cast the 'cb' parameter */ +int virConnectNetworkEventRegisterAny(virConnectPtr conn, + virNetworkPtr net, /* Optional, to filter */ + int eventID, + virConnectNetworkEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); +int virConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID); /** * virNWFilter: diff --git a/python/generator.py b/python/generator.py index 87ecf5a..c2b3bad 100755 --- a/python/generator.py +++ b/python/generator.py @@ -482,6 +482,8 @@ skip_function = ( 'virConnectDomainEventDeregister', # overridden in virConnect.py 'virConnectDomainEventRegisterAny', # overridden in virConnect.py 'virConnectDomainEventDeregisterAny', # overridden in virConnect.py + 'virConnectNetworkEventRegisterAny', # overridden in virConnect.py + 'virConnectNetworkEventDeregisterAny', # overridden in virConnect.py 'virSaveLastError', # We have our own python error wrapper 'virFreeError', # Only needed if we use virSaveLastError 'virConnectListAllDomains', # overridden in virConnect.py diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py index 4ba3d30..65e8874 100644 --- a/python/libvirt-override-virConnect.py +++ b/python/libvirt-override-virConnect.py @@ -213,6 +213,40 @@ self.domainEventCallbackID[ret] = opaque return ret + def _dispatchNetworkEventLifecycleCallback(self, net, event, cbData): + """Dispatches events to python user network lifecycle event callbacks + """ + cb = cbData["cb"] + opaque = cbData["opaque"] + + cb(self, virNetwork(self, _obj=net), event, opaque) + return 0 + + def networkEventDeregisterAny(self, callbackID): + """Removes a Network Event Callback. De-registering for a + network callback will disable delivery of this event type """ + try: + ret = libvirtmod.virConnectNetworkEventDeregisterAny(self._o, callbackID) + if ret == -1: raise libvirtError ('virConnectNetworkEventDeregisterAny() failed', conn=self) + del self.networkEventCallbackID[callbackID] + except AttributeError: + pass + + def networkEventRegisterAny(self, net, eventID, cb, opaque): + """Adds a Network Event Callback. Registering for a network + callback will enable delivery of the events """ + if not hasattr(self, 'networkEventCallbackID'): + self.networkEventCallbackID = {} + cbData = { "cb": cb, "conn": self, "opaque": opaque } + if net is None: + ret = libvirtmod.virConnectNetworkEventRegisterAny(self._o, None, eventID, cbData) + else: + ret = libvirtmod.virConnectNetworkEventRegisterAny(self._o, net._o, eventID, cbData) + if ret == -1: + raise libvirtError ('virConnectNetworkEventRegisterAny() failed', conn=self) + self.networkEventCallbackID[ret] = opaque + return ret + def listAllDomains(self, flags=0): """List all domains and returns a list of domain objects""" ret = libvirtmod.virConnectListAllDomains(self._o, flags) diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 2e58bf9..26d8a0c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -6452,6 +6452,154 @@ libvirt_virConnectDomainEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self, return py_retval; } +static void +libvirt_virConnectNetworkEventFreeFunc(void *opaque) +{ + PyObject *pyobj_conn = (PyObject*)opaque; + LIBVIRT_ENSURE_THREAD_STATE; + Py_DECREF(pyobj_conn); + LIBVIRT_RELEASE_THREAD_STATE; +} + +static int +libvirt_virConnectNetworkEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net, + int event, + void *opaque) +{ + PyObject *pyobj_cbData = (PyObject*)opaque; + PyObject *pyobj_net; + PyObject *pyobj_ret; + PyObject *pyobj_conn; + PyObject *dictKey; + int ret = -1; + + LIBVIRT_ENSURE_THREAD_STATE; + + /* Create a python instance of this virNetworkPtr */ + virNetworkRef(net); + pyobj_net = libvirt_virNetworkPtrWrap(net); + Py_INCREF(pyobj_cbData); + + dictKey = libvirt_constcharPtrWrap("conn"); + pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); + Py_DECREF(dictKey); + + /* Call the Callback Dispatcher */ + pyobj_ret = PyObject_CallMethod(pyobj_conn, + (char*)"_dispatchNetworkEventLifecycleCallback", + (char*)"OiO", + pyobj_net, + event, + pyobj_cbData); + + Py_DECREF(pyobj_cbData); + Py_DECREF(pyobj_net); + + if (!pyobj_ret) { + DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); + PyErr_Print(); + } else { + Py_DECREF(pyobj_ret); + ret = 0; + } + + LIBVIRT_RELEASE_THREAD_STATE; + return ret; +} + +static PyObject * +libvirt_virConnectNetworkEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self, + PyObject * args) +{ + PyObject *py_retval; /* return value */ + PyObject *pyobj_conn; /* virConnectPtr */ + PyObject *pyobj_net; + PyObject *pyobj_cbData; /* hash of callback data */ + int eventID; + virConnectPtr conn; + int ret = 0; + virConnectNetworkEventGenericCallback cb = NULL; + virNetworkPtr net; + virNetworkEventID eventId = VIR_NETWORK_EVENT_ID_LAST; + + if (!PyArg_ParseTuple + (args, (char *) "OOiO:virConnectNetworkEventRegisterAny", + &pyobj_conn, &pyobj_net, &eventID, &pyobj_cbData)) { + DEBUG("%s failed parsing tuple\n", __FUNCTION__); + return VIR_PY_INT_FAIL; + } + + DEBUG("libvirt_virConnectNetworkEventRegister(%p %p %d %p) called\n", + pyobj_conn, pyobj_net, eventID, pyobj_cbData); + conn = PyvirConnect_Get(pyobj_conn); + if (pyobj_net == Py_None) + net = NULL; + else + net = PyvirNetwork_Get(pyobj_net); + + if ( ((eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) { + return VIR_PY_INT_FAIL; + } + + eventId = (virNetworkEventID) (eventID & 0xFF); + switch (eventId) { + case VIR_NETWORK_EVENT_ID_LIFECYCLE: + cb = VIR_NETWORK_EVENT_CALLBACK(libvirt_virConnectNetworkEventLifecycleCallback); + break; + + case VIR_NETWORK_EVENT_ID_LAST: + break; + } + + if (!cb) { + return VIR_PY_INT_FAIL; + } + + Py_INCREF(pyobj_cbData); + + LIBVIRT_BEGIN_ALLOW_THREADS; + ret = virConnectNetworkEventRegisterAny(conn, net, eventID, + cb, pyobj_cbData, + libvirt_virConnectNetworkEventFreeFunc); + LIBVIRT_END_ALLOW_THREADS; + + if (ret < 0) { + Py_DECREF(pyobj_cbData); + } + + py_retval = libvirt_intWrap(ret); + return py_retval; +} + +static PyObject * +libvirt_virConnectNetworkEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self, + PyObject * args) +{ + PyObject *py_retval; + PyObject *pyobj_conn; + int callbackID; + virConnectPtr conn; + int ret = 0; + + if (!PyArg_ParseTuple + (args, (char *) "Oi:virConnectNetworkEventDeregister", + &pyobj_conn, &callbackID)) + return NULL; + + DEBUG("libvirt_virConnectNetworkEventDeregister(%p) called\n", pyobj_conn); + + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + LIBVIRT_BEGIN_ALLOW_THREADS; + + ret = virConnectNetworkEventDeregisterAny(conn, callbackID); + + LIBVIRT_END_ALLOW_THREADS; + py_retval = libvirt_intWrap(ret); + return py_retval; +} + static void libvirt_virConnectCloseCallbackDispatch(virConnectPtr conn ATTRIBUTE_UNUSED, @@ -7237,6 +7385,8 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL}, + {(char *) "virConnectNetworkEventRegisterAny", libvirt_virConnectNetworkEventRegisterAny, METH_VARARGS, NULL}, + {(char *) "virConnectNetworkEventDeregisterAny", libvirt_virConnectNetworkEventDeregisterAny, METH_VARARGS, NULL}, {(char *) "virConnectRegisterCloseCallback", libvirt_virConnectRegisterCloseCallback, METH_VARARGS, NULL}, {(char *) "virConnectUnregisterCloseCallback", libvirt_virConnectUnregisterCloseCallback, METH_VARARGS, NULL}, {(char *) "virStreamEventAddCallback", libvirt_virStreamEventAddCallback, METH_VARARGS, NULL}, diff --git a/src/conf/object_event.c b/src/conf/object_event.c index 46eb677..59351f0 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -329,6 +329,11 @@ virDomainEventDataFree(virObjectEventPtr event) } } +static void +virNetworkEventDataFree(virObjectEventPtr event ATTRIBUTE_UNUSED) +{ +} + void virObjectEventFree(virObjectEventPtr event) { if (!event) @@ -340,6 +345,8 @@ void virObjectEventFree(virObjectEventPtr event) case VIR_EVENT_NAMESPACE_DOMAIN: virDomainEventDataFree(event); break; + case VIR_EVENT_NAMESPACE_NETWORK: + virNetworkEventDataFree(event); } VIR_FREE(event->dom.name); @@ -652,6 +659,35 @@ cleanup: virDomainFree(dom); } +static void +virNetworkEventDispatchDefaultFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectNetworkEventGenericCallback cb ATTRIBUTE_UNUSED, + void *cbopaque ATTRIBUTE_UNUSED, + void *opaque ATTRIBUTE_UNUSED) +{ + virNetworkPtr net = virGetNetwork(conn, event->dom.name, event->dom.uuid); + if (!net) + return; + + switch ((virNetworkEventID) (event->eventID &0xFF) ) { + case VIR_DOMAIN_EVENT_ID_LIFECYCLE: + ((virConnectNetworkEventLifecycleCallback)cb)(conn, net, + event->data.networkData.lifecycle.type, + cbopaque); + goto cleanup; + +#ifdef VIR_ENUM_SENTINELS + case VIR_NETWORK_EVENT_ID_LAST: + break; +#endif + } + VIR_WARN("Unexpected event ID %d", event->eventID); + +cleanup: + virNetworkFree(net); +} + static int virObjectEventDispatchMatchCallback(virObjectEventPtr event, virObjectEventCallbackPtr cb) @@ -761,6 +797,10 @@ virObjectEventStateDispatchFunc(virConnectPtr conn, virDomainEventDispatchDefaultFunc(conn, event, VIR_DOMAIN_EVENT_CALLBACK(cb), cbopaque, NULL); break; + case VIR_EVENT_NAMESPACE_NETWORK: + virNetworkEventDispatchDefaultFunc(conn, event, + VIR_NETWORK_EVENT_CALLBACK(cb), cbopaque, NULL); + break; } virObjectEventStateLock(state); } @@ -833,7 +873,7 @@ virObjectEventStateRegisterID(virConnectPtr conn, state, NULL)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not initialize domain event timer")); + _("could not initialize object event timer")); goto cleanup; } @@ -916,3 +956,53 @@ virObjectEventStateEventID(virConnectPtr conn, virObjectEventStateUnlock(state); return ret; } + + +/** + * virNetworkEventStateRegisterID: + * @conn: connection to associate with callback + * @state: object event state + * @net: network to filter on or NULL for all networks + * @eventID: ID of the event type to register for + * @cb: function to add to event + * @opaque: data blob to pass to callback + * @freecb: callback to free @opaque + * @callbackID: filled with callback ID + * + * Register the function @callbackID with connection @conn, + * from @state, for events of type @eventID. + * + * Returns: the number of callbacks now registered, or -1 on error + */ +int +virNetworkEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) +{ + if (net) + return virObjectEventStateRegisterID(conn, state, + net->uuid, net->name, 0, eventID, + cb, opaque, freecb, callbackID); + else + return virObjectEventStateRegisterID(conn, state, + NULL, NULL, 0, eventID, + cb, opaque, freecb, callbackID); +} + +virObjectEventPtr virNetworkEventLifecycleNew(const char *name, const unsigned char *uuid, int type) +{ + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + + VIR_NETWORK_EVENT_ID_LIFECYCLE; + virObjectEventPtr event = virObjectEventNewInternal(eventId, 0, name, uuid); + + if (event) { + event->data.networkData.lifecycle.type = type; + } + + return event; +} diff --git a/src/conf/object_event.h b/src/conf/object_event.h index bf5727f..886dab7 100644 --- a/src/conf/object_event.h +++ b/src/conf/object_event.h @@ -64,6 +64,8 @@ typedef void (*virConnectObjectEventGenericCallback)(virConnectPtr conn, void *obj, void *opaque); +#define VIR_OBJECT_EVENT_CALLBACK(cb) ((virConnectObjectEventGenericCallback)(cb)) + void virObjectEventStateQueue(virObjectEventStatePtr state, virObjectEventPtr event) @@ -90,4 +92,23 @@ virObjectEventStateEventID(virConnectPtr conn, int callbackID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +/* + * Network events + */ + +int +virNetworkEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID); + +virObjectEventPtr +virNetworkEventLifecycleNew(const char *name, + const unsigned char *uuid, + int type); + #endif diff --git a/src/conf/object_event_private.h b/src/conf/object_event_private.h index 8089155..684f800 100644 --- a/src/conf/object_event_private.h +++ b/src/conf/object_event_private.h @@ -70,6 +70,12 @@ struct _virObjectEventCallback { int deleted; }; +union virNetworkEventData { + struct { + int type; + } lifecycle; +}; + union virDomainEventData { struct { int type; @@ -125,6 +131,7 @@ struct _virObjectEvent { union { union virDomainEventData domainData; + union virNetworkEventData networkData; } data; }; diff --git a/src/driver.h b/src/driver.h index 8cd164a..3c7b536 100644 --- a/src/driver.h +++ b/src/driver.h @@ -1366,6 +1366,18 @@ typedef int virNetworkPtr **nets, unsigned int flags); +typedef int +(*virDrvConnectNetworkEventRegisterAny)(virConnectPtr conn, + virNetworkPtr dom, + int eventID, + virConnectNetworkEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); + +typedef int +(*virDrvConnectNetworkEventDeregisterAny)(virConnectPtr conn, + int callbackID); + typedef virNetworkPtr (*virDrvNetworkLookupByUUID)(virConnectPtr conn, const unsigned char *uuid); @@ -1444,6 +1456,8 @@ struct _virNetworkDriver { virDrvConnectNumOfDefinedNetworks connectNumOfDefinedNetworks; virDrvConnectListDefinedNetworks connectListDefinedNetworks; virDrvConnectListAllNetworks connectListAllNetworks; + virDrvConnectNetworkEventRegisterAny connectNetworkEventRegisterAny; + virDrvConnectNetworkEventDeregisterAny connectNetworkEventDeregisterAny; virDrvNetworkLookupByUUID networkLookupByUUID; virDrvNetworkLookupByName networkLookupByName; virDrvNetworkCreateXML networkCreateXML; diff --git a/src/libvirt.c b/src/libvirt.c index ae05300..b2e4edf 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -19171,6 +19171,139 @@ error: } /** + * virConnectNetworkEventRegisterAny: + * @conn: pointer to the connection + * @net: pointer to the network + * @eventID: the event type to receive + * @cb: callback to the function handling network events + * @opaque: opaque data to pass on to the callback + * @freecb: optional function to deallocate opaque when not used anymore + * + * Adds a callback to receive notifications of arbitrary network events + * occurring on a network. + * + * If net is NULL, then events will be monitored for any network. If net + * is non-NULL, then only the specific network will be monitored + * + * Most types of event have a callback providing a custom set of parameters + * for the event. When registering an event, it is thus necessary to use + * the VIR_NETWORK_EVENT_CALLBACK() macro to cast the supplied function pointer + * to match the signature of this method. + * + * The virNetworkPtr object handle passed into the callback upon delivery + * of an event is only valid for the duration of execution of the callback. + * If the callback wishes to keep the network object after the callback + * returns, it shall take a reference to it, by calling virNetworkRef. + * The reference can be released once the object is no longer required + * by calling virNetworkFree. + * + * The return value from this method is a positive integer identifier + * for the callback. To unregister a callback, this callback ID should + * be passed to the virNetworkEventUnregisterAny method + * + * Returns a callback identifier on success, -1 on failure + */ +int +virConnectNetworkEventRegisterAny(virConnectPtr conn, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback cb, + void *opaque, + virFreeCallback freecb) +{ + VIR_DEBUG("conn=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p", + conn, eventID, cb, opaque, freecb); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (net != NULL && + !(VIR_IS_CONNECTED_NETWORK(net) && net->conn == conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(conn); + return -1; + } + virCheckNonNullArgGoto(cb, error); + virCheckNonNegativeArgGoto(eventID, error); + if (((eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) { + virReportInvalidArg(eventID, + _("eventID in %s must be have network namespace flags %d"), + __FUNCTION__, VIR_EVENT_NAMESPACE_NETWORK << 8); + goto error; + } + +#ifdef VIR_ENUM_SENTINELS + if ((eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST) { + virReportInvalidArg(eventID, + _("eventID in %s must be less than %d"), + __FUNCTION__, VIR_NETWORK_EVENT_ID_LAST); + goto error; + } +#endif + + if ((conn->networkDriver) && (conn->networkDriver->connectNetworkEventRegisterAny)) { + int ret; + ret = conn->networkDriver->connectNetworkEventRegisterAny(conn, net, + eventID, cb, + opaque, + freecb); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + virDispatchError(conn); + return -1; +} + +/** + * virConnectNetworkEventDeregisterAny: + * @conn: pointer to the connection + * @callbackID: the callback identifier + * + * Removes an event callback. The callbackID parameter should be the + * vaule obtained from a previous virNetworkEventRegisterAny method. + * + * Returns 0 on success, -1 on failure + */ +int +virConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + virCheckNonNegativeArgGoto(callbackID, error); + + if ((conn->networkDriver) && + (conn->networkDriver->connectNetworkEventDeregisterAny)) { + int ret; + ret = conn->networkDriver->connectNetworkEventDeregisterAny(conn, + callbackID); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + virDispatchError(conn); + return -1; +} + +/** * virDomainManagedSave: * @dom: pointer to the domain * @flags: bitwise-OR of virDomainSaveRestoreFlags diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index dc3882b..9989d93 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -619,7 +619,10 @@ virNWFilterVarValueGetCardinality; virNWFilterVarValueGetNthValue; virNWFilterVarValueGetSimple; + # conf/object_event.h +virNetworkEventLifecycleNew; +virNetworkEventStateRegisterID; virObjectEventFree; virObjectEventStateDeregisterID; virObjectEventStateEventID; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index fe9b497..d940b2b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -639,4 +639,10 @@ LIBVIRT_1.1.3 { virConnectGetCPUModelNames; } LIBVIRT_1.1.1; +LIBVIRT_1.1.4 { + global: + virConnectNetworkEventRegisterAny; + virConnectNetworkEventDeregisterAny; +} LIBVIRT_1.1.3; + # .... define new API here using predicted next version number .... diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 4298576..de846ab 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -438,6 +438,8 @@ networkStateInitialize(bool privileged, networkReloadFirewallRules(driverState); networkRefreshDaemons(driverState); + driverState->networkEventState = virObjectEventStateNew(); + networkDriverUnlock(driverState); #ifdef HAVE_FIREWALLD @@ -532,6 +534,8 @@ networkStateCleanup(void) { networkDriverLock(driverState); + virObjectEventStateFree(driverState->networkEventState); + /* free inactive networks */ virNetworkObjListFree(&driverState->networks); @@ -2290,6 +2294,55 @@ cleanup: return ret; } +static int +networkConnectNetworkEventRegisterAny(virConnectPtr conn, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + virNetworkDriverStatePtr driver = conn->networkPrivateData; + int ret = -1; + + networkDriverLock(driver); + + if (virConnectNetworkEventRegisterAnyEnsureACL(conn) < 0) + goto cleanup; + + if (virNetworkEventStateRegisterID(conn, driver->networkEventState, + net, eventID, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, &ret) < 0) + ret = -1; + + networkDriverUnlock(driver); + +cleanup: + return ret; +} + +static int +networkConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + virNetworkDriverStatePtr driver = conn->networkPrivateData; + int ret = -1; + + if (virConnectNetworkEventDeregisterAnyEnsureACL(conn) < 0) + goto cleanup; + + + networkDriverLock(driver); + ret = virObjectEventStateDeregisterID(conn, + driver->networkEventState, + callbackID); + networkDriverUnlock(driver); + +cleanup: + return ret; +} + static int networkIsActive(virNetworkPtr net) { virNetworkObjPtr obj; @@ -2483,6 +2536,7 @@ static virNetworkPtr networkCreateXML(virConnectPtr conn, const char *xml) { virNetworkDefPtr def; virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2509,11 +2563,17 @@ static virNetworkPtr networkCreateXML(virConnectPtr conn, const char *xml) { goto cleanup; } + event = virNetworkEventLifecycleNew(network->def->name, + network->def->uuid, + VIR_NETWORK_EVENT_STARTED); + VIR_INFO("Creating network '%s'", network->def->name); ret = virGetNetwork(conn, network->def->name, network->def->uuid); cleanup: virNetworkDefFree(def); + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -2526,6 +2586,7 @@ static virNetworkPtr networkDefineXML(virConnectPtr conn, const char *xml) { bool freeDef = true; virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2565,12 +2626,17 @@ static virNetworkPtr networkDefineXML(virConnectPtr conn, const char *xml) { goto cleanup; } + event = virNetworkEventLifecycleNew(def->name, def->uuid, + VIR_NETWORK_EVENT_DEFINED); + VIR_INFO("Defining network '%s'", def->name); ret = virGetNetwork(conn, def->name, def->uuid); cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (freeDef) - virNetworkDefFree(def); + virNetworkDefFree(def); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -2583,6 +2649,7 @@ networkUndefine(virNetworkPtr net) { virNetworkObjPtr network; int ret = -1; bool active = false; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2610,6 +2677,10 @@ networkUndefine(virNetworkPtr net) { virNetworkDefFree(network->newDef); network->newDef = NULL; + event = virNetworkEventLifecycleNew(network->def->name, + network->def->uuid, + VIR_NETWORK_EVENT_UNDEFINED); + VIR_INFO("Undefining network '%s'", network->def->name); if (!active) { if (networkRemoveInactive(driver, network) < 0) { @@ -2622,6 +2693,8 @@ networkUndefine(virNetworkPtr net) { ret = 0; cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -2785,6 +2858,7 @@ static int networkCreate(virNetworkPtr net) { virNetworkDriverStatePtr driver = net->conn->networkPrivateData; virNetworkObjPtr network; int ret = -1; + virObjectEventPtr event = NULL; networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); @@ -2800,7 +2874,13 @@ static int networkCreate(virNetworkPtr net) { ret = networkStartNetwork(driver, network); + event = virNetworkEventLifecycleNew(network->def->name, + network->def->uuid, + VIR_NETWORK_EVENT_STARTED); + cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -2811,6 +2891,7 @@ static int networkDestroy(virNetworkPtr net) { virNetworkDriverStatePtr driver = net->conn->networkPrivateData; virNetworkObjPtr network; int ret = -1; + virObjectEventPtr event = NULL; networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); @@ -2833,6 +2914,10 @@ static int networkDestroy(virNetworkPtr net) { if ((ret = networkShutdownNetwork(driver, network)) < 0) goto cleanup; + event = virNetworkEventLifecycleNew(network->def->name, + network->def->uuid, + VIR_NETWORK_EVENT_STOPPED); + if (!network->persistent) { if (networkRemoveInactive(driver, network) < 0) { network = NULL; @@ -2843,6 +2928,8 @@ static int networkDestroy(virNetworkPtr net) { } cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -3001,6 +3088,8 @@ static virNetworkDriver networkDriver = { .connectNumOfDefinedNetworks = networkConnectNumOfDefinedNetworks, /* 0.2.0 */ .connectListDefinedNetworks = networkConnectListDefinedNetworks, /* 0.2.0 */ .connectListAllNetworks = networkConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventRegisterAny = networkConnectNetworkEventRegisterAny, /* 1.1.4 */ + .connectNetworkEventDeregisterAny = networkConnectNetworkEventDeregisterAny, /* 1.1.4 */ .networkLookupByUUID = networkLookupByUUID, /* 0.2.0 */ .networkLookupByName = networkLookupByName, /* 0.2.0 */ .networkCreateXML = networkCreateXML, /* 0.2.0 */ diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h index 289ab79..82d96f6 100644 --- a/src/network/bridge_driver_platform.h +++ b/src/network/bridge_driver_platform.h @@ -29,6 +29,7 @@ # include "virthread.h" # include "virdnsmasq.h" # include "network_conf.h" +# include "object_event.h" /* Main driver state */ struct _virNetworkDriverState { @@ -43,6 +44,8 @@ struct _virNetworkDriverState { char *dnsmasqStateDir; char *radvdStateDir; dnsmasqCapsPtr dnsmasqCaps; + + virObjectEventStatePtr networkEventState; }; typedef struct _virNetworkDriverState virNetworkDriverState; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 0074f46..dfeac4f 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -272,6 +272,10 @@ static void remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque); static virNetClientProgramEvent remoteDomainEvents[] = { { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, @@ -338,6 +342,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = { remoteDomainBuildEventDeviceRemoved, sizeof(remote_domain_event_device_removed_msg), (xdrproc_t)xdr_remote_domain_event_device_removed_msg }, + { REMOTE_PROC_NETWORK_EVENT_LIFECYCLE, + remoteNetworkBuildEventLifecycle, + sizeof(remote_network_event_lifecycle_msg), + (xdrproc_t)xdr_remote_network_event_lifecycle_msg }, }; enum virDrvOpenRemoteFlags { @@ -2898,6 +2906,99 @@ done: } static int +remoteConnectNetworkEventRegisterAny(virConnectPtr conn, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_connect_network_event_register_any_args args; + int callbackID; + int count; + + remoteDriverLock(priv); + + if ((count = virNetworkEventStateRegisterID(conn, + priv->domainEventState, + net, eventID, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, + &callbackID)) < 0) { + virReportError(VIR_ERR_RPC, "%s", _("adding cb to list")); + goto done; + } + + /* If this is the first callback for this eventID, we need to enable + * events on the server */ + if (count == 1) { + args.eventID = eventID; + + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY, + (xdrproc_t) xdr_remote_connect_network_event_register_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *)NULL) == -1) { + virObjectEventStateDeregisterID(conn, + priv->domainEventState, + callbackID); + goto done; + } + } + + rv = callbackID; + +done: + remoteDriverUnlock(priv); + return rv; +} + + +static int +remoteConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + struct private_data *priv = conn->privateData; + int rv = -1; + remote_connect_network_event_deregister_any_args args; + int eventID; + int count; + + remoteDriverLock(priv); + + if ((eventID = virObjectEventStateEventID(conn, + priv->domainEventState, + callbackID)) < 0) { + virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID); + goto done; + } + + if ((count = virObjectEventStateDeregisterID(conn, + priv->domainEventState, + callbackID)) < 0) { + virReportError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID); + goto done; + } + + /* If that was the last callback for this eventID, we need to disable + * events on the server */ + if (count == 0) { + args.eventID = callbackID; + + if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY, + (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + } + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteConnectListAllInterfaces(virConnectPtr conn, virInterfacePtr **ifaces, unsigned int flags) @@ -4788,6 +4889,26 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED remoteDomainEventQueue(priv, event); } +static void +remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + struct private_data *priv = conn->privateData; + remote_network_event_lifecycle_msg *msg = evdata; + virNetworkPtr net; + virObjectEventPtr event = NULL; + + net = get_nonnull_network(conn, msg->net); + if (!net) + return; + + event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event); + virNetworkFree(net); + + remoteDomainEventQueue(priv, event); +} static virDrvOpenStatus ATTRIBUTE_NONNULL(1) remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth, @@ -7024,6 +7145,8 @@ static virNetworkDriver network_driver = { .connectNumOfDefinedNetworks = remoteConnectNumOfDefinedNetworks, /* 0.3.0 */ .connectListDefinedNetworks = remoteConnectListDefinedNetworks, /* 0.3.0 */ .connectListAllNetworks = remoteConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventDeregisterAny = remoteConnectNetworkEventDeregisterAny, /* 1.1.4 */ + .connectNetworkEventRegisterAny = remoteConnectNetworkEventRegisterAny, /* 1.1.4 */ .networkLookupByUUID = remoteNetworkLookupByUUID, /* 0.3.0 */ .networkLookupByName = remoteNetworkLookupByName, /* 0.3.0 */ .networkCreateXML = remoteNetworkCreateXML, /* 0.3.0 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f942670..c3d544f 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2849,6 +2849,30 @@ struct remote_connect_get_cpu_model_names_ret { int ret; }; +struct remote_connect_network_event_register_any_args { + int eventID; +}; + +struct remote_connect_network_event_register_any_ret { + int cb_registered; +}; + +struct remote_connect_network_event_deregister_any_args { + int eventID; +}; + +struct remote_connect_network_event_deregister_any_ret { + int cb_registered; +}; + +struct remote_network_event_lifecycle_msg { + remote_nonnull_network net; + int event; + int detail; +}; + + + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -5018,5 +5042,25 @@ enum remote_procedure { * @generate: none * @acl: connect:read */ - REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312 + REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312, + + /** + * @generate: none + * @priority: high + * @acl: connect:read + */ + REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY = 313, + + /** + * @generate: none + * @priority: high + * @acl: connect:read + */ + REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY = 314, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_NETWORK_EVENT_LIFECYCLE = 315 }; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index f472494..4419bb3 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -121,7 +121,7 @@ static const virNodeInfo defaultNodeInfo = { static int testConnectClose(virConnectPtr conn); -static void testDomainEventQueue(testConnPtr driver, +static void testObjectEventQueue(testConnPtr driver, virObjectEventPtr event); @@ -1650,7 +1650,7 @@ cleanup: if (dom) virObjectUnlock(dom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); virDomainDefFree(def); testDriverUnlock(privconn); return ret; @@ -1781,7 +1781,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -1821,7 +1821,7 @@ cleanup: virObjectUnlock(privdom); if (event) { testDriverLock(privconn); - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); } return ret; @@ -1864,7 +1864,7 @@ cleanup: if (event) { testDriverLock(privconn); - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); } return ret; @@ -1911,7 +1911,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -1987,7 +1987,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -2159,7 +2159,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -2265,7 +2265,7 @@ cleanup: if (dom) virObjectUnlock(dom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -2335,7 +2335,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -2819,7 +2819,7 @@ cleanup: if (dom) virObjectUnlock(dom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -2955,7 +2955,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -3030,7 +3030,7 @@ cleanup: if (privdom) virObjectUnlock(privdom); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); return ret; } @@ -3529,6 +3529,7 @@ static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) { virNetworkDefPtr def; virNetworkObjPtr net = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; testDriverLock(privconn); if ((def = virNetworkDefParseString(xml)) == NULL) @@ -3539,10 +3540,15 @@ static virNetworkPtr testNetworkCreateXML(virConnectPtr conn, const char *xml) { def = NULL; net->active = 1; + event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid, + VIR_NETWORK_EVENT_STARTED); + ret = virGetNetwork(conn, net->def->name, net->def->uuid); cleanup: virNetworkDefFree(def); + if (event) + testObjectEventQueue(privconn, event); if (net) virNetworkObjUnlock(net); testDriverUnlock(privconn); @@ -3556,6 +3562,7 @@ virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml) virNetworkDefPtr def; virNetworkObjPtr net = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; testDriverLock(privconn); if ((def = virNetworkDefParseString(xml)) == NULL) @@ -3566,10 +3573,15 @@ virNetworkPtr testNetworkDefineXML(virConnectPtr conn, const char *xml) def = NULL; net->persistent = 1; + event = virNetworkEventLifecycleNew(net->def->name, net->def->uuid, + VIR_NETWORK_EVENT_DEFINED); + ret = virGetNetwork(conn, net->def->name, net->def->uuid); cleanup: virNetworkDefFree(def); + if (event) + testObjectEventQueue(privconn, event); if (net) virNetworkObjUnlock(net); testDriverUnlock(privconn); @@ -3580,6 +3592,7 @@ static int testNetworkUndefine(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; int ret = -1; + virObjectEventPtr event = NULL; testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, @@ -3596,12 +3609,18 @@ static int testNetworkUndefine(virNetworkPtr network) { goto cleanup; } + event = virNetworkEventLifecycleNew(network->name, network->uuid, + VIR_NETWORK_EVENT_UNDEFINED); + virNetworkRemoveInactive(&privconn->networks, privnet); + privnet = NULL; ret = 0; cleanup: + if (event) + testObjectEventQueue(privconn, event); if (privnet) virNetworkObjUnlock(privnet); testDriverUnlock(privconn); @@ -3658,7 +3677,8 @@ cleanup: static int testNetworkCreate(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; - virNetworkObjPtr privnet; + virNetworkObjPtr privnet = NULL; + virObjectEventPtr event = NULL; int ret = -1; testDriverLock(privconn); @@ -3678,9 +3698,13 @@ static int testNetworkCreate(virNetworkPtr network) { } privnet->active = 1; + event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid, + VIR_NETWORK_EVENT_STARTED); ret = 0; cleanup: + if (event) + testObjectEventQueue(privconn, event); if (privnet) virNetworkObjUnlock(privnet); return ret; @@ -3690,6 +3714,7 @@ static int testNetworkDestroy(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; int ret = -1; + virObjectEventPtr event = NULL; testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, @@ -3701,6 +3726,8 @@ static int testNetworkDestroy(virNetworkPtr network) { } privnet->active = 0; + event = virNetworkEventLifecycleNew(privnet->def->name, privnet->def->uuid, + VIR_NETWORK_EVENT_STOPPED); if (!privnet->persistent) { virNetworkRemoveInactive(&privconn->networks, privnet); @@ -3709,6 +3736,8 @@ static int testNetworkDestroy(virNetworkPtr network) { ret = 0; cleanup: + if (event) + testObjectEventQueue(privconn, event); if (privnet) virNetworkObjUnlock(privnet); testDriverUnlock(privconn); @@ -6027,8 +6056,51 @@ testConnectDomainEventDeregisterAny(virConnectPtr conn, } +static int +testConnectNetworkEventRegisterAny(virConnectPtr conn, + virNetworkPtr net, + int eventID, + virConnectNetworkEventGenericCallback callback, + void *opaque, + virFreeCallback freecb) +{ + testConnPtr driver = conn->privateData; + int ret; + + testDriverLock(driver); + if (net) + { + if (virObjectEventStateRegisterID(conn, + driver->domainEventState, + net->uuid, net->name, 0, eventID, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, &ret) < 0) + ret = -1; + } + else + { + if (virObjectEventStateRegisterID(conn, + driver->domainEventState, + NULL, NULL, 0, eventID, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, &ret) < 0) + ret = -1; + } + testDriverUnlock(driver); + + return ret; +} + +static int +testConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + return testConnectDomainEventDeregisterAny(conn, callbackID); +} + + /* driver must be locked before calling */ -static void testDomainEventQueue(testConnPtr driver, +static void testObjectEventQueue(testConnPtr driver, virObjectEventPtr event) { virObjectEventStateQueue(driver->domainEventState, event); @@ -6191,7 +6263,7 @@ cleanup: virObjectUnlock(vm); if (event) { testDriverLock(privconn); - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); } @@ -6743,7 +6815,7 @@ cleanup: } if (event) { testDriverLock(privconn); - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); testDriverUnlock(privconn); } virDomainSnapshotDefFree(def); @@ -6989,7 +7061,7 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT); if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); goto load; } @@ -7069,7 +7141,7 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0; if (event) - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT); @@ -7085,9 +7157,9 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ret = 0; cleanup: if (event) { - testDomainEventQueue(privconn, event); + testObjectEventQueue(privconn, event); if (event2) - testDomainEventQueue(privconn, event2); + testObjectEventQueue(privconn, event2); } else { virObjectEventFree(event2); } @@ -7205,6 +7277,8 @@ static virNetworkDriver testNetworkDriver = { .connectNumOfDefinedNetworks = testConnectNumOfDefinedNetworks, /* 0.3.2 */ .connectListDefinedNetworks = testConnectListDefinedNetworks, /* 0.3.2 */ .connectListAllNetworks = testConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.1.4 */ + .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.1.4 */ .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */ .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */ .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */ diff --git a/tests/Makefile.am b/tests/Makefile.am index e46d5f7..734ab50 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -300,6 +300,8 @@ EXTRA_DIST += \ $(NULL) endif ! WITH_LIBVIRTD +test_programs += objecteventtest + if WITH_SECDRIVER_APPARMOR test_scripts += virt-aa-helper-test else ! WITH_SECDRIVER_APPARMOR @@ -888,6 +890,11 @@ fdstreamtest_SOURCES = \ fdstreamtest.c testutils.h testutils.c fdstreamtest_LDADD = $(LDADDS) +objecteventtest_SOURCES = \ + objecteventtest.c \ + testutils.c testutils.h +objecteventtest_LDADD = $(LDADDS) + if WITH_LINUX fchosttest_SOURCES = \ fchosttest.c testutils.h testutils.c diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c new file mode 100644 index 0000000..af66155 --- /dev/null +++ b/tests/objecteventtest.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Cedric Bosdonnat <cbosdonnat@suse.com> + */ + +#include <config.h> + +#include "testutils.h" + +#include "virerror.h" +#include "virxml.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + + +static const char networkDef[] = +"<network>\n" +" <name>test</name>\n" +" <bridge name=\"virbr0\"/>\n" +" <forward/>\n" +" <ip address=\"192.168.122.1\" netmask=\"255.255.255.0\">\n" +" <dhcp>\n" +" <range start=\"192.168.122.2\" end=\"192.168.122.254\"/>\n" +" </dhcp>\n" +" </ip>\n" +"</network>\n"; + + +struct objecteventTest { + virConnectPtr conn; + virNetworkPtr net; +}; + +struct networkLifecycleEventCounter { + int startEvents; + int stopEvents; + int defineEvents; + int undefineEvents; +}; + +static void +networkLifecycleCb(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net ATTRIBUTE_UNUSED, + int event, + void* opaque) { + struct networkLifecycleEventCounter *counter = opaque; + + if (event == VIR_NETWORK_EVENT_STARTED) + counter->startEvents++; + else if (event == VIR_NETWORK_EVENT_STOPPED) + counter->stopEvents++; + else if (event == VIR_NETWORK_EVENT_DEFINED) + counter->defineEvents++; + else if (event == VIR_NETWORK_EVENT_UNDEFINED) + counter->undefineEvents++; +} + + +static int +testNetworkCreateXML(const void *data) +{ + const struct objecteventTest *test = data; + struct networkLifecycleEventCounter counter; + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + VIR_NETWORK_EVENT_ID_LIFECYCLE; + virNetworkPtr net; + int id; + int ret = 0; + + counter.startEvents = 0; + + id = virConnectNetworkEventRegisterAny(test->conn, NULL, eventId, + VIR_NETWORK_EVENT_CALLBACK(&networkLifecycleCb), + &counter, NULL); + net = virNetworkCreateXML(test->conn, networkDef); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.startEvents != 1) { + ret = -1; + goto cleanup; + } + +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + virNetworkDestroy(net); + + virNetworkFree(net); + + return ret; +} + +static int +testNetworkDefine(const void *data) +{ + const struct objecteventTest *test = data; + struct networkLifecycleEventCounter counter; + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + VIR_NETWORK_EVENT_ID_LIFECYCLE; + virNetworkPtr net; + int id; + int ret = 0; + + counter.defineEvents = 0; + counter.undefineEvents = 0; + + id = virConnectNetworkEventRegisterAny(test->conn, NULL, eventId, + VIR_NETWORK_EVENT_CALLBACK(&networkLifecycleCb), + &counter, NULL); + + /* Make sure the define event is triggered */ + net = virNetworkDefineXML(test->conn, networkDef); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.defineEvents != 1) { + ret = -1; + goto cleanup; + } + + /* Make sure the undefine event is triggered */ + virNetworkUndefine(net); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.undefineEvents != 1) { + ret = -1; + goto cleanup; + } + + +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + virNetworkFree(net); + + return ret; +} + +static int +testNetworkStartStopEvent(const void *data) +{ + const struct objecteventTest *test = data; + struct networkLifecycleEventCounter counter; + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + VIR_NETWORK_EVENT_ID_LIFECYCLE; + int id; + int ret = 0; + + counter.startEvents = 0; + + id = virConnectNetworkEventRegisterAny(test->conn, test->net, eventId, + VIR_NETWORK_EVENT_CALLBACK(&networkLifecycleCb), + &counter, NULL); + virNetworkCreate(test->net); + virNetworkDestroy(test->net); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.startEvents != 1 || counter.stopEvents != 1) { + ret = -1; + goto cleanup; + } + +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + + return ret; +} + +static int +mymain(void) +{ + struct objecteventTest test; + int ret = EXIT_SUCCESS; + + virEventRegisterDefaultImpl(); + + if (!(test.conn = virConnectOpen("test:///default"))) + return EXIT_FAILURE; + + /* Tests requiring the test network not to be set up*/ + if (virtTestRun("Network createXML start event ", testNetworkCreateXML, &test) < 0) + ret = EXIT_FAILURE; + if (virtTestRun("Network (un)define events", testNetworkDefine, &test) < 0) + ret = EXIT_FAILURE; + + /* Define a test network */ + test.net = virNetworkDefineXML(test.conn, networkDef); + + virtTestQuiesceLibvirtErrors(false); + + if (virtTestRun("Network start stop events ", testNetworkStartStopEvent, &test) < 0) + ret = EXIT_FAILURE; + + /* Undefine test network */ + virNetworkUndefine(test.net); + + virNetworkFree(test.net); + virConnectClose(test.conn); + + return ret; +} + +VIRT_TEST_MAIN(mymain) -- 1.8.4.2

On 11/19/2013 10:43 AM, Cédric Bosdonnat wrote:
These changes are all about bringing events for network object like the ones existing for domains. This feature is needed for virt-manager to refresh its UI when networks are started/destroyed/defined/undefined.
The first commit is a refactoring of the domain events internal functions to extract the reusable parts of them. The second commit adds network events based on those now-common event functions. The network events are implemented in the test and bridge network drivers ATM.
Cédric Bosdonnat (2): virDomainEvent refactoring to separate generic things from domain ones Added network events API and unit tests
Cool! This will certainly be useful for virt-manager (as you know since you submitted a patch there as well :) ). However to ease review it will help if you split these patches up into many smaller units. I'd recommend 2 series: the first will do the event refactor. try to put virObjectEvent find replace into its own patch with nothing else: that's a very large piece of the change, but if it's in a standalone patch it will be trivial to review for correctness. I'd also add tests/objecteventtest.c in this step as well, but add tests for the pre-existing domain events: that will give devs more confidence that your refactoring doesn't introduce any regressions, and hopefully it should be easy to adapt your network test cases to work with domain events as well. next series is the new APIs. take a look at docs/api_extension/*.patch for a rough guideline of how to split up this series. It doesn't directly apply here but it should give you some ideas. Add the network objecteventtest.c test cases at the end of this series. To be clear, you don't need to wait for series 1 to be reviewed committed before submitting series 2 as well. Thanks, Cole
.gitignore | 2 + daemon/libvirtd.h | 1 + daemon/remote.c | 175 +++- include/libvirt/libvirt.h.in | 85 ++ python/generator.py | 2 + python/libvirt-override-virConnect.py | 34 + python/libvirt-override.c | 150 ++++ src/Makefile.am | 6 + src/conf/domain_event.c | 1431 ++++++--------------------------- src/conf/domain_event.h | 134 ++- src/conf/object_event.c | 1008 +++++++++++++++++++++++ src/conf/object_event.h | 114 +++ src/conf/object_event_private.h | 167 ++++ src/driver.h | 14 + src/libvirt.c | 133 +++ src/libvirt_private.syms | 18 +- src/libvirt_public.syms | 6 + src/libxl/libxl_conf.h | 2 +- src/libxl/libxl_driver.c | 28 +- src/lxc/lxc_conf.h | 2 +- src/lxc/lxc_driver.c | 38 +- src/lxc/lxc_process.c | 12 +- src/network/bridge_driver.c | 91 ++- src/network/bridge_driver_platform.h | 3 + src/parallels/parallels_utils.h | 2 +- src/qemu/qemu_conf.h | 2 +- src/qemu/qemu_domain.c | 6 +- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_driver.c | 50 +- src/qemu/qemu_hotplug.c | 10 +- src/qemu/qemu_migration.c | 12 +- src/qemu/qemu_process.c | 48 +- src/remote/remote_driver.c | 173 +++- src/remote/remote_protocol.x | 46 +- src/test/test_driver.c | 166 ++-- src/uml/uml_conf.h | 2 +- src/uml/uml_driver.c | 26 +- src/vbox/vbox_tmpl.c | 20 +- src/xen/xen_driver.c | 10 +- src/xen/xen_driver.h | 4 +- src/xen/xen_inotify.c | 8 +- src/xen/xs_internal.c | 4 +- tests/Makefile.am | 7 + tests/objecteventtest.c | 228 ++++++ tests/qemuhotplugtest.c | 2 +- 45 files changed, 2974 insertions(+), 1510 deletions(-) create mode 100644 src/conf/object_event.c create mode 100644 src/conf/object_event.h create mode 100644 src/conf/object_event_private.h create mode 100644 tests/objecteventtest.c

On Tue, Nov 19, 2013 at 04:43:12PM +0100, Cédric Bosdonnat wrote:
These changes are all about bringing events for network object like the ones existing for domains. This feature is needed for virt-manager to refresh its UI when networks are started/destroyed/defined/undefined.
Nit-pick virt-manager should already be refreshing its UI, but it will do it by polling for updates every N seconds. The events would simply allow it to be more efficient avoiding the need to poll for changes. Thanks for daring to tackle this piece of work. I think that realistically this isn't going to get into this month's release, since it'll likely need a few rounds of changes. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 11/21/2013 08:45 AM, Daniel P. Berrange wrote:
On Tue, Nov 19, 2013 at 04:43:12PM +0100, Cédric Bosdonnat wrote:
These changes are all about bringing events for network object like the ones existing for domains. This feature is needed for virt-manager to refresh its UI when networks are started/destroyed/defined/undefined.
Nit-pick virt-manager should already be refreshing its UI, but it will do it by polling for updates every N seconds. The events would simply allow it to be more efficient avoiding the need to poll for changes.
Actually in latest git I dropped polling of non-domain objects on every tick. We obviously poll on initial libvirt open(), but after that we only refresh our net/storage/iface state when something calls for it, like creating a new network, redefining and interface, etc. I figured in practice very few people were depending on it, it saves us tons of network traffic and CPU cycles, and if state gets out of sync there's a workaround of just disconnecting/reconnecting to libvirt. But event support for non-domain objects are obviously the correct solution for that problem, and this patch set is a great start. - Cole
participants (3)
-
Cole Robinson
-
Cédric Bosdonnat
-
Daniel P. Berrange