---
include/libvirt/libvirt.h.in | 78 +++++++++++++++++++++++++
src/conf/object_event.c | 80 +++++++++++++++++++++++++-
src/conf/object_event.h | 21 +++++--
src/driver.h | 14 +++++
src/libvirt.c | 133 +++++++++++++++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 7 +++
7 files changed, 328 insertions(+), 6 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 25ab777..50fa3f7 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4966,6 +4966,7 @@ typedef enum {
*/
typedef enum {
VIR_EVENT_NAMESPACE_DOMAIN = 0, /* 0 to keep value of virDomainEventId unchanged */
+ VIR_EVENT_NAMESPACE_NETWORK = 1,
} virEventNamespaceID;
@@ -4980,6 +4981,83 @@ int virConnectDomainEventRegisterAny(virConnectPtr conn,
int virConnectDomainEventDeregisterAny(virConnectPtr conn,
int callbackID);
+/**
+ * virNetworkEventLifecycleType:
+ *
+ * a virNetworkEventLifecycleType is emitted during network lifecycle events
+ */
+typedef enum {
+ VIR_NETWORK_EVENT_DEFINED = 0,
+ VIR_NETWORK_EVENT_UNDEFINED = 1,
+ VIR_NETWORK_EVENT_STARTED = 2,
+ VIR_NETWORK_EVENT_STOPPED = 3,
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_NETWORK_EVENT_LAST
+#endif
+} virNetworkEventLifecycleType;
+
+/**
+ * virConnectNetworkEventLifecycleCallback:
+ * @conn: connection object
+ * @net: network on which the event occurred
+ * @event: The specific virNetworkEventLifeCycleType which occurred
+ * @opaque: application specified data
+ *
+ * This callback occurs when the network is started or stopped.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_NETWORK_EVENT_ID_LIFECYCLE with virConnectNetworkEventRegisterAny()
+ */
+typedef void (*virConnectNetworkEventLifecycleCallback)(virConnectPtr conn,
+ virNetworkPtr net,
+ int event,
+ void *opaque);
+
+/**
+ * VIR_NETWORK_EVENT_CALLBACK:
+ *
+ * Used to cast the event specific callback into the generic one
+ * for use for virNetworkEventRegister
+ */
+#define VIR_NETWORK_EVENT_CALLBACK(cb) ((virConnectNetworkEventGenericCallback)(cb))
+
+typedef enum {
+ VIR_NETWORK_EVENT_ID_LIFECYCLE = 0, /* virConnectNetworkEventLifecycleCallback
*/
+
+#ifdef VIR_ENUM_SENTINELS
+ VIR_NETWORK_EVENT_ID_LAST
+ /*
+ * NB: this enum value will increase over time as new events are
+ * added to the libvirt API. It reflects the last event ID supported
+ * by this version of the libvirt API.
+ */
+#endif
+} virNetworkEventID;
+
+/*
+ * virConnectNetworkEventGenericCallback:
+ * @conn: the connection pointer
+ * @net: the network pointer
+ * @opaque: application specified data
+ *
+ * A generic network event callback handler. Specific events usually
+ * have a customization with extra parameters
+ */
+typedef void (*virConnectNetworkEventGenericCallback)(virConnectPtr conn,
+ virNetworkPtr net,
+ void *opaque);
+
+/* Use VIR_NETWORK_EVENT_CALLBACK() to cast the 'cb' parameter */
+int virConnectNetworkEventRegisterAny(virConnectPtr conn,
+ virNetworkPtr net, /* Optional, to filter */
+ int eventID,
+ virConnectNetworkEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb);
+
+int virConnectNetworkEventDeregisterAny(virConnectPtr conn,
+ int callbackID);
/**
* virNWFilter:
diff --git a/src/conf/object_event.c b/src/conf/object_event.c
index c6538c0..2d5cf8c 100644
--- a/src/conf/object_event.c
+++ b/src/conf/object_event.c
@@ -542,6 +542,41 @@ typedef void (*virObjectEventDispatchFunc)(virConnectPtr conn,
void *opaque);
+static 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,
+ cbopaque);
+ goto cleanup;
+ }
+
+#ifdef VIR_ENUM_SENTINELS
+ case VIR_NETWORK_EVENT_ID_LAST:
+ break;
+#endif
+ }
+ VIR_WARN("Unexpected event ID %d", event->eventID);
+
+cleanup:
+ virNetworkFree(net);
+}
+
+
static int virObjectEventDispatchMatchCallback(virObjectEventPtr event,
virObjectEventCallbackPtr cb)
{
@@ -650,6 +685,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);
}
@@ -806,7 +845,44 @@ virObjectEventStateEventID(virConnectPtr conn,
return ret;
}
-void *virNetworkEventLifecycleNew(int id, const char *name,
+
+/**
+ * virNetworkEventStateRegisterID:
+ * @conn: connection to associate with callback
+ * @state: object event state
+ * @net: network to filter on or NULL for all networks
+ * @eventID: ID of the event type to register for
+ * @cb: function to add to event
+ * @opaque: data blob to pass to callback
+ * @freecb: callback to free @opaque
+ * @callbackID: filled with callback ID
+ *
+ * Register the function @callbackID with connection @conn,
+ * from @state, for events of type @eventID.
+ *
+ * Returns: the number of callbacks now registered, or -1 on error
+ */
+int
+virNetworkEventStateRegisterID(virConnectPtr conn,
+ virObjectEventStatePtr state,
+ virNetworkPtr net,
+ int eventID,
+ virConnectObjectEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb,
+ int *callbackID)
+{
+ if (net)
+ return virObjectEventStateRegisterID(conn, state,
+ net->uuid, net->name, 0, eventID,
+ cb, opaque, freecb, callbackID);
+ else
+ return virObjectEventStateRegisterID(conn, state,
+ NULL, NULL, 0, eventID,
+ cb, opaque, freecb, callbackID);
+}
+
+void *virNetworkEventLifecycleNew(const char *name,
const unsigned char *uuid,
int type)
{
@@ -818,7 +894,7 @@ void *virNetworkEventLifecycleNew(int id, const char *name,
if (!(event = virObjectEventNew(virNetworkEventLifecycleClass,
eventId,
- id, name, uuid)))
+ 0, name, uuid)))
return NULL;
event->type = type;
diff --git a/src/conf/object_event.h b/src/conf/object_event.h
index 3fdd8c5..181a798 100644
--- a/src/conf/object_event.h
+++ b/src/conf/object_event.h
@@ -93,8 +93,21 @@ virObjectEventStateEventID(virConnectPtr conn,
int callbackID)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-void *virNetworkEventLifecycleNew(int id,
- const char *name,
- const unsigned char *uuid,
- int type);
+/*
+ * Network events
+ */
+
+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);
#endif
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 eff44eb..576ce96 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -19176,6 +19176,139 @@ error:
}
/**
+ * virConnectNetworkEventRegisterAny:
+ * @conn: pointer to the connection
+ * @net: pointer to the network
+ * @eventID: the event type to receive
+ * @cb: callback to the function handling network events
+ * @opaque: opaque data to pass on to the callback
+ * @freecb: optional function to deallocate opaque when not used anymore
+ *
+ * Adds a callback to receive notifications of arbitrary network events
+ * occurring on a network.
+ *
+ * If net is NULL, then events will be monitored for any network. If net
+ * is non-NULL, then only the specific network will be monitored
+ *
+ * Most types of event have a callback providing a custom set of parameters
+ * for the event. When registering an event, it is thus necessary to use
+ * the VIR_NETWORK_EVENT_CALLBACK() macro to cast the supplied function pointer
+ * to match the signature of this method.
+ *
+ * The virNetworkPtr object handle passed into the callback upon delivery
+ * of an event is only valid for the duration of execution of the callback.
+ * If the callback wishes to keep the network object after the callback
+ * returns, it shall take a reference to it, by calling virNetworkRef.
+ * The reference can be released once the object is no longer required
+ * by calling virNetworkFree.
+ *
+ * The return value from this method is a positive integer identifier
+ * for the callback. To unregister a callback, this callback ID should
+ * be passed to the virNetworkEventUnregisterAny method
+ *
+ * Returns a callback identifier on success, -1 on failure
+ */
+int
+virConnectNetworkEventRegisterAny(virConnectPtr conn,
+ virNetworkPtr net,
+ int eventID,
+ virConnectNetworkEventGenericCallback cb,
+ void *opaque,
+ virFreeCallback freecb)
+{
+ VIR_DEBUG("conn=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p",
+ conn, eventID, cb, opaque, freecb);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ if (net != NULL &&
+ !(VIR_IS_CONNECTED_NETWORK(net) && net->conn == conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(conn);
+ return -1;
+ }
+ virCheckNonNullArgGoto(cb, error);
+ virCheckNonNegativeArgGoto(eventID, error);
+ if (((eventID & 0xFF00) >> 8) != VIR_EVENT_NAMESPACE_NETWORK) {
+ virReportInvalidArg(eventID,
+ _("eventID in %s must be have network namespace flags
%d"),
+ __FUNCTION__, VIR_EVENT_NAMESPACE_NETWORK << 8);
+ goto error;
+ }
+
+#ifdef VIR_ENUM_SENTINELS
+ if ((eventID & 0xFF) >= VIR_NETWORK_EVENT_ID_LAST) {
+ virReportInvalidArg(eventID,
+ _("eventID in %s must be less than %d"),
+ __FUNCTION__, VIR_NETWORK_EVENT_ID_LAST);
+ goto error;
+ }
+#endif
+
+ if ((conn->networkDriver) &&
(conn->networkDriver->connectNetworkEventRegisterAny)) {
+ int ret;
+ ret = conn->networkDriver->connectNetworkEventRegisterAny(conn, net,
+ eventID, cb,
+ opaque,
+ freecb);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virConnectNetworkEventDeregisterAny:
+ * @conn: pointer to the connection
+ * @callbackID: the callback identifier
+ *
+ * Removes an event callback. The callbackID parameter should be the
+ * vaule obtained from a previous virNetworkEventRegisterAny method.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virConnectNetworkEventDeregisterAny(virConnectPtr conn,
+ int callbackID)
+{
+ VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ virCheckNonNegativeArgGoto(callbackID, error);
+
+ if ((conn->networkDriver) &&
+ (conn->networkDriver->connectNetworkEventDeregisterAny)) {
+ int ret;
+ ret = conn->networkDriver->connectNetworkEventDeregisterAny(conn,
+ callbackID);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
* virDomainManagedSave:
* @dom: pointer to the domain
* @flags: bitwise-OR of virDomainSaveRestoreFlags
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6977324..22ec0ab 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -622,6 +622,7 @@ 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.2