https://bugzilla.redhat.com/show_bug.cgi?id=1639228 This event will be emitted whenever a lease is attached or detached. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- examples/object-events/event-test.c | 34 +++++++++++ include/libvirt/libvirt-domain.h | 33 +++++++++++ src/conf/domain_event.c | 89 +++++++++++++++++++++++++++++ src/conf/domain_event.h | 12 ++++ src/libvirt_private.syms | 2 + src/remote/remote_daemon_dispatch.c | 40 +++++++++++++ src/remote/remote_driver.c | 32 +++++++++++ src/remote/remote_protocol.x | 16 +++++- src/remote_protocol-structs | 8 +++ tools/virsh-domain.c | 31 ++++++++++ 10 files changed, 296 insertions(+), 1 deletion(-) diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c index fcf4492470..e9775d7450 100644 --- a/examples/object-events/event-test.c +++ b/examples/object-events/event-test.c @@ -957,6 +957,39 @@ myDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED, } +static const char * +leaseActionTypeToStr(int action) +{ + switch ((virConnectDomainEventLeaseAction) action) { + case VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_ATTACH: + return "attach"; + + case VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_DETACH: + return "detach"; + + case VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_LAST: + break; + } + + return "unknown"; +} + + +static int +myDomainEventLeaseChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int action, + const char *lockspace, + const char *key, + void *opaque ATTRIBUTE_UNUSED) +{ + printf("%s EVENT domain %s(%d) lease change: action %s lockspace %s key %s", + __func__, virDomainGetName(dom), virDomainGetID(dom), + leaseActionTypeToStr(action), lockspace, key); + return 0; +} + + static int myDomainEventMigrationIterationCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, @@ -1087,6 +1120,7 @@ struct domainEventData domainEvents[] = { DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback), + DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_LEASE_CHANGE, myDomainEventLeaseChangeCallback), }; struct storagePoolEventData { diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 7d36820b5a..8a68b84135 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4473,6 +4473,38 @@ typedef void (*virConnectDomainEventBlockThresholdCallback)(virConnectPtr conn, unsigned long long excess, void *opaque); + +typedef enum { + VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_ATTACH = 1, /* lease attached */ + VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_DETACH = 2, /* lease detached */ + +# ifdef VIR_ENUM_SENTINELS + VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_LAST +# endif +} virConnectDomainEventLeaseAction; + +/** + * virConnectDomainEventLeaseChangeCallback: + * @conn: connection object + * @dom: domain on which the event occurred + * @action: action which occurred, one of virConnectDomainEventLeaseAction + * @lockspace: string identifying within which lockspace @key is held + * @key: unique key + * @opaque: application specified data + * + * The callback occurs on lease attach or detach. + * + * The callback signature to use when registering for an event of type + * VIR_DOMAIN_EVENT_ID_LEASE_CHANGE with virConnectDomainEventRegisterAny() + */ +typedef void (*virConnectDomainEventLeaseChangeCallback)(virConnectPtr conn, + virDomainPtr dom, + int action, + const char *lockspace, + const char *key, + void *opaque); + + /** * VIR_DOMAIN_EVENT_CALLBACK: * @@ -4515,6 +4547,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */ VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */ VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */ + VIR_DOMAIN_EVENT_ID_LEASE_CHANGE = 25, /* virConnectDomainEventLeaseChangeCallback */ # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_ID_LAST diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index b33589f472..436a0c9eb1 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -59,6 +59,7 @@ static virClassPtr virDomainEventJobCompletedClass; static virClassPtr virDomainEventDeviceRemovalFailedClass; static virClassPtr virDomainEventMetadataChangeClass; static virClassPtr virDomainEventBlockThresholdClass; +static virClassPtr virDomainEventLeaseChangeClass; static void virDomainEventDispose(void *obj); static void virDomainEventLifecycleDispose(void *obj); @@ -81,6 +82,7 @@ static void virDomainEventJobCompletedDispose(void *obj); static void virDomainEventDeviceRemovalFailedDispose(void *obj); static void virDomainEventMetadataChangeDispose(void *obj); static void virDomainEventBlockThresholdDispose(void *obj); +static void virDomainEventLeaseChangeDispose(void *obj); static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, @@ -289,6 +291,17 @@ struct _virDomainEventBlockThreshold { typedef struct _virDomainEventBlockThreshold virDomainEventBlockThreshold; typedef virDomainEventBlockThreshold *virDomainEventBlockThresholdPtr; +struct _virDomainEventLeaseChange { + virDomainEvent parent; + + int action; + + char *lockspace; + char *key; +}; +typedef struct _virDomainEventLeaseChange virDomainEventLeaseChange; +typedef virDomainEventLeaseChange *virDomainEventLeaseChangePtr; + static int virDomainEventsOnceInit(void) @@ -335,6 +348,8 @@ virDomainEventsOnceInit(void) return -1; if (!VIR_CLASS_NEW(virDomainEventBlockThreshold, virDomainEventClass)) return -1; + if (!VIR_CLASS_NEW(virDomainEventLeaseChange, virDomainEventClass)) + return -1; return 0; } @@ -544,6 +559,17 @@ virDomainEventBlockThresholdDispose(void *obj) } +static void +virDomainEventLeaseChangeDispose(void *obj) +{ + virDomainEventLeaseChangePtr event = obj; + VIR_DEBUG("obj=%p", event); + + VIR_FREE(event->lockspace); + VIR_FREE(event->key); +} + + static void * virDomainEventNew(virClassPtr klass, int eventID, @@ -1672,6 +1698,55 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr dom, } +static virObjectEventPtr +virDomainEventLeaseChangeNew(int id, + const char *name, + unsigned char *uuid, + int action, + const char *lockspace, + const char *key) +{ + virDomainEventLeaseChangePtr ev; + + if (virDomainEventsInitialize() < 0) + return NULL; + + if (!(ev = virDomainEventNew(virDomainEventLeaseChangeClass, + VIR_DOMAIN_EVENT_ID_LEASE_CHANGE, + id, name, uuid))) + return NULL; + + if (VIR_STRDUP(ev->lockspace, lockspace) < 0 || + VIR_STRDUP(ev->key, key) < 0) { + virObjectUnref(ev); + return NULL; + } + ev->action = action; + + return (virObjectEventPtr)ev; +} + +virObjectEventPtr +virDomainEventLeaseChangeNewFromObj(virDomainObjPtr obj, + int action, + const char *lockspace, + const char *key) +{ + return virDomainEventLeaseChangeNew(obj->def->id, obj->def->name, + obj->def->uuid, action, lockspace, key); +} + +virObjectEventPtr +virDomainEventLeaseChangeNewFromDom(virDomainPtr dom, + int action, + const char *lockspace, + const char *key) +{ + return virDomainEventLeaseChangeNew(dom->id, dom->name, dom->uuid, + action, lockspace, key); +} + + static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, virObjectEventPtr event, @@ -1955,6 +2030,20 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, cbopaque); goto cleanup; } + + case VIR_DOMAIN_EVENT_ID_LEASE_CHANGE: + { + virDomainEventLeaseChangePtr leaseChangeEvent; + + leaseChangeEvent = (virDomainEventLeaseChangePtr)event; + ((virConnectDomainEventLeaseChangeCallback)cb)(conn, dom, + leaseChangeEvent->action, + leaseChangeEvent->lockspace, + leaseChangeEvent->key, + cbopaque); + goto cleanup; + } + case VIR_DOMAIN_EVENT_ID_LAST: break; } diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index 637f1daf68..bcd9c139a2 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -256,6 +256,18 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr dom, unsigned long long threshold, unsigned long long excess); +virObjectEventPtr +virDomainEventLeaseChangeNewFromObj(virDomainObjPtr obj, + int action, + const char *lockspace, + const char *key); + +virObjectEventPtr +virDomainEventLeaseChangeNewFromDom(virDomainPtr dom, + int action, + const char *lockspace, + const char *key); + int virDomainEventStateRegister(virConnectPtr conn, virObjectEventStatePtr state, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 212adf53c1..06295b031d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -635,6 +635,8 @@ virDomainEventIOErrorReasonNewFromDom; virDomainEventIOErrorReasonNewFromObj; virDomainEventJobCompletedNewFromDom; virDomainEventJobCompletedNewFromObj; +virDomainEventLeaseChangeNewFromDom; +virDomainEventLeaseChangeNewFromObj; virDomainEventLifecycleNew; virDomainEventLifecycleNewFromDef; virDomainEventLifecycleNewFromDom; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index df28259042..82a75c73bd 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -1449,6 +1449,45 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr conn, } +static int +remoteRelayDomainEventLeaseChange(virConnectPtr conn, + virDomainPtr dom, + int action, + const char *lockspace, + const char *key, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; + remote_domain_event_lease_change_msg data; + + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) + return -1; + + VIR_DEBUG("Relaying domain lease change event %s %d %d %s %s, callback %d", + dom->name, dom->id, action, lockspace, key, callback->callbackID); + + memset(&data, 0, sizeof(data)); + data.callbackID = callback->callbackID; + if (VIR_STRDUP(data.locspace, lockspace) < 0 || + VIR_STRDUP(data.key, key) < 0) + goto error; + data.action = action; + if (make_nonnull_domain(&data.dom, dom) < 0) + goto error; + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE, + (xdrproc_t)xdr_remote_domain_event_lease_change_msg, &data); + return 0; + + error: + xdr_free((xdrproc_t)xdr_remote_domain_event_lease_change_msg, + (char *) &data); + return -1; +} + + static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), @@ -1475,6 +1514,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLeaseChange), }; verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 5c4dd41227..7f6a463f2b 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -418,6 +418,11 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventLeaseChange(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + static void remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetClientPtr client ATTRIBUTE_UNUSED, @@ -629,6 +634,10 @@ static virNetClientProgramEvent remoteEvents[] = { remoteDomainBuildEventBlockThreshold, sizeof(remote_domain_event_block_threshold_msg), (xdrproc_t)xdr_remote_domain_event_block_threshold_msg }, + { REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE, + remoteDomainBuildEventLeaseChange, + sizeof(remote_domain_event_lease_change_msg), + (xdrproc_t)xdr_remote_domain_event_lease_change_msg }, }; static void @@ -5590,6 +5599,29 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgramPtr prog ATTRIBUTE_UNUSE } +static void +remoteDomainBuildEventLeaseChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_lease_change_msg *msg = evdata; + struct private_data *priv = conn->privateData; + virDomainPtr dom; + virObjectEventPtr event = NULL; + + if (!(dom = get_nonnull_domain(conn, msg->dom))) + return; + + event = virDomainEventLeaseChangeNewFromDom(dom, + msg->action, + msg->locspace, + msg->key); + virObjectUnref(dom); + virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID); +} + + static int remoteStreamSend(virStreamPtr st, const char *data, diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 74be4b37d0..780b2ca9cb 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3573,6 +3573,14 @@ struct remote_connect_get_storage_pool_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_domain_event_lease_change_msg { + int callbackID; + remote_nonnull_domain dom; + int action; + remote_nonnull_string locspace; + remote_nonnull_string key; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -6342,5 +6350,11 @@ enum remote_procedure { * @generate: both * @acl: connect:read */ - REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES = 403 + REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES = 403, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE = 404 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 768189c573..5aae22bf78 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2981,6 +2981,13 @@ struct remote_connect_get_storage_pool_capabilities_args { struct remote_connect_get_storage_pool_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_domain_event_lease_change_msg { + int callbackID; + remote_nonnull_domain dom; + int action; + remote_nonnull_string locspace; + remote_nonnull_string key; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3385,4 +3392,5 @@ enum remote_procedure { REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS = 401, REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS = 402, REMOTE_PROC_CONNECT_GET_STORAGE_POOL_CAPABILITIES = 403, + REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE = 404, }; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index e8d5404acf..ced5e62484 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13405,6 +13405,35 @@ virshEventBlockThresholdPrint(virConnectPtr conn ATTRIBUTE_UNUSED, } +VIR_ENUM_DECL(virshEventLeaseChangeAction); +VIR_ENUM_IMPL(virshEventLeaseChangeAction, + VIR_CONNECT_DOMAIN_EVENT_LEASE_ACTION_LAST, + N_("unknown"), + N_("attach"), + N_("detach")); + + +static void +virshEventLeaseChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int action, + const char *lockspace, + const char *key, + void *opaque) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&buf, + _("event 'lease-change' for domain %s: " + "action: %s lockspace: %s key: %s\n"), + virDomainGetName(dom), + UNKNOWNSTR(virshEventLeaseChangeActionTypeToString(action)), + lockspace, key); + + virshEventPrint(opaque, &buf); +} + + virshDomainEventCallback virshDomainEventCallbacks[] = { { "lifecycle", VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), }, @@ -13454,6 +13483,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), }, { "block-threshold", VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), }, + { "lease-change", + VIR_DOMAIN_EVENT_CALLBACK(virshEventLeaseChangePrint), }, }; verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(virshDomainEventCallbacks)); -- 2.21.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list