[libvirt] [PATCH 28/34] Added API for network events similar to the one from Domain events

Cédric Bosdonnat cbosdonnat at suse.com
Fri Nov 29 15:19:04 UTC 2013


---
 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




More information about the libvir-list mailing list