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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list