[libvirt] [PATCH 2/3] Introduce VIR_DOMAIN_EVENT_ID_LEASE_CHANGE

Michal Privoznik mprivozn at redhat.com
Fri Apr 5 07:57:37 UTC 2019


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 at redhat.com>
---
 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




More information about the libvir-list mailing list