[libvirt] [PATCH 9/9] secret: add support for value change events
Michal Privoznik
mprivozn at redhat.com
Fri Jan 6 15:02:45 UTC 2017
On 01/05/2017 02:59 PM, Daniel P. Berrange wrote:
> Emit an event whenever a secret value changes
>
> Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
> ---
> daemon/remote.c | 29 ++++++++++++++++++++
> include/libvirt/libvirt-secret.h | 1 +
> src/conf/secret_event.c | 59 ++++++++++++++++++++++++++++++++++++++++
> src/conf/secret_event.h | 4 +++
> src/libvirt_private.syms | 1 +
> src/remote/remote_driver.c | 30 ++++++++++++++++++++
> src/remote/remote_protocol.x | 13 ++++++++-
> src/secret/secret_driver.c | 6 ++++
> tools/virsh-secret.c | 35 ++++++++++++++++++++++++
> 9 files changed, 177 insertions(+), 1 deletion(-)
>
> diff --git a/daemon/remote.c b/daemon/remote.c
> index 3a7ee9e..f2b9b9a 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -1528,8 +1528,37 @@ remoteRelaySecretEventLifecycle(virConnectPtr conn,
> return 0;
> }
>
> +static int
> +remoteRelaySecretEventValueChanged(virConnectPtr conn,
> + virSecretPtr secret,
> + void *opaque)
> +{
> + daemonClientEventCallbackPtr callback = opaque;
> + remote_secret_event_value_changed_msg data;
> +
> + if (callback->callbackID < 0 ||
> + !remoteRelaySecretEventCheckACL(callback->client, conn, secret))
> + return -1;
> +
> + VIR_DEBUG("Relaying node secret value changed callback %d",
> + callback->callbackID);
> +
> + /* build return data */
> + memset(&data, 0, sizeof(data));
> + make_nonnull_secret(&data.secret, secret);
> + data.callbackID = callback->callbackID;
> +
> + remoteDispatchObjectEventSend(callback->client, remoteProgram,
> + REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED,
> + (xdrproc_t)xdr_remote_secret_event_value_changed_msg,
> + &data);
> +
> + return 0;
> +}
> +
> static virConnectSecretEventGenericCallback secretEventCallbacks[] = {
> VIR_SECRET_EVENT_CALLBACK(remoteRelaySecretEventLifecycle),
> + VIR_SECRET_EVENT_CALLBACK(remoteRelaySecretEventValueChanged),
> };
>
> verify(ARRAY_CARDINALITY(secretEventCallbacks) == VIR_SECRET_EVENT_ID_LAST);
> diff --git a/include/libvirt/libvirt-secret.h b/include/libvirt/libvirt-secret.h
> index 1bbbf3f..5df0b8f 100644
> --- a/include/libvirt/libvirt-secret.h
> +++ b/include/libvirt/libvirt-secret.h
> @@ -127,6 +127,7 @@ int virSecretFree (virSecretPtr secret);
> */
> typedef enum {
> VIR_SECRET_EVENT_ID_LIFECYCLE = 0, /* virConnectSecretEventLifecycleCallback */
> + VIR_SECRET_EVENT_ID_VALUE_CHANGED = 1, /* virConnectSecretEventGenericCallback */
>
> # ifdef VIR_ENUM_SENTINELS
> VIR_SECRET_EVENT_ID_LAST
> diff --git a/src/conf/secret_event.c b/src/conf/secret_event.c
> index 9d578f0..c130909 100644
> --- a/src/conf/secret_event.c
> +++ b/src/conf/secret_event.c
> @@ -48,10 +48,19 @@ struct _virSecretEventLifecycle {
> typedef struct _virSecretEventLifecycle virSecretEventLifecycle;
> typedef virSecretEventLifecycle *virSecretEventLifecyclePtr;
>
> +struct _virSecretEventValueChanged {
> + virSecretEvent parent;
> + bool dummy;
> +};
> +typedef struct _virSecretEventValueChanged virSecretEventValueChanged;
> +typedef virSecretEventValueChanged *virSecretEventValueChangedPtr;
> +
> static virClassPtr virSecretEventClass;
> static virClassPtr virSecretEventLifecycleClass;
> +static virClassPtr virSecretEventValueChangedClass;
> static void virSecretEventDispose(void *obj);
> static void virSecretEventLifecycleDispose(void *obj);
> +static void virSecretEventValueChangedDispose(void *obj);
>
> static int
> virSecretEventsOnceInit(void)
> @@ -68,6 +77,12 @@ virSecretEventsOnceInit(void)
> sizeof(virSecretEventLifecycle),
> virSecretEventLifecycleDispose)))
> return -1;
> + if (!(virSecretEventValueChangedClass =
> + virClassNew(virSecretEventClass,
> + "virSecretEventValueChanged",
> + sizeof(virSecretEventValueChanged),
> + virSecretEventValueChangedDispose)))
> + return -1;
> return 0;
> }
>
> @@ -90,6 +105,14 @@ virSecretEventLifecycleDispose(void *obj)
>
>
> static void
> +virSecretEventValueChangedDispose(void *obj)
> +{
> + virSecretEventValueChangedPtr event = obj;
> + VIR_DEBUG("obj=%p", event);
> +}
> +
> +
> +static void
> virSecretEventDispatchDefaultFunc(virConnectPtr conn,
> virObjectEventPtr event,
> virConnectObjectEventGenericCallback cb,
> @@ -116,6 +139,13 @@ virSecretEventDispatchDefaultFunc(virConnectPtr conn,
> goto cleanup;
> }
>
> + case VIR_SECRET_EVENT_ID_VALUE_CHANGED:
> + {
> + ((virConnectSecretEventGenericCallback)cb)(conn, secret,
> + cbopaque);
> + goto cleanup;
> + }
> +
> case VIR_SECRET_EVENT_ID_LAST:
> break;
> }
> @@ -250,3 +280,32 @@ virSecretEventLifecycleNew(const unsigned char *uuid,
>
> return (virObjectEventPtr)event;
> }
> +
> +
> +/**
> + * virSecretEventValueChangedNew:
> + * @uuid: UUID of the secret object the event describes
> + *
> + * Create a new secret lifecycle event.
> + */
> +virObjectEventPtr
> +virSecretEventValueChangedNew(const unsigned char *uuid,
> + int usage_type,
> + const char *usage_id)
> +{
> + virSecretEventValueChangedPtr event;
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> +
> + if (virSecretEventsInitialize() < 0)
> + return NULL;
> +
> + virUUIDFormat(uuid, uuidstr);
> + VIR_DEBUG("Event %s %d %s", uuidstr, usage_type, usage_id);
> + if (!(event = virObjectEventNew(virSecretEventValueChangedClass,
> + virSecretEventDispatchDefaultFunc,
> + VIR_SECRET_EVENT_ID_VALUE_CHANGED,
> + usage_type, usage_id, uuid, uuidstr)))
> + return NULL;
> +
> + return (virObjectEventPtr)event;
> +}
> diff --git a/src/conf/secret_event.h b/src/conf/secret_event.h
> index 4649d94..5fd52f3 100644
> --- a/src/conf/secret_event.h
> +++ b/src/conf/secret_event.h
> @@ -57,5 +57,9 @@ virSecretEventLifecycleNew(const unsigned char *uuid,
> const char *usage_id,
> int type,
> int detail);
> +virObjectEventPtr
> +virSecretEventValueChangedNew(const unsigned char *uuid,
> + int usage_type,
> + const char *usage_id);
>
> #endif
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 2c78ed6..3d98780 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -842,6 +842,7 @@ virSecretUsageTypeToString;
> # conf/secret_event.h
> virSecretEventLifecycleNew;
> virSecretEventStateRegisterID;
> +virSecretEventValueChangedNew;
>
>
> # conf/snapshot_conf.h
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index e689316..59d74a2 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -391,6 +391,11 @@ remoteSecretBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> void *evdata, void *opaque);
>
> static void
> +remoteSecretBuildEventValueChanged(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> + virNetClientPtr client ATTRIBUTE_UNUSED,
> + void *evdata, void *opaque);
> +
> +static void
> remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque);
> @@ -593,6 +598,10 @@ static virNetClientProgramEvent remoteEvents[] = {
> remoteSecretBuildEventLifecycle,
> sizeof(remote_secret_event_lifecycle_msg),
> (xdrproc_t)xdr_remote_secret_event_lifecycle_msg },
> + { REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED,
> + remoteSecretBuildEventValueChanged,
> + sizeof(remote_secret_event_value_changed_msg),
> + (xdrproc_t)xdr_remote_secret_event_value_changed_msg },
> };
>
> static void
> @@ -5517,6 +5526,27 @@ remoteSecretBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> }
>
> static void
> +remoteSecretBuildEventValueChanged(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> + virNetClientPtr client ATTRIBUTE_UNUSED,
> + void *evdata, void *opaque)
> +{
> + virConnectPtr conn = opaque;
> + struct private_data *priv = conn->privateData;
> + remote_secret_event_value_changed_msg *msg = evdata;
> + virSecretPtr secret;
> + virObjectEventPtr event = NULL;
> +
> + secret = get_nonnull_secret(conn, msg->secret);
> + if (!secret)
> + return;
> +
> + event = virSecretEventValueChangedNew(secret->uuid, secret->usageType, secret->usageID);
> + virObjectUnref(secret);
> +
> + remoteEventQueue(priv, event, msg->callbackID);
> +}
> +
> +static void
> remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque)
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index ce4c4ef..6445685 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -3381,6 +3381,11 @@ struct remote_secret_event_lifecycle_msg {
> int detail;
> };
>
> +struct remote_secret_event_value_changed_msg {
> + int callbackID;
> + remote_nonnull_secret secret;
> +};
> +
> /*----- Protocol. -----*/
>
> /* Define the program number, protocol version and procedure numbers here. */
> @@ -6007,6 +6012,12 @@ enum remote_procedure {
> * @generate: both
> * @acl: none
> */
> - REMOTE_PROC_SECRET_EVENT_LIFECYCLE = 382
> + REMOTE_PROC_SECRET_EVENT_LIFECYCLE = 382,
> +
> + /**
> + * @generate: both
> + * @acl: none
> + */
> + REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383
>
> };
> diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
> index 0e3d97e..2a371b6 100644
> --- a/src/secret/secret_driver.c
> +++ b/src/secret/secret_driver.c
> @@ -327,6 +327,7 @@ secretSetValue(virSecretPtr obj,
> int ret = -1;
> virSecretObjPtr secret;
> virSecretDefPtr def;
> + virObjectEventPtr event = NULL;
>
> virCheckFlags(0, -1);
>
> @@ -343,10 +344,15 @@ secretSetValue(virSecretPtr obj,
> if (virSecretObjSetValue(secret, value, value_size) < 0)
> goto cleanup;
>
> + event = virSecretEventValueChangedNew(def->uuid,
> + def->usage_type,
> + def->usage_id);
> ret = 0;
>
> cleanup:
> virSecretObjEndAPI(&secret);
> + if (event)
> + virObjectEventStateQueue(driver->secretEventState, event);
>
> return ret;
> }
> diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c
> index f7197f4..cd788b6 100644
> --- a/tools/virsh-secret.c
> +++ b/tools/virsh-secret.c
> @@ -614,9 +614,44 @@ vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> vshEventDone(data->ctl);
> }
>
> +static void
> +vshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virSecretPtr secret,
> + void *opaque)
> +{
> + virshSecretEventData *data = opaque;
> + char uuid[VIR_UUID_STRING_BUFLEN];
> +
> + if (!data->loop && data->count)
> + return;
> +
> + virSecretGetUUIDString(secret, uuid);
> +
> + if (data->timestamp) {
> + char timestamp[VIR_TIME_STRING_BUFLEN];
> +
> + if (virTimeStringNowRaw(timestamp) < 0)
> + timestamp[0] = '\0';
> +
> + vshPrint(data->ctl, _("%s: event '%s' for secret %s\n"),
> + timestamp,
> + data->cb->name,
> + uuid);
> + } else {
> + vshPrint(data->ctl, _("event '%s' for secret %s\n"),
> + data->cb->name,
> + uuid);
> + }
> +
> + data->count++;
> + if (!data->loop)
> + vshEventDone(data->ctl);
> +}
> +
> static vshEventCallback vshEventCallbacks[] = {
> { "lifecycle",
> VIR_SECRET_EVENT_CALLBACK(vshEventLifecyclePrint), },
> + { "value-changed", vshEventGenericPrint, },
We advise users to wrap their callbacks with VIR_SECRET_EVENT_CALLBACK() macro. We should follow our own advices.
> };
>
> static const vshCmdInfo info_secret_event[] = {
>
Also, looks like there's something missing:
object-events/event-test.c:1094:1: note: in expansion of macro 'verify'
verify(ARRAY_CARDINALITY(secretEvents) == VIR_SECRET_EVENT_ID_LAST);
^
Perhaps this?
diff --git i/examples/object-events/event-test.c w/examples/object-events/event-test.c
index cf8c1bca2..55c004f93 100644
--- i/examples/object-events/event-test.c
+++ w/examples/object-events/event-test.c
@@ -763,6 +763,18 @@ mySecretEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
}
+static int
+mySecretEventValueChanged(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virSecretPtr secret,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ virSecretGetUUIDString(secret, uuid);
+ printf("%s EVENT: Secret %s\n", __func__, uuid);
+ return 0;
+}
+
+
static void
eventTypedParamsPrint(virTypedParameterPtr params,
int nparams)
@@ -1085,6 +1097,7 @@ struct secretEventData {
struct secretEventData secretEvents[] = {
SECRET_EVENT(VIR_SECRET_EVENT_ID_LIFECYCLE, mySecretEventCallback),
+ SECRET_EVENT(VIR_SECRET_EVENT_ID_VALUE_CHANGED, mySecretEventValueChanged),
};
/* make sure that the events are kept in sync */
Michal
More information about the libvir-list
mailing list