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(a)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