[PATCH 2/3] Introduce VIR_DOMAIN_EVENT_ID_LEASE_CHANGE

Michal Privoznik mprivozn at redhat.com
Wed May 20 08:01:39 UTC 2020


This event will be emitted whenever a lease is attached or
detached. The even consists of four values: lockspace, key, path
and offset. These are verbatim copy of the lease XML.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 examples/c/misc/event-test.c        |  37 ++++++++++
 include/libvirt/libvirt-domain.h    |  37 ++++++++++
 src/conf/domain_event.c             | 100 ++++++++++++++++++++++++++++
 src/conf/domain_event.h             |  16 +++++
 src/libvirt_private.syms            |   2 +
 src/remote/remote_daemon_dispatch.c |  37 ++++++++++
 src/remote/remote_driver.c          |  34 ++++++++++
 src/remote/remote_protocol.x        |  18 ++++-
 src/remote_protocol-structs         |   8 +++
 tools/virsh-domain.c                |  34 ++++++++++
 10 files changed, 322 insertions(+), 1 deletion(-)

diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index 52caa8ffa8..8b2d1c1e5b 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -963,6 +963,42 @@ myDomainEventBlockThresholdCallback(virConnectPtr conn G_GNUC_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 G_GNUC_UNUSED,
+                                 virDomainPtr dom,
+                                 int action,
+                                 const char *lockspace,
+                                 const char *key,
+                                 const char *path,
+                                 unsigned long long offset,
+                                 void *opaque G_GNUC_UNUSED)
+{
+    printf("%s EVENT domain %s(%d) lease change: action %s lockspace %s key %s "
+           "path %s offset %llu",
+           __func__, virDomainGetName(dom), virDomainGetID(dom),
+           leaseActionTypeToStr(action), lockspace, key, path, offset);
+    return 0;
+}
+
+
 static int
 myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
                                         virDomainPtr dom,
@@ -1093,6 +1129,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 f129e6a1af..e002d5cb18 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4551,6 +4551,42 @@ 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
+ * @path: fully qualified path of the file associated with the lockspace
+ * @offset: offset within @path, may be 0 if the lock manager doesn't support offsets
+ * @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,
+                                                         const char *path,
+                                                         unsigned long long offset,
+                                                         void *opaque);
+
+
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
  *
@@ -4593,6 +4629,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 33fbf10406..b1eff402ac 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -57,6 +57,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);
@@ -79,6 +80,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,
@@ -287,6 +289,19 @@ struct _virDomainEventBlockThreshold {
 typedef struct _virDomainEventBlockThreshold virDomainEventBlockThreshold;
 typedef virDomainEventBlockThreshold *virDomainEventBlockThresholdPtr;
 
+struct _virDomainEventLeaseChange {
+    virDomainEvent parent;
+
+    int action;
+
+    char *lockspace;
+    char *key;
+    char *path;
+    unsigned long long offset;
+};
+typedef struct _virDomainEventLeaseChange virDomainEventLeaseChange;
+typedef virDomainEventLeaseChange *virDomainEventLeaseChangePtr;
+
 
 static int
 virDomainEventsOnceInit(void)
@@ -333,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;
 }
 
@@ -542,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,
@@ -1619,6 +1647,62 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr dom,
 }
 
 
+static virObjectEventPtr
+virDomainEventLeaseChangeNew(int id,
+                             const char *name,
+                             unsigned char *uuid,
+                             int action,
+                             const char *lockspace,
+                             const char *key,
+                             const char *path,
+                             unsigned long long offset)
+{
+    virDomainEventLeaseChangePtr ev;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventLeaseChangeClass,
+                                 VIR_DOMAIN_EVENT_ID_LEASE_CHANGE,
+                                 id, name, uuid)))
+        return NULL;
+
+    ev->action = action;
+    ev->lockspace = g_strdup(lockspace);
+    ev->key = g_strdup(key);
+    ev->path = g_strdup(path);
+    ev->offset = offset;
+
+    return (virObjectEventPtr)ev;
+}
+
+virObjectEventPtr
+virDomainEventLeaseChangeNewFromObj(virDomainObjPtr obj,
+                                    int action,
+                                    const char *lockspace,
+                                    const char *key,
+                                    const char *path,
+                                    unsigned long long offset)
+{
+    return virDomainEventLeaseChangeNew(obj->def->id, obj->def->name,
+                                        obj->def->uuid, action, lockspace,
+                                        key, path, offset);
+}
+
+virObjectEventPtr
+virDomainEventLeaseChangeNewFromDom(virDomainPtr dom,
+                                    int action,
+                                    const char *lockspace,
+                                    const char *key,
+                                    const char *path,
+                                    unsigned long long offset)
+{
+    return virDomainEventLeaseChangeNew(dom->id, dom->name, dom->uuid,
+                                        action, lockspace, key,
+                                        path, offset);
+}
+
+
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                   virObjectEventPtr event,
@@ -1902,6 +1986,22 @@ 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,
+                                                           leaseChangeEvent->path,
+                                                           leaseChangeEvent->offset,
+                                                           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 d1cfb81d62..3e5641f9c2 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -255,6 +255,22 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr dom,
                                        unsigned long long threshold,
                                        unsigned long long excess);
 
+virObjectEventPtr
+virDomainEventLeaseChangeNewFromObj(virDomainObjPtr obj,
+                                    int action,
+                                    const char *lockspace,
+                                    const char *key,
+                                    const char *path,
+                                    unsigned long long offset);
+
+virObjectEventPtr
+virDomainEventLeaseChangeNewFromDom(virDomainPtr dom,
+                                    int action,
+                                    const char *lockspace,
+                                    const char *key,
+                                    const char *path,
+                                    unsigned long long offset);
+
 int
 virDomainEventStateRegister(virConnectPtr conn,
                             virObjectEventStatePtr state,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 935ef7303b..8ccca53b83 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -692,6 +692,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 6f67d2fb30..97b167ef42 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -1304,6 +1304,42 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventLeaseChange(virConnectPtr conn,
+                                  virDomainPtr dom,
+                                  int action,
+                                  const char *lockspace,
+                                  const char *key,
+                                  const char *path,
+                                  unsigned long long offset,
+                                  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;
+    data.action = action;
+    data.locspace = g_strdup(lockspace);
+    data.key = g_strdup(key);
+    data.path = g_strdup(path);
+    data.offset = offset;
+    make_nonnull_domain(&data.dom, dom);
+
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE,
+                                  (xdrproc_t)xdr_remote_domain_event_lease_change_msg, &data);
+    return 0;
+}
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -1330,6 +1366,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLeaseChange),
 };
 
 G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 0aeab9db27..78e8541c95 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -468,6 +468,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 G_GNUC_UNUSED,
                                          virNetClientPtr client G_GNUC_UNUSED,
@@ -679,6 +684,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
@@ -5687,6 +5696,31 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgramPtr prog G_GNUC_UNUSED,
 }
 
 
+static void
+remoteDomainBuildEventLeaseChange(virNetClientProgramPtr prog G_GNUC_UNUSED,
+                                  virNetClientPtr client G_GNUC_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,
+                                                msg->path,
+                                                msg->offset);
+    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 d4393680e9..909b0db9c7 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3771,6 +3771,16 @@ struct remote_domain_backup_get_xml_desc_ret {
     remote_nonnull_string xml;
 };
 
+struct remote_domain_event_lease_change_msg {
+    int callbackID;
+    remote_nonnull_domain dom;
+    int action;
+    remote_nonnull_string locspace;
+    remote_nonnull_string key;
+    remote_nonnull_string path;
+    unsigned hyper offset;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -6664,5 +6674,11 @@ enum remote_procedure {
      * @priority: high
      * @acl: domain:read
      */
-    REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422
+    REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE = 423
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index bae0f0b545..70e9c2ae6b 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -3135,6 +3135,13 @@ struct remote_domain_backup_get_xml_desc_args {
 struct remote_domain_backup_get_xml_desc_ret {
         remote_nonnull_string      xml;
 };
+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,
@@ -3558,4 +3565,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_AGENT_SET_RESPONSE_TIMEOUT = 420,
         REMOTE_PROC_DOMAIN_BACKUP_BEGIN = 421,
         REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422,
+        REMOTE_PROC_DOMAIN_EVENT_LEASE_CHANGE = 423,
 };
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 61cd72f714..3a062dd184 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13591,6 +13591,38 @@ virshEventBlockThresholdPrint(virConnectPtr conn G_GNUC_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 G_GNUC_UNUSED,
+                           virDomainPtr dom,
+                           int action,
+                           const char *lockspace,
+                           const char *key,
+                           const char *path,
+                           unsigned long long offset,
+                           void *opaque)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf,
+                      _("event 'lease-change' for domain %s: "
+                        "action: %s lockspace: %s key: %s "
+                        "path %s offset: %llu\n"),
+                      virDomainGetName(dom),
+                      UNKNOWNSTR(virshEventLeaseChangeActionTypeToString(action)),
+                      lockspace, key, path, offset);
+
+    virshEventPrint(opaque, &buf);
+}
+
+
 virshDomainEventCallback virshDomainEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -13640,6 +13672,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
     { "block-threshold",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
+    { "lease-change",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventLeaseChangePrint), },
 };
 G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));
 
-- 
2.26.2




More information about the libvir-list mailing list