Add public APIs to allow applications to watch for define and undefine of secret objects.
Signed-off-by: Daniel P. Berrange <berra...@redhat.com> --- include/libvirt/libvirt-secret.h | 91 +++++++++++++++++++++++++++ src/datatypes.h | 14 +++++ src/driver-secret.h | 14 +++++ src/libvirt-secret.c | 129 +++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 2 + 5 files changed, 250 insertions(+) diff --git a/include/libvirt/libvirt-secret.h b/include/libvirt/libvirt-secret.h index 2ae36f6..1bbbf3f 100644 --- a/include/libvirt/libvirt-secret.h +++ b/include/libvirt/libvirt-secret.h @@ -110,5 +110,96 @@ int virSecretUndefine (virSecretPtr secret); int virSecretRef (virSecretPtr secret); int virSecretFree (virSecretPtr secret); +/** + * VIR_SECRET_EVENT_CALLBACK: + * + * Used to cast the event specific callback into the generic one + * for use for virConnectSecretEventRegisterAny() + */ +# define VIR_SECRET_EVENT_CALLBACK(cb)((virConnectSecretEventGenericCallback)(cb)) + +/** + * virSecretEventID: + * + * An enumeration of supported eventId parameters for + * virConnectSecretEventRegisterAny(). Each event id determines which + * signature of callback function will be used. + */ +typedef enum { + VIR_SECRET_EVENT_ID_LIFECYCLE = 0, /* virConnectSecretEventLifecycleCallback */ + +# ifdef VIR_ENUM_SENTINELS + VIR_SECRET_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 +} virSecretEventID; + +/** + * virConnectSecretEventGenericCallback: + * @conn: the connection pointer + * @secret: the secret pointer + * @opaque: application specified data + * + * A generic secret event callback handler, for use with + * virConnectSecretEventRegisterAny(). Specific events usually + * have a customization with extra parameters, often with @opaque being + * passed in a different parameter position; use + * VIR_SECRET_EVENT_CALLBACK() when registering an appropriate handler. + */ +typedef void (*virConnectSecretEventGenericCallback)(virConnectPtr conn, + virSecretPtr secret, + void *opaque); + +/* Use VIR_SECRET_EVENT_CALLBACK() to cast the 'cb' parameter */ +int virConnectSecretEventRegisterAny(virConnectPtr conn, + virSecretPtr secret, /* optional, to filter */ + int eventID, + virConnectSecretEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); + +int virConnectSecretEventDeregisterAny(virConnectPtr conn, + int callbackID); + +/** + * virSecretEventLifecycleType: + * + * a virSecretEventLifecycleType is emitted during secret + * lifecycle events + */ +typedef enum { + VIR_SECRET_EVENT_DEFINED = 0, + VIR_SECRET_EVENT_UNDEFINED = 1, + +# ifdef VIR_ENUM_SENTINELS + VIR_SECRET_EVENT_LAST +# endif +} virSecretEventLifecycleType; + +/** + * virConnectSecretEventLifecycleCallback: + * @conn: connection object + * @secret: secret on which the event occurred + * @event: The specific virSecretEventLifeCycleType which occurred + * @detail: contains some details on the reason of the event. + * @opaque: application specified data + * + * This callback is called when a secret lifecycle action is performed, + * like added or removed. + * + * The callback signature to use when registering for an event of type + * VIR_SECRET_EVENT_ID_LIFECYCLE with + * virConnectSecretEventRegisterAny() + */ +typedef void (*virConnectSecretEventLifecycleCallback)(virConnectPtr conn, + virSecretPtr secret, + int event, + int detail, + void *opaque); + #endif /* __VIR_LIBVIRT_SECRET_H__ */ diff --git a/src/datatypes.h b/src/datatypes.h index 9a5fbbc..5830482 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -223,6 +223,20 @@ extern virClassPtr virAdmClientClass; } \ } while (0) +# define virCheckSecretGoto(obj, label) \ + do { \ + virSecretPtr _secret = (obj); \ + if (!virObjectIsClass(_secret, virSecretClass) || \ + !virObjectIsClass(_secret->conn, virConnectClass)) { \ + virReportErrorHelper(VIR_FROM_SECRET, \ + VIR_ERR_INVALID_SECRET, \ + __FILE__, __FUNCTION__, __LINE__, \ + __FUNCTION__); \ + virDispatchError(NULL); \ + goto label; \ + } \ + } while (0) + # define virCheckStreamReturn(obj, retval) \ do { \ virStreamPtr _st = (obj); \ diff --git a/src/driver-secret.h b/src/driver-secret.h index c39e0d7..3cd9034 100644 --- a/src/driver-secret.h +++ b/src/driver-secret.h @@ -77,6 +77,18 @@ typedef int virSecretPtr **secrets, unsigned int flags); +typedef int +(*virDrvConnectSecretEventRegisterAny)(virConnectPtr conn, + virSecretPtr secret, + int eventID, + virConnectSecretEventGenericCallback cb, + void *opaque, + virFreeCallback freecb); + +typedef int +(*virDrvConnectSecretEventDeregisterAny)(virConnectPtr conn, + int callbackID); + typedef struct _virSecretDriver virSecretDriver; typedef virSecretDriver *virSecretDriverPtr; @@ -98,6 +110,8 @@ struct _virSecretDriver { virDrvSecretSetValue secretSetValue; virDrvSecretGetValue secretGetValue; virDrvSecretUndefine secretUndefine; + virDrvConnectSecretEventRegisterAny connectSecretEventRegisterAny; + virDrvConnectSecretEventDeregisterAny connectSecretEventDeregisterAny; }; diff --git a/src/libvirt-secret.c b/src/libvirt-secret.c index db42aec..8a99c8c 100644 --- a/src/libvirt-secret.c +++ b/src/libvirt-secret.c @@ -693,3 +693,132 @@ virSecretFree(virSecretPtr secret) virObjectUnref(secret); return 0; } + + +/** + * virConnectSecretEventRegisterAny: + * @conn: pointer to the connection + * @secret: pointer to the secret + * @eventID: the event type to receive + * @cb: callback to the function handling secret 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 secret events + * occurring on a secret. This function requires that an event loop + * has been previously registered with virEventRegisterImpl() or + * virEventRegisterDefaultImpl(). + * + * If @secret is NULL, then events will be monitored for any secret. + * If @secret is non-NULL, then only the specific secret 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_SECRET_EVENT_CALLBACK() macro to cast the + * supplied function pointer to match the signature of this method. + * + * The virSecretPtr 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 secret object after the callback + * returns, it shall take a reference to it, by calling virSecretRef(). + * The reference can be released once the object is no longer required + * by calling virSecretFree(). + * + * 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 virConnectSecretEventDeregisterAny() method. + * + * Returns a callback identifier on success, -1 on failure. + */ +int +virConnectSecretEventRegisterAny(virConnectPtr conn, + virSecretPtr secret, + int eventID, + virConnectSecretEventGenericCallback cb, + void *opaque, + virFreeCallback freecb) +{ + VIR_DEBUG("conn=%p, secret=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p", + conn, secret, eventID, cb, opaque, freecb); + + virResetLastError(); + + virCheckConnectReturn(conn, -1); + if (secret) { + virCheckSecretGoto(secret, error); + if (secret->conn != conn) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(secret->uuid, uuidstr); + virReportInvalidArg(secret, + _("secret '%s' in %s must match connection"), + uuidstr, __FUNCTION__); + goto error; + } + } + virCheckNonNullArgGoto(cb, error); + virCheckNonNegativeArgGoto(eventID, error); + + if (eventID >= VIR_SECRET_EVENT_ID_LAST) { + virReportInvalidArg(eventID, + _("eventID in %s must be less than %d"), + __FUNCTION__, VIR_SECRET_EVENT_ID_LAST); + goto error; + } + + if (conn->secretDriver && + conn->secretDriver->connectSecretEventRegisterAny) { + int ret; + ret = conn->secretDriver->connectSecretEventRegisterAny(conn, + secret, + eventID, + cb, + opaque, + freecb); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return -1; +} + + +/** + * virConnectSecretEventDeregisterAny: + * @conn: pointer to the connection + * @callbackID: the callback identifier + * + * Removes an event callback. The callbackID parameter should be the + * value obtained from a previous virConnectSecretEventRegisterAny() method. + * + * Returns 0 on success, -1 on failure. + */ +int +virConnectSecretEventDeregisterAny(virConnectPtr conn, + int callbackID) +{ + VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID); + + virResetLastError(); + + virCheckConnectReturn(conn, -1); + virCheckNonNegativeArgGoto(callbackID, error); + + if (conn->secretDriver && + conn->secretDriver->connectSecretEventDeregisterAny) { + int ret; + ret = conn->secretDriver->connectSecretEventDeregisterAny(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 12ef085..62885ac 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -749,6 +749,8 @@ LIBVIRT_2.2.0 { LIBVIRT_3.0.0 { global: virStorageVolGetInfoFlags; + virConnectSecretEventRegisterAny; + virConnectSecretEventDeregisterAny; } LIBVIRT_2.2.0; # .... define new API here using predicted next version number .... -- 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list