diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index db6f2b498f89a8bd3a78ce3e87ebe06f4e37127f..a67a97f3f3f4248268a8ff2af886f0c48f840d59 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -377,5 +377,98 @@ int virStorageVolResize (virStorageVolPtr vol, int virStoragePoolIsActive(virStoragePoolPtr pool); int virStoragePoolIsPersistent(virStoragePoolPtr pool); +/** + * VIR_STORAGE_POOL_EVENT_CALLBACK: + * + * Used to cast the event specific callback into the generic one + * for use for virConnectStoragePoolEventRegisterAny() + */ +# define VIR_STORAGE_POOL_EVENT_CALLBACK(cb)((virConnectStoragePoolEventGenericCallback)(cb)) + +/** + * virStoragePoolEventID: + * + * An enumeration of supported eventId parameters for + * virConnectStoragePoolEventRegisterAny(). Each event id determines which + * signature of callback function will be used. + */ +typedef enum { + VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE = 0, /* virConnectStoragePoolEventLifecycleCallback */ + +# ifdef VIR_ENUM_SENTINELS + VIR_STORAGE_POOL_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 +} virStoragePoolEventID; + +/** + * virConnectStoragePoolEventGenericCallback: + * @conn: the connection pointer + * @pool: the pool pointer + * @opaque: application specified data + * + * A generic storage pool event callback handler, for use with + * virConnectStoragePoolEventRegisterAny(). Specific events usually + * have a customization with extra parameters, often with @opaque being + * passed in a different parameter position; use + * VIR_STORAGE_POOL_EVENT_CALLBACK() when registering an appropriate handler. + */ +typedef void (*virConnectStoragePoolEventGenericCallback)(virConnectPtr conn, + virStoragePoolPtr pool, + void *opaque); + +/* Use VIR_STORAGE_POOL_EVENT_CALLBACK() to cast the 'cb' parameter */ +int virConnectStoragePoolEventRegisterAny(virConnectPtr conn, + virStoragePoolPtr pool, /* optional, to filter */ + int eventID, + virConnectStoragePoolEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); + +int virConnectStoragePoolEventDeregisterAny(virConnectPtr conn, + int callbackID); + +/** + * virStoragePoolEventLifecycleType: + * + * a virStoragePoolEventLifecycleType is emitted during storage pool + * lifecycle events + */ +typedef enum { + VIR_STORAGE_POOL_EVENT_DEFINED = 0, + VIR_STORAGE_POOL_EVENT_UNDEFINED = 1, + VIR_STORAGE_POOL_EVENT_STARTED = 2, + VIR_STORAGE_POOL_EVENT_STOPPED = 3, + VIR_STORAGE_POOL_EVENT_REFRESHED = 4, + +# ifdef VIR_ENUM_SENTINELS + VIR_STORAGE_POOL_EVENT_LAST +# endif +} virStoragePoolEventLifecycleType; + +/** + * virConnectStoragePoolEventLifecycleCallback: + * @conn: connection object + * @pool: pool on which the event occurred + * @event: The specific virStoragePoolEventLifeCycleType which occurred + * @detail: contains some details on the reason of the event. + * @opaque: application specified data + * + * This callback is called when a pool lifecycle action is performed, like start + * or stop. + * + * The callback signature to use when registering for an event of type + * VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE with + * virConnectStoragePoolEventRegisterAny() + */ +typedef void (*virConnectStoragePoolEventLifecycleCallback)(virConnectPtr conn, + virStoragePoolPtr pool, + int event, + int detail, + void *opaque); #endif /* __VIR_LIBVIRT_STORAGE_H__ */ diff --git a/src/datatypes.h b/src/datatypes.h index 8ccc7b02eceabf66c528b2e80337bccb219e7641..996506b6d57adfe047eca1562c6cdb204a4970d3 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -143,6 +143,19 @@ extern virClassPtr virAdmClientClass; } \ } while (0) +# define virCheckStoragePoolGoto(obj, label) \ + do { \ + virStoragePoolPtr _pool= (obj); \ + if (!virObjectIsClass(_pool, virStoragePoolClass) || \ + !virObjectIsClass(_pool->conn, virConnectClass)) { \ + virReportErrorHelper(VIR_FROM_STORAGE, \ + VIR_ERR_INVALID_STORAGE_POOL, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + goto label; \ + } \ + } while (0) + # define virCheckStorageVolReturn(obj, retval) \ do { \ virStorageVolPtr _vol = (obj); \ diff --git a/src/driver-storage.h b/src/driver-storage.h index 0489647a9159e04d487d59367ccf50e2a8005afb..afcb12bc84bada971d84cfcb15155890aaef1256 100644 --- a/src/driver-storage.h +++ b/src/driver-storage.h @@ -196,6 +196,17 @@ typedef int typedef int (*virDrvStoragePoolIsPersistent)(virStoragePoolPtr pool); +typedef int +(*virDrvConnectStoragePoolEventRegisterAny)(virConnectPtr conn, + virStoragePoolPtr pool, + int eventID, + virConnectStoragePoolEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); + +typedef int +(*virDrvConnectStoragePoolEventDeregisterAny)(virConnectPtr conn, + int callbackID); typedef struct _virStorageDriver virStorageDriver; @@ -215,6 +226,8 @@ struct _virStorageDriver { virDrvConnectListDefinedStoragePools connectListDefinedStoragePools; virDrvConnectListAllStoragePools connectListAllStoragePools; virDrvConnectFindStoragePoolSources connectFindStoragePoolSources; + virDrvConnectStoragePoolEventRegisterAny connectStoragePoolEventRegisterAny; + virDrvConnectStoragePoolEventDeregisterAny connectStoragePoolEventDeregisterAny; virDrvStoragePoolLookupByName storagePoolLookupByName; virDrvStoragePoolLookupByUUID storagePoolLookupByUUID; virDrvStoragePoolLookupByVolume storagePoolLookupByVolume; diff --git a/src/libvirt-storage.c b/src/libvirt-storage.c index 1ce67455bb8872329677db49821ac94555326a29..cebe02fdda66ef8a973ba573aa4d108327779146 100644 --- a/src/libvirt-storage.c +++ b/src/libvirt-storage.c @@ -2124,3 +2124,128 @@ virStoragePoolIsPersistent(virStoragePoolPtr pool) virDispatchError(pool->conn); return -1; } + +/** + * virConnectStoragePoolEventRegisterAny: + * @conn: pointer to the connection + * @pool: pointer to the storage pool + * @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 storage pool events + * occurring on a storage pool. This function requires that an event loop + * has been previously registered with virEventRegisterImpl() or + * virEventRegisterDefaultImpl(). + * + * If @pool is NULL, then events will be monitored for any storage pool. + * If @pool is non-NULL, then only the specific storage pool 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_STORAGE_POOL_EVENT_CALLBACK() macro to cast the + * supplied function pointer to match the signature of this method. + * + * The virStoragePoolPtr 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 storage pool object after the callback + * returns, it shall take a reference to it, by calling virStoragePoolRef(). + * The reference can be released once the object is no longer required + * by calling virStoragePoolFree(). + * + * 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 virConnectStoragePoolEventDeregisterAny() method. + * + * Returns a callback identifier on success, -1 on failure. + */ +int +virConnectStoragePoolEventRegisterAny(virConnectPtr conn, + virStoragePoolPtr pool, + int eventID, + virConnectStoragePoolEventGenericCallback cb, + void *opaque, + virFreeCallback freecb) +{ + VIR_DEBUG("conn=%p, pool=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p", + conn, pool, eventID, cb, opaque, freecb); + + virResetLastError(); + + virCheckConnectReturn(conn, -1); + if (pool) { + virCheckStoragePoolGoto(pool, error); + if (pool->conn != conn) { + virReportInvalidArg(pool, + _("storage pool '%s' in %s must match connection"), + pool->name, __FUNCTION__); + goto error; + } + } + virCheckNonNullArgGoto(cb, error); + virCheckNonNegativeArgGoto(eventID, error); + + if (eventID >= VIR_STORAGE_POOL_EVENT_ID_LAST) { + virReportInvalidArg(eventID, + _("eventID in %s must be less than %d"), + __FUNCTION__, VIR_STORAGE_POOL_EVENT_ID_LAST); + goto error; + } + + if (conn->storageDriver && + conn->storageDriver->connectStoragePoolEventRegisterAny) { + int ret; + ret = conn->storageDriver->connectStoragePoolEventRegisterAny(conn, + pool, + eventID, + cb, + opaque, + freecb); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return -1; +} + +/** + * virConnectStoragePoolEventDeregisterAny: + * @conn: pointer to the connection + * @callbackID: the callback identifier + * + * Removes an event callback. The callbackID parameter should be the + * value obtained from a previous virConnectStoragePoolEventRegisterAny() method. + * + * Returns 0 on success, -1 on failure + */ +int +virConnectStoragePoolEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID); + + virResetLastError(); + + virCheckConnectReturn(conn, -1); + virCheckNonNegativeArgGoto(callbackID, error); + + if (conn->storageDriver && + conn->storageDriver->connectStoragePoolEventDeregisterAny) { + int ret; + ret = conn->storageDriver->connectStoragePoolEventDeregisterAny(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 1e920d6e68903784146b70ed4c21f7c5a22459b3..06011ce489e9a3140fb33f1fb00e318b2f74fab8 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -732,4 +732,10 @@ LIBVIRT_1.3.3 { virDomainSetPerfEvents; } LIBVIRT_1.2.19; +LIBVIRT_2.0.0 { + global: + virConnectStoragePoolEventRegisterAny; + virConnectStoragePoolEventDeregisterAny; +} LIBVIRT_1.3.3; + # .... define new API here using predicted next version number ....