[libvirt] [PATCH v4 0/7] Network events API

This patch serie include changes to respond to Eric and Daniel's comments. The event namespace part of the ID is only handled at the object event's level, though we need to strip it out of virObjectEventStateEventID to get the remote driver properly deregister. Cédric Bosdonnat (7): Added Network events API and virNetworkEventLifecycle. test driver: implemented network events Add network events unit tests Add network events to the remote driver Added network events to the bridged network driver Fixed indentation in src/conf/*_event* Added default case with error for object event dispatching daemon/libvirtd.h | 1 + daemon/remote.c | 139 +++++++++++++++++ include/libvirt/libvirt.h.in | 80 ++++++++++ src/Makefile.am | 5 + src/conf/domain_event.c | 286 ++++++++++++++++++++--------------- src/conf/domain_event.h | 271 +++++++++++++++++++-------------- src/conf/network_event.c | 154 +++++++++++++++++++ src/conf/network_event.h | 51 +++++++ src/conf/object_event.c | 50 +++--- src/conf/object_event.h | 1 + src/conf/object_event_private.h | 20 ++- src/driver.h | 14 ++ src/libvirt.c | 125 +++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 7 + src/network/bridge_driver.c | 90 +++++++++++ src/network/bridge_driver_platform.h | 3 + src/remote/remote_driver.c | 127 ++++++++++++++++ src/remote/remote_protocol.x | 46 +++++- src/test/test_driver.c | 62 ++++++++ tests/objecteventtest.c | 167 ++++++++++++++++++++ 21 files changed, 1444 insertions(+), 257 deletions(-) create mode 100644 src/conf/network_event.c create mode 100644 src/conf/network_event.h -- 1.8.4.4

Put all network-events related code in src/conf/network_event.[ch] --- include/libvirt/libvirt.h.in | 80 ++++++++++++++++++++++ src/Makefile.am | 5 ++ src/conf/network_event.c | 154 +++++++++++++++++++++++++++++++++++++++++++ src/conf/network_event.h | 51 ++++++++++++++ src/conf/object_event.c | 9 +++ src/conf/object_event.h | 1 + src/driver.h | 14 ++++ src/libvirt.c | 125 +++++++++++++++++++++++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 7 ++ 10 files changed, 448 insertions(+) create mode 100644 src/conf/network_event.c create mode 100644 src/conf/network_event.h diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 29d4dce..73a77c0 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -4974,6 +4974,86 @@ 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 + * @detail: contains some details on the reason of the event. + * It will be 0 for the while. + * @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, + int detail, + 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/src/Makefile.am b/src/Makefile.am index a3ea55c..57e163f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -248,6 +248,9 @@ OBJECT_EVENT_SOURCES = \ DOMAIN_EVENT_SOURCES = \ conf/domain_event.c conf/domain_event.h +NETWORK_EVENT_SOURCES = \ + conf/network_event.c conf/network_event.h + # Network driver generic impl APIs NETWORK_CONF_SOURCES = \ conf/network_conf.c conf/network_conf.h @@ -298,6 +301,7 @@ CONF_SOURCES = \ $(DOMAIN_CONF_SOURCES) \ $(OBJECT_EVENT_SOURCES) \ $(DOMAIN_EVENT_SOURCES) \ + $(NETWORK_EVENT_SOURCES) \ $(NETWORK_CONF_SOURCES) \ $(NWFILTER_CONF_SOURCES) \ $(NODE_DEVICE_CONF_SOURCES) \ @@ -2026,6 +2030,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \ util/virutil.c \ util/viruuid.c \ conf/domain_event.c \ + conf/network_event.c \ conf/object_event.c \ rpc/virnetsocket.c \ rpc/virnetsocket.h \ diff --git a/src/conf/network_event.c b/src/conf/network_event.c new file mode 100644 index 0000000..74e9d3d --- /dev/null +++ b/src/conf/network_event.c @@ -0,0 +1,154 @@ +/* + * network_event.c: network event queue processing helpers + * + * 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 + */ + +#include <config.h> + +#include "network_event.h" +#include "object_event.h" +#include "object_event_private.h" +#include "datatypes.h" +#include "virlog.h" + +struct _virNetworkEventLifecycle { + virObjectEvent parent; + + int type; +}; +typedef struct _virNetworkEventLifecycle virNetworkEventLifecycle; +typedef virNetworkEventLifecycle *virNetworkEventLifecyclePtr; + +static virClassPtr virNetworkEventLifecycleClass; +static void virNetworkEventLifecycleDispose(void *obj); + +static int +virNetworkEventsOnceInit(void) +{ + if (!(virNetworkEventLifecycleClass = + virClassNew(virClassForObjectEvent(), + "virNetworkEventLifecycle", + sizeof(virNetworkEventLifecycle), + virNetworkEventLifecycleDispose))) + return -1; + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virNetworkEvents) + +void +virNetworkEventLifecycleDispose(void *obj) +{ + virNetworkEventLifecyclePtr event = obj; + VIR_DEBUG("obj=%p", event); +} + + +void +virNetworkEventDispatchDefaultFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectNetworkEventGenericCallback cb ATTRIBUTE_UNUSED, + void *cbopaque ATTRIBUTE_UNUSED, + void *opaque ATTRIBUTE_UNUSED) +{ + virNetworkPtr net = virGetNetwork(conn, event->meta.name, event->meta.uuid); + if (!net) + return; + + switch ((virNetworkEventID) (event->eventID &0xFF)) { + case VIR_NETWORK_EVENT_ID_LIFECYCLE: + { + virNetworkEventLifecyclePtr networkLifecycleEvent; + + networkLifecycleEvent = (virNetworkEventLifecyclePtr)event; + ((virConnectNetworkEventLifecycleCallback)cb)(conn, net, + networkLifecycleEvent->type, + 0, + cbopaque); + goto cleanup; + } + + case VIR_NETWORK_EVENT_ID_LAST: + break; + } + VIR_WARN("Unexpected event ID %d", event->eventID); + +cleanup: + virNetworkFree(net); +} + + +/** + * 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) +{ + int nsEventID = (VIR_EVENT_NAMESPACE_NETWORK << 8) + eventID; + if (net) + return virObjectEventStateRegisterID(conn, state, + net->uuid, net->name, 0, nsEventID, + cb, opaque, freecb, callbackID); + else + return virObjectEventStateRegisterID(conn, state, + NULL, NULL, 0, nsEventID, + cb, opaque, freecb, callbackID); +} + +void +*virNetworkEventLifecycleNew(const char *name, + const unsigned char *uuid, + int type) +{ + virNetworkEventLifecyclePtr event; + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + VIR_NETWORK_EVENT_ID_LIFECYCLE; + + if (virNetworkEventsInitialize() < 0) + return NULL; + + if (!(event = virObjectEventNew(virNetworkEventLifecycleClass, + eventId, + 0, name, uuid))) + return NULL; + + event->type = type; + + return event; +} diff --git a/src/conf/network_event.h b/src/conf/network_event.h new file mode 100644 index 0000000..385d618 --- /dev/null +++ b/src/conf/network_event.h @@ -0,0 +1,51 @@ +/* + * network_event.h: network event queue processing helpers + * + * 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 + */ + +#include "internal.h" +#include "object_event.h" +#include "object_event_private.h" + +#ifndef __NETWORK_EVENT_H__ +# define __NETWORK_EVENT_H__ + +int +virNetworkEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID); + +void +*virNetworkEventLifecycleNew(const char *name, + const unsigned char *uuid, + int type); + +void +virNetworkEventDispatchDefaultFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectNetworkEventGenericCallback cb, + void *cbopaque, + void *opaque); +#endif diff --git a/src/conf/object_event.c b/src/conf/object_event.c index fc4d9bb..065a3b0 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -25,6 +25,7 @@ #include <config.h> #include "domain_event.h" +#include "network_event.h" #include "object_event.h" #include "object_event_private.h" #include "virlog.h" @@ -42,6 +43,7 @@ struct _virObjectEventQueue { static virClassPtr virObjectEventClass; +static virClassPtr virObjectEventClass; static void virObjectEventDispose(void *obj); static int virObjectEventOnceInit(void) @@ -635,6 +637,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); } @@ -787,6 +793,9 @@ virObjectEventStateEventID(virConnectPtr conn, virObjectEventStateLock(state); ret = virObjectEventCallbackListEventID(conn, state->callbacks, callbackID); + /* Callers don't need to know we are namespacing the event Ids */ + if (ret >= 0) + ret = (0xFF & ret); virObjectEventStateUnlock(state); return ret; } diff --git a/src/conf/object_event.h b/src/conf/object_event.h index edd3e87..50cfe19 100644 --- a/src/conf/object_event.h +++ b/src/conf/object_event.h @@ -32,6 +32,7 @@ */ typedef enum { VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */ + VIR_EVENT_NAMESPACE_NETWORK = 1, } virEventNamespaceID; typedef struct _virObjectEventCallback virObjectEventCallback; 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 b3543d0..97175b2 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -19177,6 +19177,131 @@ 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 >= VIR_NETWORK_EVENT_ID_LAST) { + virReportInvalidArg(eventID, + _("eventID in %s must be less than %d"), + __FUNCTION__, VIR_NETWORK_EVENT_ID_LAST); + goto error; + } + + 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 3ca20e4..0e749b1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -624,6 +624,8 @@ virNWFilterVarValueGetSimple; # conf/object_event.h +virNetworkEventLifecycleNew; +virNetworkEventStateRegisterID; virObjectEventStateDeregisterID; virObjectEventStateEventID; virObjectEventStateFree; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index fe9b497..6ed6ce6 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -639,4 +639,11 @@ LIBVIRT_1.1.3 { virConnectGetCPUModelNames; } LIBVIRT_1.1.1; +LIBVIRT_1.2.1 { + global: + virConnectNetworkEventRegisterAny; + virConnectNetworkEventDeregisterAny; +} LIBVIRT_1.1.3; + + # .... define new API here using predicted next version number .... -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:37:58AM +0100, Cédric Bosdonnat wrote:
diff --git a/src/conf/network_event.c b/src/conf/network_event.c new file mode 100644 index 0000000..74e9d3d --- /dev/null +++ b/src/conf/network_event.c
+int +virNetworkEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID)
Small indentation bug I'll fix when pushing.
+{ + int nsEventID = (VIR_EVENT_NAMESPACE_NETWORK << 8) + eventID; + if (net) + return virObjectEventStateRegisterID(conn, state, + net->uuid, net->name, 0, nsEventID, + cb, opaque, freecb, callbackID); + else + return virObjectEventStateRegisterID(conn, state, + NULL, NULL, 0, nsEventID, + cb, opaque, freecb, callbackID); +} + +void +*virNetworkEventLifecycleNew(const char *name, + const unsigned char *uuid, + int type)
The return type should be virObjectEventPtr - will fix
+{ + virNetworkEventLifecyclePtr event; + int eventId = (VIR_EVENT_NAMESPACE_NETWORK << 8) + VIR_NETWORK_EVENT_ID_LIFECYCLE; + + if (virNetworkEventsInitialize() < 0) + return NULL; + + if (!(event = virObjectEventNew(virNetworkEventLifecycleClass, + eventId, + 0, name, uuid))) + return NULL; + + event->type = type; + + return event; +}
+int +virNetworkEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virNetworkPtr net, + int eventID, + virConnectObjectEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID);
Same indent issue
+ +void +*virNetworkEventLifecycleNew(const char *name, + const unsigned char *uuid, + int type); + +void +virNetworkEventDispatchDefaultFunc(virConnectPtr conn, + virObjectEventPtr event, + virConnectNetworkEventGenericCallback cb, + void *cbopaque, + void *opaque); +#endif + +typedef int +(*virDrvConnectNetworkEventDeregisterAny)(virConnectPtr conn, + int callbackID);
Tiny indent issue.
diff --git a/src/libvirt.c b/src/libvirt.c index b3543d0..97175b2 100644 --- a/src/libvirt.c +++ b/src/libvirt.c +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)) {
Small indent issue ACK will push with fixes 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 :|

--- src/test/test_driver.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 4972e3d..66afdf7 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -45,6 +45,7 @@ #include "interface_conf.h" #include "domain_conf.h" #include "domain_event.h" +#include "network_event.h" #include "snapshot_conf.h" #include "fdstream.h" #include "storage_conf.h" @@ -3529,6 +3530,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 +3541,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 +3563,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 +3574,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 +3593,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 +3610,17 @@ 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); @@ -3660,6 +3679,7 @@ static int testNetworkCreate(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; int ret = -1; + virObjectEventPtr event = NULL; testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, @@ -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,6 +6056,37 @@ 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 (virNetworkEventStateRegisterID(conn, + driver->domainEventState, + net, 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 testObjectEventQueue(testConnPtr driver, virObjectEventPtr event) @@ -7205,6 +7265,8 @@ static virNetworkDriver testNetworkDriver = { .connectNumOfDefinedNetworks = testConnectNumOfDefinedNetworks, /* 0.3.2 */ .connectListDefinedNetworks = testConnectListDefinedNetworks, /* 0.3.2 */ .connectListAllNetworks = testConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventRegisterAny = testConnectNetworkEventRegisterAny, /* 1.2.1 */ + .connectNetworkEventDeregisterAny = testConnectNetworkEventDeregisterAny, /* 1.2.1 */ .networkLookupByUUID = testNetworkLookupByUUID, /* 0.3.2 */ .networkLookupByName = testNetworkLookupByName, /* 0.3.2 */ .networkCreateXML = testNetworkCreateXML, /* 0.3.2 */ -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:37:59AM +0100, Cédric Bosdonnat wrote:
--- src/test/test_driver.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+)
@@ -6027,6 +6056,37 @@ 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 (virNetworkEventStateRegisterID(conn, + driver->domainEventState, + net, eventID, + VIR_OBJECT_EVENT_CALLBACK(callback), + opaque, freecb, &ret) < 0) + ret = -1; + testDriverUnlock(driver); + + return ret; +} + +static int +testConnectNetworkEventDeregisterAny(virConnectPtr conn, + int callbackID)
Indentation.
+{ + return testConnectDomainEventDeregisterAny(conn, callbackID); +}
We generally aim to avoid having one public API calling into another one, so I'm going to expand this to the explicit code. ACK and will fix issues before pushing. 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 :|

--- tests/objecteventtest.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c index 33e2551..ae29792 100644 --- a/tests/objecteventtest.c +++ b/tests/objecteventtest.c @@ -40,6 +40,18 @@ static const char domainDef[] = " </os>" "</domain>"; +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"; + typedef struct { int startEvents; int stopEvents; @@ -60,6 +72,7 @@ lifecycleEventCounter_reset(lifecycleEventCounter *counter) typedef struct { virConnectPtr conn; + virNetworkPtr net; } objecteventTest; @@ -92,6 +105,26 @@ domainLifecycleCb(virConnectPtr conn ATTRIBUTE_UNUSED, return 0; } +static void +networkLifecycleCb(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net ATTRIBUTE_UNUSED, + int event, + int detail ATTRIBUTE_UNUSED, + void* opaque) +{ + lifecycleEventCounter *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 testDomainCreateXML(const void *data) { @@ -223,6 +256,125 @@ cleanup: } static int +testNetworkCreateXML(const void *data) +{ + const objecteventTest *test = data; + lifecycleEventCounter counter; + virNetworkPtr net; + int id; + int ret = 0; + + lifecycleEventCounter_reset(&counter); + + id = virConnectNetworkEventRegisterAny(test->conn, NULL, + VIR_NETWORK_EVENT_ID_LIFECYCLE, + VIR_NETWORK_EVENT_CALLBACK(&networkLifecycleCb), + &counter, NULL); + net = virNetworkCreateXML(test->conn, networkDef); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.startEvents != 1 || counter.unexpectedEvents > 0) { + ret = -1; + goto cleanup; + } + +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + virNetworkDestroy(net); + + virNetworkFree(net); + + return ret; +} + +static int +testNetworkDefine(const void *data) +{ + const objecteventTest *test = data; + lifecycleEventCounter counter; + virNetworkPtr net; + int id; + int ret = 0; + + lifecycleEventCounter_reset(&counter); + + id = virConnectNetworkEventRegisterAny(test->conn, NULL, + VIR_NETWORK_EVENT_ID_LIFECYCLE, + 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 || counter.unexpectedEvents > 0) { + ret = -1; + goto cleanup; + } + + /* Make sure the undefine event is triggered */ + virNetworkUndefine(net); + + if (virEventRunDefaultImpl() < 0) { + ret = -1; + goto cleanup; + } + + if (counter.undefineEvents != 1 || counter.unexpectedEvents > 0) { + ret = -1; + goto cleanup; + } + + +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + virNetworkFree(net); + + return ret; +} + +static int +testNetworkStartStopEvent(const void *data) +{ + const objecteventTest *test = data; + lifecycleEventCounter counter; + int id; + int ret = 0; + + lifecycleEventCounter_reset(&counter); + + id = virConnectNetworkEventRegisterAny(test->conn, test->net, + VIR_NETWORK_EVENT_ID_LIFECYCLE, + 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 || + counter.unexpectedEvents > 0) { + ret = -1; + goto cleanup; + } +cleanup: + virConnectNetworkEventDeregisterAny(test->conn, id); + + return ret; +} + +static int mymain(void) { objecteventTest test; @@ -243,6 +395,21 @@ mymain(void) if (virtTestRun("Domain start stop events", testDomainStartStopEvent, &test) < 0) ret = EXIT_FAILURE; + /* Network event tests */ + /* 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); + if (virtTestRun("Network start stop events ", testNetworkStartStopEvent, &test) < 0) + ret = EXIT_FAILURE; + + /* Cleanup */ + virNetworkUndefine(test.net); + virNetworkFree(test.net); virConnectClose(test.conn); return ret; -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:38:00AM +0100, Cédric Bosdonnat wrote:
--- tests/objecteventtest.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+)
ACK 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 :|

--- daemon/libvirtd.h | 1 + daemon/remote.c | 139 +++++++++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 127 +++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 46 +++++++++++++- 4 files changed, 312 insertions(+), 1 deletion(-) 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 f060006..bcd73d4 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -49,6 +49,7 @@ #include "qemu_protocol.h" #include "lxc_protocol.h" #include "virstring.h" +#include "object_event.h" #define VIR_FROM_THIS VIR_FROM_RPC @@ -653,6 +654,38 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); +static int remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net, + int event, + int detail, + void *opaque) +{ + virNetServerClientPtr client = opaque; + remote_network_event_lifecycle_msg data; + + if (!client) + return -1; + + VIR_DEBUG("Relaying network lifecycle event %d, detail %d", event, detail); + + /* 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 +713,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 +758,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; } @@ -5216,6 +5261,100 @@ 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported network event ID %d"), args->eventID); + goto cleanup; + } + + if (priv->networkEventCallbackID[args->eventID] != -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], + 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) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported event ID %d"), args->eventID); + goto cleanup; + } + + callbackID = priv->networkEventCallbackID[args->eventID]; + 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] = -1; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virMutexUnlock(&priv->lock); + return rv; +} + /*----- Helpers. -----*/ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 4a84a52..046f424 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -33,6 +33,7 @@ #include "virlog.h" #include "datatypes.h" #include "domain_event.h" +#include "network_event.h" #include "driver.h" #include "virbuffer.h" #include "remote_driver.h" @@ -273,6 +274,11 @@ 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, remoteDomainBuildEventRTCChange, @@ -338,6 +344,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 { @@ -2902,6 +2912,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 = eventID; + + 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) @@ -4800,6 +4903,28 @@ remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED } +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, unsigned int flags) @@ -7035,6 +7160,8 @@ static virNetworkDriver network_driver = { .connectNumOfDefinedNetworks = remoteConnectNumOfDefinedNetworks, /* 0.3.0 */ .connectListDefinedNetworks = remoteConnectListDefinedNetworks, /* 0.3.0 */ .connectListAllNetworks = remoteConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventDeregisterAny = remoteConnectNetworkEventDeregisterAny, /* 1.2.1 */ + .connectNetworkEventRegisterAny = remoteConnectNetworkEventRegisterAny, /* 1.2.1 */ .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 }; -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:38:01AM +0100, Cédric Bosdonnat wrote:
--- daemon/libvirtd.h | 1 + daemon/remote.c | 139 +++++++++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 127 +++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 46 +++++++++++++- 4 files changed, 312 insertions(+), 1 deletion(-)
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 f060006..bcd73d4 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -49,6 +49,7 @@ #include "qemu_protocol.h" #include "lxc_protocol.h" #include "virstring.h" +#include "object_event.h"
#define VIR_FROM_THIS VIR_FROM_RPC
@@ -653,6 +654,38 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
+static int remoteRelayNetworkEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, + virNetworkPtr net, + int event, + int detail, + void *opaque)
Indent.
@@ -5216,6 +5261,100 @@ 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) {
We can drop the "& 0xFF" bit now namespaces aren't visible on the wire
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported network event ID %d"), args->eventID); + goto cleanup; + } + + if (priv->networkEventCallbackID[args->eventID] != -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], + client, NULL)) < 0) + goto cleanup; + + priv->networkEventCallbackID[args->eventID & 0xFF] = callbackID;
And again here.
+ + 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) {
And here
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 4a84a52..046f424 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2902,6 +2912,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) {
Indent
+ 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 = eventID; + + 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)
ACK, will fix the minor issues when pushing. 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 Wed, Dec 11, 2013 at 11:38:01AM +0100, Cédric Bosdonnat wrote:
--- daemon/libvirtd.h | 1 + daemon/remote.c | 139 +++++++++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 127 +++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 46 +++++++++++++- 4 files changed, 312 insertions(+), 1 deletion(-)
Oppps, missed changes to src/remote_protocol-structs which causes 'make check' to fail - I've added the obvious bits. 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 :|

My overnight Coverity run found an issue in the function: 'remoteNetworkBuildEventLifecycle' On 12/11/2013 05:38 AM, Cédric Bosdonnat wrote:
--- daemon/libvirtd.h | 1 + daemon/remote.c | 139 +++++++++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 127 +++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 46 +++++++++++++- 4 files changed, 312 insertions(+), 1 deletion(-)
<...snip...>
+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; +
4920 (3) Event returned_null: Function "virNetworkEventLifecycleNew(char const *, unsigned char const *, int)" returns null (checked 10 out of 11 times). [details] (14) Event var_assigned: Assigning: "event" = null return value from "virNetworkEventLifecycleNew(char const *, unsigned char const *, int)". Also see events: [example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][dereference] 4921 event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event);
+ event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event); + virNetworkFree(net); +
(15) Event dereference: Dereferencing a pointer that might be null "event" when calling "remoteDomainEventQueue(struct private_data *, virObjectEventPtr)". [details] Also see events: [returned_null][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][var_assigned]
+ remoteDomainEventQueue(priv, event); +} + +
Essentially - you need to check for NULL event. John

Hi John, On Thu, 2013-12-12 at 06:50 -0500, John Ferlan wrote:
4920
(3) Event returned_null: Function "virNetworkEventLifecycleNew(char const *, unsigned char const *, int)" returns null (checked 10 out of 11 times). [details] (14) Event var_assigned: Assigning: "event" = null return value from "virNetworkEventLifecycleNew(char const *, unsigned char const *, int)". Also see events: [example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][dereference]
4921 event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event);
+ event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event); + virNetworkFree(net); +
(15) Event dereference: Dereferencing a pointer that might be null "event" when calling "remoteDomainEventQueue(struct private_data *, virObjectEventPtr)". [details] Also see events: [returned_null][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][var_assigned]
+ remoteDomainEventQueue(priv, event); +} + +
Essentially - you need to check for NULL event.
Sure, but the weird thing it that it should also complain on the similar functions for domain events, right above this one in the same file. -- Cedric

On 12/12/2013 07:30 AM, Cedric Bosdonnat wrote:
Hi John,
+ event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event); + virNetworkFree(net); + remoteDomainEventQueue(priv, event);
Essentially - you need to check for NULL event.
Sure, but the weird thing it that it should also complain on the similar functions for domain events, right above this one in the same file.
Revisiting this. The problem can only happen on OOM situations, so it's not that likely to hit in real life; but we should indeed fix our code. I think the easiest way is to fix remoteDomainEventQueue to gracefully do nothing on a NULL event (events are best effort, and if OOM occurs, skipping event delivery is an acceptable action, since we have no way of reporting the error). I'll post a patch. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 01/09/2014 07:50 PM, Eric Blake wrote:
On 12/12/2013 07:30 AM, Cedric Bosdonnat wrote:
Hi John,
+ event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event); + virNetworkFree(net); + remoteDomainEventQueue(priv, event);
Essentially - you need to check for NULL event.
Sure, but the weird thing it that it should also complain on the similar functions for domain events, right above this one in the same file.
Revisiting this. The problem can only happen on OOM situations, so it's not that likely to hit in real life; but we should indeed fix our code. I think the easiest way is to fix remoteDomainEventQueue to gracefully do nothing on a NULL event (events are best effort, and if OOM occurs, skipping event delivery is an acceptable action, since we have no way of reporting the error). I'll post a patch.
Actually, it turns out we are quite lucky - appending a NULL event to the queue had no ill effects, because when checking for what callbacks to dispatch, our first use of events was an early exit if (!virObjectIsClass(event, cb->klass)). So the ATTRIBUTE_NONNULL could actually be deleted - but that in turn implies we have a lot of code that checks for non-null events before queueing them up which could also be simplified. And even if we did that, queueing a NULL event is a waste of resources compared to just avoiding them altogether. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

--- src/network/bridge_driver.c | 90 ++++++++++++++++++++++++++++++++++++ src/network/bridge_driver_platform.h | 3 ++ 2 files changed, 93 insertions(+) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 80c5acb..4c0c352 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -70,6 +70,7 @@ #include "virfile.h" #include "virstring.h" #include "viraccessapicheck.h" +#include "network_event.h" #define VIR_FROM_THIS VIR_FROM_NETWORK @@ -438,6 +439,8 @@ networkStateInitialize(bool privileged, networkReloadFirewallRules(driverState); networkRefreshDaemons(driverState); + driverState->networkEventState = virObjectEventStateNew(); + networkDriverUnlock(driverState); #ifdef HAVE_FIREWALLD @@ -532,6 +535,8 @@ networkStateCleanup(void) { networkDriverLock(driverState); + virObjectEventStateFree(driverState->networkEventState); + /* free inactive networks */ virNetworkObjListFree(&driverState->networks); @@ -2290,6 +2295,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 +2537,7 @@ static virNetworkPtr networkCreateXML(virConnectPtr conn, const char *xml) { virNetworkDefPtr def; virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2509,11 +2564,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 +2587,7 @@ static virNetworkPtr networkDefineXML(virConnectPtr conn, const char *xml) { bool freeDef = true; virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2565,10 +2627,15 @@ 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); if (network) @@ -2583,6 +2650,7 @@ networkUndefine(virNetworkPtr net) { virNetworkObjPtr network; int ret = -1; bool active = false; + virObjectEventPtr event = NULL; networkDriverLock(driver); @@ -2610,6 +2678,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 +2694,8 @@ networkUndefine(virNetworkPtr net) { ret = 0; cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -2805,6 +2879,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); @@ -2820,7 +2895,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); @@ -2831,6 +2912,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); @@ -2853,6 +2935,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; @@ -2863,6 +2949,8 @@ static int networkDestroy(virNetworkPtr net) { } cleanup: + if (event) + virObjectEventStateQueue(driver->networkEventState, event); if (network) virNetworkObjUnlock(network); networkDriverUnlock(driver); @@ -3021,6 +3109,8 @@ static virNetworkDriver networkDriver = { .connectNumOfDefinedNetworks = networkConnectNumOfDefinedNetworks, /* 0.2.0 */ .connectListDefinedNetworks = networkConnectListDefinedNetworks, /* 0.2.0 */ .connectListAllNetworks = networkConnectListAllNetworks, /* 0.10.2 */ + .connectNetworkEventRegisterAny = networkConnectNetworkEventRegisterAny, /* 1.2.1 */ + .connectNetworkEventDeregisterAny = networkConnectNetworkEventDeregisterAny, /* 1.2.1 */ .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; -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:38:02AM +0100, Cédric Bosdonnat wrote:
--- src/network/bridge_driver.c | 90 ++++++++++++++++++++++++++++++++++++ src/network/bridge_driver_platform.h | 3 ++ 2 files changed, 93 insertions(+)
ACK
+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; +}
Opps, locking is wrong - if the ACL check fails we leave the driver locked. We can actually do without locking entirely, since the event state struct is self-locking, so I'll remove the lock/unlock
+ +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; +}
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 :|

--- src/conf/domain_event.c | 286 +++++++++++++++++++++++----------------- src/conf/domain_event.h | 271 +++++++++++++++++++++---------------- src/conf/object_event.c | 47 ++++--- src/conf/object_event_private.h | 20 +-- 4 files changed, 364 insertions(+), 260 deletions(-) diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index da57129..45e48b6 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -443,11 +443,12 @@ virDomainEventCallbackListAdd(virConnectPtr conn, } -static void *virDomainEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid) +static void +*virDomainEventNew(virClassPtr klass, + int eventID, + int id, + const char *name, + const unsigned char *uuid) { virDomainEventPtr event; @@ -468,9 +469,12 @@ static void *virDomainEventNew(virClassPtr klass, return (virObjectEventPtr)event; } -virObjectEventPtr virDomainEventLifecycleNew(int id, const char *name, - const unsigned char *uuid, - int type, int detail) +virObjectEventPtr +virDomainEventLifecycleNew(int id, + const char *name, + const unsigned char *uuid, + int type, + int detail) { virDomainEventLifecyclePtr event; @@ -488,25 +492,36 @@ virObjectEventPtr virDomainEventLifecycleNew(int id, const char *name, return (virObjectEventPtr)event; } -virObjectEventPtr virDomainEventLifecycleNewFromDom(virDomainPtr dom, int type, int detail) +virObjectEventPtr +virDomainEventLifecycleNewFromDom(virDomainPtr dom, + int type, + int detail) { return virDomainEventLifecycleNew(dom->id, dom->name, dom->uuid, type, detail); } -virObjectEventPtr virDomainEventLifecycleNewFromObj(virDomainObjPtr obj, int type, int detail) +virObjectEventPtr +virDomainEventLifecycleNewFromObj(virDomainObjPtr obj, + int type, + int detail) { return virDomainEventLifecycleNewFromDef(obj->def, type, detail); } -virObjectEventPtr virDomainEventLifecycleNewFromDef(virDomainDefPtr def, int type, int detail) +virObjectEventPtr +virDomainEventLifecycleNewFromDef(virDomainDefPtr def, + int type, + int detail) { return virDomainEventLifecycleNew(def->id, def->name, def->uuid, type, detail); } -virObjectEventPtr virDomainEventRebootNew(int id, const char *name, - const unsigned char *uuid) +virObjectEventPtr +virDomainEventRebootNew(int id, + const char *name, + const unsigned char *uuid) { if (virDomainEventsInitialize() < 0) return NULL; @@ -516,7 +531,8 @@ virObjectEventPtr virDomainEventRebootNew(int id, const char *name, id, name, uuid); } -virObjectEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom) +virObjectEventPtr +virDomainEventRebootNewFromDom(virDomainPtr dom) { if (virDomainEventsInitialize() < 0) return NULL; @@ -526,7 +542,8 @@ virObjectEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom) dom->id, dom->name, dom->uuid); } -virObjectEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj) +virObjectEventPtr +virDomainEventRebootNewFromObj(virDomainObjPtr obj) { if (virDomainEventsInitialize() < 0) return NULL; @@ -536,8 +553,9 @@ virObjectEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj) obj->def->id, obj->def->name, obj->def->uuid); } -virObjectEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, - long long offset) +virObjectEventPtr +virDomainEventRTCChangeNewFromDom(virDomainPtr dom, + long long offset) { virDomainEventRTCChangePtr ev; @@ -553,8 +571,9 @@ virObjectEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, - long long offset) +virObjectEventPtr +virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, + long long offset) { virDomainEventRTCChangePtr ev; @@ -572,7 +591,9 @@ virObjectEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action) +virObjectEventPtr +virDomainEventWatchdogNewFromDom(virDomainPtr dom, + int action) { virDomainEventWatchdogPtr ev; @@ -588,7 +609,9 @@ virObjectEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action) return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action) +virObjectEventPtr +virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, + int action) { virDomainEventWatchdogPtr ev; @@ -606,12 +629,13 @@ virObjectEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int acti return (virObjectEventPtr)ev; } -static virObjectEventPtr virDomainEventIOErrorNewFromDomImpl(int event, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason) +static virObjectEventPtr +virDomainEventIOErrorNewFromDomImpl(int event, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason) { virDomainEventIOErrorPtr ev; @@ -633,12 +657,13 @@ static virObjectEventPtr virDomainEventIOErrorNewFromDomImpl(int event, return (virObjectEventPtr)ev; } -static virObjectEventPtr virDomainEventIOErrorNewFromObjImpl(int event, - virDomainObjPtr obj, - const char *srcPath, - const char *devAlias, - int action, - const char *reason) +static virObjectEventPtr +virDomainEventIOErrorNewFromObjImpl(int event, + virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action, + const char *reason) { virDomainEventIOErrorPtr ev; @@ -661,42 +686,46 @@ static virObjectEventPtr virDomainEventIOErrorNewFromObjImpl(int event, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action) +virObjectEventPtr +virDomainEventIOErrorNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action) { return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR, dom, srcPath, devAlias, action, NULL); } -virObjectEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, - const char *srcPath, - const char *devAlias, - int action) +virObjectEventPtr +virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action) { return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR, obj, srcPath, devAlias, action, NULL); } -virObjectEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason) +virObjectEventPtr +virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason) { return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, dom, srcPath, devAlias, action, reason); } -virObjectEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, - const char *srcPath, - const char *devAlias, - int action, - const char *reason) +virObjectEventPtr +virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action, + const char *reason) { return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, obj, srcPath, devAlias, @@ -704,12 +733,13 @@ virObjectEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, } -virObjectEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject) +virObjectEventPtr +virDomainEventGraphicsNewFromDom(virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject) { virDomainEventGraphicsPtr ev; @@ -733,12 +763,13 @@ virObjectEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject) +virObjectEventPtr +virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject) { virDomainEventGraphicsPtr ev; @@ -763,13 +794,13 @@ virObjectEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, return (virObjectEventPtr)ev; } -static -virObjectEventPtr virDomainEventBlockJobNew(int id, - const char *name, - unsigned char *uuid, - const char *path, - int type, - int status) +static virObjectEventPtr +virDomainEventBlockJobNew(int id, + const char *name, + unsigned char *uuid, + const char *path, + int type, + int status) { virDomainEventBlockJobPtr ev; @@ -791,25 +822,28 @@ virObjectEventPtr virDomainEventBlockJobNew(int id, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, - const char *path, - int type, - int status) +virObjectEventPtr +virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, + const char *path, + int type, + int status) { return virDomainEventBlockJobNew(obj->def->id, obj->def->name, obj->def->uuid, path, type, status); } -virObjectEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, - const char *path, - int type, - int status) +virObjectEventPtr +virDomainEventBlockJobNewFromDom(virDomainPtr dom, + const char *path, + int type, + int status) { return virDomainEventBlockJobNew(dom->id, dom->name, dom->uuid, path, type, status); } -virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) +virObjectEventPtr +virDomainEventControlErrorNewFromDom(virDomainPtr dom) { virObjectEventPtr ev; @@ -824,7 +858,8 @@ virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) } -virObjectEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj) +virObjectEventPtr +virDomainEventControlErrorNewFromObj(virDomainObjPtr obj) { virObjectEventPtr ev; @@ -839,12 +874,14 @@ virObjectEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj) return ev; } -static -virObjectEventPtr virDomainEventDiskChangeNew(int id, const char *name, - unsigned char *uuid, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, int reason) +static virObjectEventPtr +virDomainEventDiskChangeNew(int id, + const char *name, + unsigned char *uuid, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason) { virDomainEventDiskChangePtr ev; @@ -874,22 +911,24 @@ error: return NULL; } -virObjectEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason) +virObjectEventPtr +virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason) { return virDomainEventDiskChangeNew(obj->def->id, obj->def->name, obj->def->uuid, oldSrcPath, newSrcPath, devAlias, reason); } -virObjectEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason) +virObjectEventPtr +virDomainEventDiskChangeNewFromDom(virDomainPtr dom, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason) { return virDomainEventDiskChangeNew(dom->id, dom->name, dom->uuid, oldSrcPath, newSrcPath, @@ -897,7 +936,8 @@ virObjectEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, } static virObjectEventPtr -virDomainEventTrayChangeNew(int id, const char *name, +virDomainEventTrayChangeNew(int id, + const char *name, unsigned char *uuid, const char *devAlias, int reason) @@ -924,9 +964,10 @@ error: return NULL; } -virObjectEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, - const char *devAlias, - int reason) +virObjectEventPtr +virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, + const char *devAlias, + int reason) { return virDomainEventTrayChangeNew(obj->def->id, obj->def->name, @@ -935,16 +976,18 @@ virObjectEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, reason); } -virObjectEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, - const char *devAlias, - int reason) +virObjectEventPtr +virDomainEventTrayChangeNewFromDom(virDomainPtr dom, + const char *devAlias, + int reason) { return virDomainEventTrayChangeNew(dom->id, dom->name, dom->uuid, devAlias, reason); } static virObjectEventPtr -virDomainEventPMWakeupNew(int id, const char *name, +virDomainEventPMWakeupNew(int id, + const char *name, unsigned char *uuid) { virObjectEventPtr ev; @@ -975,7 +1018,8 @@ virDomainEventPMWakeupNewFromDom(virDomainPtr dom) } static virObjectEventPtr -virDomainEventPMSuspendNew(int id, const char *name, +virDomainEventPMSuspendNew(int id, + const char *name, unsigned char *uuid) { virObjectEventPtr ev; @@ -1006,7 +1050,8 @@ virDomainEventPMSuspendNewFromDom(virDomainPtr dom) } static virObjectEventPtr -virDomainEventPMSuspendDiskNew(int id, const char *name, +virDomainEventPMSuspendDiskNew(int id, + const char *name, unsigned char *uuid) { virObjectEventPtr ev; @@ -1035,8 +1080,9 @@ virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom) return virDomainEventPMSuspendDiskNew(dom->id, dom->name, dom->uuid); } -virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, - unsigned long long actual) +virObjectEventPtr +virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, + unsigned long long actual) { virDomainEventBalloonChangePtr ev; @@ -1052,8 +1098,9 @@ virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, return (virObjectEventPtr)ev; } -virObjectEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, - unsigned long long actual) +virObjectEventPtr +virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, + unsigned long long actual) { virDomainEventBalloonChangePtr ev; @@ -1070,10 +1117,11 @@ virObjectEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, return (virObjectEventPtr)ev; } -static virObjectEventPtr virDomainEventDeviceRemovedNew(int id, - const char *name, - unsigned char *uuid, - const char *devAlias) +static virObjectEventPtr +virDomainEventDeviceRemovedNew(int id, + const char *name, + unsigned char *uuid, + const char *devAlias) { virDomainEventDeviceRemovedPtr ev; @@ -1095,15 +1143,17 @@ error: return NULL; } -virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, - const char *devAlias) +virObjectEventPtr +virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, + const char *devAlias) { return virDomainEventDeviceRemovedNew(obj->def->id, obj->def->name, obj->def->uuid, devAlias); } -virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, - const char *devAlias) +virObjectEventPtr +virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, + const char *devAlias) { return virDomainEventDeviceRemovedNew(dom->id, dom->name, dom->uuid, devAlias); diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index c7fa0e3..30156ed 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -31,120 +31,165 @@ # include "domain_conf.h" -virObjectEventPtr virDomainEventLifecycleNew(int id, - const char *name, - const unsigned char *uuid, - int type, - int detail); -virObjectEventPtr virDomainEventLifecycleNewFromDom(virDomainPtr dom, - int type, - int detail); -virObjectEventPtr virDomainEventLifecycleNewFromObj(virDomainObjPtr obj, - int type, - int detail); -virObjectEventPtr virDomainEventLifecycleNewFromDef(virDomainDefPtr def, - int type, - int detail); - -virObjectEventPtr virDomainEventRebootNew(int id, const char *name, const unsigned char *uuid); -virObjectEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom); -virObjectEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj); - -virObjectEventPtr virDomainEventRTCChangeNewFromDom(virDomainPtr dom, long long offset); -virObjectEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, long long offset); - -virObjectEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action); -virObjectEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action); - -virObjectEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action); -virObjectEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, - const char *srcPath, - const char *devAlias, - int action); -virObjectEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason); -virObjectEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, - const char *srcPath, - const char *devAlias, - int action, - const char *reason); - -virObjectEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject); -virObjectEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject); -virObjectEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom); -virObjectEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj); - -virObjectEventPtr virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, - const char *path, - int type, - int status); -virObjectEventPtr virDomainEventBlockJobNewFromDom(virDomainPtr dom, - const char *path, - int type, - int status); - -virObjectEventPtr virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason); -virObjectEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason); -virObjectEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, - const char *devAlias, - int reason); -virObjectEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom, - const char *devAlias, - int reason); -virObjectEventPtr virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj); -virObjectEventPtr virDomainEventPMWakeupNewFromDom(virDomainPtr dom); -virObjectEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj); -virObjectEventPtr virDomainEventPMSuspendNewFromDom(virDomainPtr dom); - -virObjectEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, unsigned long long actual); -virObjectEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, unsigned long long actual); - -virObjectEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); -virObjectEventPtr virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); - -virObjectEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, - const char *devAlias); -virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, - const char *devAlias); - -int virDomainEventStateRegister(virConnectPtr conn, - virObjectEventStatePtr state, - virConnectDomainEventCallback callback, - void *opaque, - virFreeCallback freecb) +virObjectEventPtr +virDomainEventLifecycleNew(int id, + const char *name, + const unsigned char *uuid, + int type, + int detail); +virObjectEventPtr +virDomainEventLifecycleNewFromDom(virDomainPtr dom, + int type, + int detail); +virObjectEventPtr +virDomainEventLifecycleNewFromObj(virDomainObjPtr obj, + int type, + int detail); +virObjectEventPtr +virDomainEventLifecycleNewFromDef(virDomainDefPtr def, + int type, + int detail); + +virObjectEventPtr +virDomainEventRebootNew(int id, + const char *name, + const unsigned char *uuid); +virObjectEventPtr +virDomainEventRebootNewFromDom(virDomainPtr dom); +virObjectEventPtr +virDomainEventRebootNewFromObj(virDomainObjPtr obj); + +virObjectEventPtr +virDomainEventRTCChangeNewFromDom(virDomainPtr dom, + long long offset); +virObjectEventPtr +virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, + long long offset); + +virObjectEventPtr +virDomainEventWatchdogNewFromDom(virDomainPtr dom, + int action); +virObjectEventPtr +virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, + int action); + +virObjectEventPtr +virDomainEventIOErrorNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action); +virObjectEventPtr +virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action); +virObjectEventPtr +virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason); +virObjectEventPtr +virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action, + const char *reason); + +virObjectEventPtr +virDomainEventGraphicsNewFromDom(virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject); +virObjectEventPtr +virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject); +virObjectEventPtr +virDomainEventControlErrorNewFromDom(virDomainPtr dom); +virObjectEventPtr +virDomainEventControlErrorNewFromObj(virDomainObjPtr obj); + +virObjectEventPtr +virDomainEventBlockJobNewFromObj(virDomainObjPtr obj, + const char *path, + int type, + int status); +virObjectEventPtr +virDomainEventBlockJobNewFromDom(virDomainPtr dom, + const char *path, + int type, + int status); + +virObjectEventPtr +virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason); +virObjectEventPtr +virDomainEventDiskChangeNewFromDom(virDomainPtr dom, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason); +virObjectEventPtr +virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj, + const char *devAlias, + int reason); +virObjectEventPtr +virDomainEventTrayChangeNewFromDom(virDomainPtr dom, + const char *devAlias, + int reason); +virObjectEventPtr +virDomainEventPMWakeupNewFromObj(virDomainObjPtr obj); +virObjectEventPtr +virDomainEventPMWakeupNewFromDom(virDomainPtr dom); +virObjectEventPtr +virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj); +virObjectEventPtr +virDomainEventPMSuspendNewFromDom(virDomainPtr dom); + +virObjectEventPtr +virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, + unsigned long long actual); +virObjectEventPtr +virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, + unsigned long long actual); + +virObjectEventPtr +virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); +virObjectEventPtr +virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); + +virObjectEventPtr +virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, + const char *devAlias); +virObjectEventPtr +virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, + const char *devAlias); + +int +virDomainEventStateRegister(virConnectPtr conn, + virObjectEventStatePtr state, + virConnectDomainEventCallback callback, + void *opaque, + virFreeCallback freecb) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); -int virDomainEventStateRegisterID(virConnectPtr conn, - virObjectEventStatePtr state, - virDomainPtr dom, - int eventID, - virConnectDomainEventGenericCallback cb, - void *opaque, - virFreeCallback freecb, - int *callbackID) +int +virDomainEventStateRegisterID(virConnectPtr conn, + virObjectEventStatePtr state, + virDomainPtr dom, + int eventID, + virConnectDomainEventGenericCallback cb, + void *opaque, + virFreeCallback freecb, + int *callbackID) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5); int virDomainEventStateDeregister(virConnectPtr conn, diff --git a/src/conf/object_event.c b/src/conf/object_event.c index 065a3b0..0f21c37 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -46,7 +46,8 @@ static virClassPtr virObjectEventClass; static virClassPtr virObjectEventClass; static void virObjectEventDispose(void *obj); -static int virObjectEventOnceInit(void) +static int +virObjectEventOnceInit(void) { if (!(virObjectEventClass = virClassNew(virClassForObject(), @@ -59,14 +60,16 @@ static int virObjectEventOnceInit(void) VIR_ONCE_GLOBAL_INIT(virObjectEvent) -virClassPtr virClassForObjectEvent(void) +virClassPtr +virClassForObjectEvent(void) { if (virObjectEventInitialize() < 0) return NULL; return virObjectEventClass; } -int virObjectEventGetEventID(void *anyobj) +int +virObjectEventGetEventID(void *anyobj) { virObjectEventPtr obj = anyobj; @@ -78,7 +81,8 @@ int virObjectEventGetEventID(void *anyobj) return obj->eventID; } -static void virObjectEventDispose(void *obj) +static void +virObjectEventDispose(void *obj) { virObjectEventPtr event = obj; @@ -460,11 +464,12 @@ error: return NULL; } -void *virObjectEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid) +void +*virObjectEventNew(virClassPtr klass, + int eventID, + int id, + const char *name, + const unsigned char *uuid) { virObjectEventPtr event; @@ -529,8 +534,9 @@ typedef void (*virObjectEventDispatchFunc)(virConnectPtr conn, void *opaque); -static int virObjectEventDispatchMatchCallback(virObjectEventPtr event, - virObjectEventCallbackPtr cb) +static int +virObjectEventDispatchMatchCallback(virObjectEventPtr event, + virObjectEventCallbackPtr cb) { if (!cb) return 0; @@ -631,16 +637,15 @@ virObjectEventStateDispatchFunc(virConnectPtr conn, /* 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; - case VIR_EVENT_NAMESPACE_NETWORK: - virNetworkEventDispatchDefaultFunc(conn, event, - VIR_NETWORK_EVENT_CALLBACK(cb), cbopaque, NULL); - break; + switch (namespace) { + case VIR_EVENT_NAMESPACE_DOMAIN: + 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); } diff --git a/src/conf/object_event_private.h b/src/conf/object_event_private.h index e4ebd95..0ed2eef 100644 --- a/src/conf/object_event_private.h +++ b/src/conf/object_event_private.h @@ -75,9 +75,11 @@ struct _virObjectEvent { virObjectMeta meta; }; -virClassPtr virClassForObjectEvent(void); +virClassPtr +virClassForObjectEvent(void); -int virObjectEventGetEventID(void *anyobj); +int +virObjectEventGetEventID(void *anyobj); int virObjectEventCallbackListAddID(virConnectPtr conn, @@ -101,13 +103,15 @@ void virObjectEventStateUnlock(virObjectEventStatePtr state); void -virObjectEventTimer(int timer, void *opaque); +virObjectEventTimer(int timer, + void *opaque); -void *virObjectEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid); +void +*virObjectEventNew(virClassPtr klass, + int eventID, + int id, + const char *name, + const unsigned char *uuid); #endif -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:38:03AM +0100, Cédric Bosdonnat wrote:
--- src/conf/domain_event.c | 286 +++++++++++++++++++++++----------------- src/conf/domain_event.h | 271 +++++++++++++++++++++---------------- src/conf/object_event.c | 47 ++++--- src/conf/object_event_private.h | 20 +-- 4 files changed, 364 insertions(+), 260 deletions(-)
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index da57129..45e48b6 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -443,11 +443,12 @@ virDomainEventCallbackListAdd(virConnectPtr conn, }
-static void *virDomainEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid) +static void +*virDomainEventNew(virClassPtr klass,
The '*' should be on the same line as the void.
+ int eventID, + int id, + const char *name, + const unsigned char *uuid) { virDomainEventPtr event;
@@ -460,11 +464,12 @@ error: return NULL; }
-void *virObjectEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid) +void +*virObjectEventNew(virClassPtr klass,
And here
+ int eventID, + int id, + const char *name, + const unsigned char *uuid) { virObjectEventPtr event;
-void *virObjectEventNew(virClassPtr klass, - int eventID, - int id, - const char *name, - const unsigned char *uuid); +void +*virObjectEventNew(virClassPtr klass,
And here
+ int eventID, + int id, + const char *name, + const unsigned char *uuid);
ACK will fix those bugs. 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 :|

Hitting this should be pretty rare, but at least developers will know that they are providing a weird event ID. Otherwise for namespace that are added in the normal way, gcc will raise a warning about unhandled case in the switch. --- src/conf/object_event.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/conf/object_event.c b/src/conf/object_event.c index 0f21c37..1e0b33d 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -646,6 +646,8 @@ virObjectEventStateDispatchFunc(virConnectPtr conn, virNetworkEventDispatchDefaultFunc(conn, event, VIR_NETWORK_EVENT_CALLBACK(cb), cbopaque, NULL); break; + default: + VIR_ERROR(_("Unknown event namespace to dispatch")); } virObjectEventStateLock(state); } -- 1.8.4.4

On Wed, Dec 11, 2013 at 11:38:04AM +0100, Cédric Bosdonnat wrote:
Hitting this should be pretty rare, but at least developers will know that they are providing a weird event ID. Otherwise for namespace that are added in the normal way, gcc will raise a warning about unhandled case in the switch. --- src/conf/object_event.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/src/conf/object_event.c b/src/conf/object_event.c index 0f21c37..1e0b33d 100644 --- a/src/conf/object_event.c +++ b/src/conf/object_event.c @@ -646,6 +646,8 @@ virObjectEventStateDispatchFunc(virConnectPtr conn, virNetworkEventDispatchDefaultFunc(conn, event, VIR_NETWORK_EVENT_CALLBACK(cb), cbopaque, NULL); break; + default: + VIR_ERROR(_("Unknown event namespace to dispatch")); } virObjectEventStateLock(state); }
ACK 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 :|
participants (5)
-
Cedric Bosdonnat
-
Cédric Bosdonnat
-
Daniel P. Berrange
-
Eric Blake
-
John Ferlan