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@xxxxxxxxxx> > --- > 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list