[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