diff --git a/daemon/remote.c b/daemon/remote.c index 3a7ee9e6bb..f2b9b9aec4 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/examples/object-events/event-test.c b/examples/object-events/event-test.c index cf8c1bca27..55c004f93f 100644 --- a/examples/object-events/event-test.c +++ b/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 */ diff --git a/include/libvirt/libvirt-secret.h b/include/libvirt/libvirt-secret.h index 1bbbf3f34b..5df0b8ff89 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 9d578f0ed3..c130909282 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; } @@ -89,6 +104,14 @@ virSecretEventLifecycleDispose(void *obj) } +static void +virSecretEventValueChangedDispose(void *obj) +{ + virSecretEventValueChangedPtr event = obj; + VIR_DEBUG("obj=%p", event); +} + + static void virSecretEventDispatchDefaultFunc(virConnectPtr conn, virObjectEventPtr event, @@ -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 4649d949ed..5fd52f3fd3 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 2cf7389e23..82adf7ecb7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -845,6 +845,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 e689316175..59d74a26e0 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -390,6 +390,11 @@ remoteSecretBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client 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, @@ -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 @@ -5516,6 +5525,27 @@ remoteSecretBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, remoteEventQueue(priv, event, msg->callbackID); } +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, diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index ce4c4ef36e..6445685ba1 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 0e3d97e09e..2a371b6707 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 f7197f4afe..cd788b6873 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[] = {