[libvirt] [PATCH 1/9] Introduce node device lifecycle event APIs

Jovanka Gulicoska jovanka.gulicoska at gmail.com
Wed Jul 20 13:50:39 UTC 2016


Node device lifecycle event API entry points for registering and deregistering
node deivce events, as well as types of events associated with node devices.
These entry points will be used for implementing asynchronous lifecycle events.

Node device API:
virConnectNodeDeviceEventRegisterAny
virConnectNodeDeviceEventDeregisterAny
virNodeDeviceEventLifecycleType which has events CREATED and DELETED
---
 include/libvirt/libvirt-nodedev.h |  90 +++++++++++++++++++++++++++
 po/POTFILES.in                    |   1 +
 src/datatypes.h                   |  13 ++++
 src/driver-nodedev.h              |  14 +++++
 src/libvirt-nodedev.c             | 127 ++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms           |   6 ++
 6 files changed, 251 insertions(+)

diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index cd0b548..8a35470 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -121,5 +121,95 @@ virNodeDevicePtr        virNodeDeviceCreateXML  (virConnectPtr conn,
 
 int                     virNodeDeviceDestroy    (virNodeDevicePtr dev);
 
+/**
+ * VIR_NODE_DEVICE_EVENT_CALLBACK:
+ *
+ * Used to cast the event specific callback into the generic one
+ * for use for virConnectNodeDeviceEventRegisterAny()
+ */
+# define VIR_NODE_DEVICE_EVENT_CALLBACK(cb)((virConnectNodeDeviceEventGenericCallback)(cb))
+
+/**
+ * virNodeDeviceEventID:
+ *
+ * An enumeration of supported eventId parameters for
+ * virConnectNodeDeviceEventRegisterAny(). Each event id determines which
+ * signature of callback function will be used.
+ */
+typedef enum {
+    VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE = 0, /* virConnectNodeDeviceEventLifecycleCallback */
+
+# ifdef VIR_ENUM_SENTINELS
+    VIR_NODE_DEVICE_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
+} virNodeDeviceEventID;
+
+/**
+ * virConnectNodeDeviceEventGenericCallback:
+ * @conn: the connection pointer
+ * @dev: the node device pointer
+ * @opaque: application specified data
+ *
+ * A generic node device event callback handler, for use with
+ * virConnectNodeDeviceEventRegisterAny(). Specific events usually
+ * have a customization with extra parameters, often with @opaque being
+ * passed in a different parameter position; use
+ * VIR_NODE_DEVICE_EVENT_CALLBACK() when registering an appropriate handler.
+ */
+typedef void (*virConnectNodeDeviceEventGenericCallback)(virConnectPtr conn,
+                                                         virNodeDevicePtr dev,
+                                                         void *opaque);
+
+/* Use VIR_NODE_DEVICE_EVENT_CALLBACK() to cast the 'cb' parameter  */
+int virConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
+                                         virNodeDevicePtr dev, /* optional, to filter */
+                                         int eventID,
+                                         virConnectNodeDeviceEventGenericCallback cb,
+                                         void *opaque,
+                                         virFreeCallback freecb);
+
+int virConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
+                                           int callbackID);
+
+/**
+ * virNodeDeviceEventLifecycleType:
+ *
+ * a virNodeDeviceEventLifecycleType is emitted during node device
+ * lifecycle events
+ */
+typedef enum {
+    VIR_NODE_DEVICE_EVENT_CREATED = 0,
+    VIR_NODE_DEVICE_EVENT_DELETED = 1,
+
+# ifdef VIR_ENUM_SENTINELS
+    VIR_NODE_DEVICE_EVENT_LAST
+# endif
+} virNodeDeviceEventLifecycleType;
+
+/**
+ * virConnectNodeDeviceEventLifecycleCallback:
+ * @conn: connection object
+ * @dev: node device on which the event occurred
+ * @event: The specific virNodeDeviceEventLifeCycleType which occurred
+ * @detail: contains some details on the reason of the event.
+ * @opaque: application specified data
+ *
+ * This callback is called when a node device lifecycle action is performed,
+ * like added, removed or changed.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE with
+ * virConnectNodeDeviceEventRegisterAny()
+ */
+typedef void (*virConnectNodeDeviceEventLifecycleCallback)(virConnectPtr conn,
+                                                           virNodeDevicePtr dev,
+                                                           int event,
+                                                           int detail,
+                                                           void *opaque);
 
 #endif /* __VIR_LIBVIRT_NODEDEV_H__ */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a6b6c9c..25dbc84 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -70,6 +70,7 @@ src/libvirt-domain.c
 src/libvirt-host.c
 src/libvirt-lxc.c
 src/libvirt-network.c
+src/libvirt-nodedev.c
 src/libvirt-nwfilter.c
 src/libvirt-qemu.c
 src/libvirt-secret.c
diff --git a/src/datatypes.h b/src/datatypes.h
index 996506b..2b6adb4 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -196,6 +196,19 @@ extern virClassPtr virAdmClientClass;
         }                                                               \
     } while (0)
 
+# define virCheckNodeDeviceGoto(obj, label)                             \
+    do {                                                                \
+        virNodeDevicePtr _dev= (obj);                                   \
+        if (!virObjectIsClass(_dev, virNodeDeviceClass) ||              \
+            !virObjectIsClass(_dev->conn, virConnectClass)) {           \
+            virReportErrorHelper(VIR_FROM_NODEDEV,                      \
+                                 VIR_ERR_INVALID_NODE_DEVICE,           \
+                                 __FILE__, __FUNCTION__, __LINE__,      \
+                                 __FUNCTION__);                         \
+            goto label;                                                 \
+        }                                                               \
+    } while (0)
+
 # define virCheckSecretReturn(obj, retval)                              \
     do {                                                                \
         virSecretPtr _secret = (obj);                                   \
diff --git a/src/driver-nodedev.h b/src/driver-nodedev.h
index e846612..5eae239 100644
--- a/src/driver-nodedev.h
+++ b/src/driver-nodedev.h
@@ -75,6 +75,18 @@ typedef virNodeDevicePtr
 typedef int
 (*virDrvNodeDeviceDestroy)(virNodeDevicePtr dev);
 
+typedef int
+(*virDrvConnectNodeDeviceEventRegisterAny)(virConnectPtr conn,
+                                           virNodeDevicePtr dev,
+                                           int eventID,
+                                           virConnectNodeDeviceEventGenericCallback cb,
+                                           void *opaque,
+                                           virFreeCallback freecb);
+
+typedef int
+(*virDrvConnectNodeDeviceEventDeregisterAny)(virConnectPtr conn,
+                                             int callbackID);
+
 
 
 typedef struct _virNodeDeviceDriver virNodeDeviceDriver;
@@ -92,6 +104,8 @@ struct _virNodeDeviceDriver {
     virDrvNodeNumOfDevices nodeNumOfDevices;
     virDrvNodeListDevices nodeListDevices;
     virDrvConnectListAllNodeDevices connectListAllNodeDevices;
+    virDrvConnectNodeDeviceEventRegisterAny connectNodeDeviceEventRegisterAny;
+    virDrvConnectNodeDeviceEventDeregisterAny connectNodeDeviceEventDeregisterAny;
     virDrvNodeDeviceLookupByName nodeDeviceLookupByName;
     virDrvNodeDeviceLookupSCSIHostByWWN nodeDeviceLookupSCSIHostByWWN;
     virDrvNodeDeviceGetXMLDesc nodeDeviceGetXMLDesc;
diff --git a/src/libvirt-nodedev.c b/src/libvirt-nodedev.c
index c1ca575..8658b71 100644
--- a/src/libvirt-nodedev.c
+++ b/src/libvirt-nodedev.c
@@ -753,3 +753,130 @@ virNodeDeviceDestroy(virNodeDevicePtr dev)
     virDispatchError(dev->conn);
     return -1;
 }
+
+
+/**
+ * virConnectNodeDeviceEventRegisterAny:
+ * @conn: pointer to the connection
+ * @dev: pointer to the node device
+ * @eventID: the event type to receive
+ * @cb: callback to the function handling node device 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 node device events
+ * occurring on a node device. This function requires that an event loop
+ * has been previously registered with virEventRegisterImpl() or
+ * virEventRegisterDefaultImpl().
+ *
+ * If @dev is NULL, then events will be monitored for any node device.
+ * If @dev is non-NULL, then only the specific node device will be monitored.
+ *
+ * Most types of events have a callback providing a custom set of parameters
+ * for the event. When registering an event, it is thus necessary to use
+ * the VIR_NODE_DEVICE_EVENT_CALLBACK() macro to cast the
+ * supplied function pointer to match the signature of this method.
+ *
+ * The virNodeDevicePtr 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 node device object after the callback
+ * returns, it shall take a reference to it, by calling virNodeDeviceRef().
+ * The reference can be released once the object is no longer required
+ * by calling virNodeDeviceFree().
+ *
+ * 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 virConnectNodeDeviceEventDeregisterAny() method.
+ *
+ * Returns a callback identifier on success, -1 on failure.
+ */
+int
+virConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
+                                     virNodeDevicePtr dev,
+                                     int eventID,
+                                     virConnectNodeDeviceEventGenericCallback cb,
+                                     void *opaque,
+                                     virFreeCallback freecb)
+{
+    VIR_DEBUG("conn=%p, nodeDevice=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p",
+              conn, dev, eventID, cb, opaque, freecb);
+
+    virResetLastError();
+
+    virCheckConnectReturn(conn, -1);
+    if (dev) {
+        virCheckNodeDeviceGoto(dev, error);
+        if (dev->conn != conn) {
+            virReportInvalidArg(dev,
+                                _("node device '%s' in %s must match connection"),
+                                dev->name, __FUNCTION__);
+            goto error;
+        }
+    }
+    virCheckNonNullArgGoto(cb, error);
+    virCheckNonNegativeArgGoto(eventID, error);
+
+    if (eventID >= VIR_NODE_DEVICE_EVENT_ID_LAST) {
+        virReportInvalidArg(eventID,
+                            _("eventID in %s must be less than %d"),
+                            __FUNCTION__, VIR_STORAGE_POOL_EVENT_ID_LAST);
+        goto error;
+    }
+
+    if (conn->nodeDeviceDriver &&
+        conn->nodeDeviceDriver->connectNodeDeviceEventRegisterAny) {
+        int ret;
+        ret = conn->nodeDeviceDriver->connectNodeDeviceEventRegisterAny(conn,
+                                                                        dev,
+                                                                        eventID,
+                                                                        cb,
+                                                                        opaque,
+                                                                        freecb);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
+
+
+/**
+ * virConnectNodeDeviceEventDeregisterAny:
+ * @conn: pointer to the connection
+ * @callbackID: the callback identifier
+ *
+ * Removes an event callback. The callbackID parameter should be the
+ * value obtained from a previous virConnectNodeDeviceEventRegisterAny() method.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+virConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
+                                       int callbackID)
+{
+    VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID);
+
+    virResetLastError();
+
+    virCheckConnectReturn(conn, -1);
+    virCheckNonNegativeArgGoto(callbackID, error);
+
+    if (conn->nodeDeviceDriver &&
+        conn->nodeDeviceDriver->connectNodeDeviceEventDeregisterAny) {
+        int ret;
+        ret = conn->nodeDeviceDriver->connectNodeDeviceEventDeregisterAny(conn,
+                                                                          callbackID);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index b6d2dfd..9722b93 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -740,4 +740,10 @@ LIBVIRT_2.0.0 {
         virDomainSetGuestVcpus;
 } LIBVIRT_1.3.3;
 
+LIBVIRT_2.1.0 {
+    global:
+        virConnectNodeDeviceEventRegisterAny;
+        virConnectNodeDeviceEventDeregisterAny;
+} LIBVIRT_2.0.0;
+
 # .... define new API here using predicted next version number ....
-- 
2.7.4




More information about the libvir-list mailing list