[libvirt] [PATCH 9/9] secret: add support for value change events

Daniel P. Berrange berrange at redhat.com
Thu Jan 5 13:59:27 UTC 2017


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, },
 };
 
 static const vshCmdInfo info_secret_event[] = {
-- 
2.9.3




More information about the libvir-list mailing list