[libvirt] [PATCH] Add domain event for metadata changes

Daniel P. Berrange berrange at redhat.com
Thu Dec 22 14:48:45 UTC 2016


When changing the metadata via virDomainSetMetadata, we now
emit an event to notify the app of changes. This is useful
when co-ordinating different applications read/write of
custom metadata.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 daemon/remote.c                     | 45 +++++++++++++++++++
 examples/object-events/event-test.c | 35 +++++++++++++++
 include/libvirt/libvirt-domain.h    | 20 +++++++++
 src/bhyve/bhyve_driver.c            |  7 +++
 src/conf/domain_event.c             | 86 +++++++++++++++++++++++++++++++++++++
 src/conf/domain_event.h             | 10 +++++
 src/libvirt_private.syms            |  2 +
 src/lxc/lxc_driver.c                |  6 +++
 src/qemu/qemu_driver.c              |  6 +++
 src/remote/remote_driver.c          | 33 +++++++++++++-
 src/remote/remote_protocol.x        | 15 ++++++-
 src/remote_protocol-structs         |  7 +++
 src/test/test_driver.c              |  6 +++
 tools/virsh-domain.c                | 25 +++++++++++
 14 files changed, 301 insertions(+), 2 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 23c9de4..3d837d8 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1223,6 +1223,50 @@ remoteRelayDomainEventDeviceRemovalFailed(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventMetadataChange(virConnectPtr conn,
+                                     virDomainPtr dom,
+                                     int type,
+                                     const char *nsuri,
+                                     void *opaque)
+{
+    daemonClientEventCallbackPtr callback = opaque;
+    remote_domain_event_callback_metadata_change_msg data;
+    char **nsurip;
+
+    if (callback->callbackID < 0 ||
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+        return -1;
+
+    VIR_DEBUG("Relaying domain metadata change %s %d %d %s, callback %d",
+              dom->name, dom->id, type, NULLSTR(nsuri), callback->callbackID);
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+
+    data.type = type;
+    if (nsuri) {
+        if (VIR_ALLOC(nsurip) < 0)
+            return -1;
+        if (VIR_STRDUP(*nsurip, nsuri) < 0) {
+            VIR_FREE(nsurip);
+            return -1;
+        }
+        data.nsuri = nsurip;
+    }
+
+    make_nonnull_domain(&data.dom, dom);
+    data.callbackID = callback->callbackID;
+
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_CALLBACK_METADATA_CHANGE,
+                                  (xdrproc_t)xdr_remote_domain_event_callback_metadata_change_msg,
+                                  &data);
+
+    return 0;
+}
+
+
 
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
@@ -1248,6 +1292,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMigrationIteration),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventJobCompleted),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c
index 730cb8b..f2316d7 100644
--- a/examples/object-events/event-test.c
+++ b/examples/object-events/event-test.c
@@ -917,6 +917,40 @@ myDomainEventDeviceRemovalFailedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
 }
 
 
+static const char *
+metadataTypeToStr(int status)
+{
+    switch ((virDomainMetadataType) status) {
+    case VIR_DOMAIN_METADATA_DESCRIPTION:
+        return "description";
+
+    case VIR_DOMAIN_METADATA_TITLE:
+        return "title";
+
+    case VIR_DOMAIN_METADATA_ELEMENT:
+        return "element";
+
+    case VIR_DOMAIN_METADATA_LAST:
+        break;
+    }
+
+    return "unknown";
+}
+
+static int
+myDomainEventMetadataChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                    virDomainPtr dom,
+                                    int type,
+                                    const char *nsuri,
+                                    void *opaque ATTRIBUTE_UNUSED)
+{
+    const char *typestr = metadataTypeToStr(type);
+    printf("%s EVENT: Domain %s(%d) metadata type: %s (%s)\n",
+           __func__, virDomainGetName(dom), virDomainGetID(dom), typestr, nsuri ? nsuri : "n/a");
+    return 0;
+}
+
+
 
 static void
 myFreeFunc(void *opaque)
@@ -971,6 +1005,7 @@ struct domainEventData domainEvents[] = {
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION, myDomainEventMigrationIterationCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, myDomainEventJobCompletedCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
+    DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
 };
 
 struct storagePoolEventData {
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 6362947..e303140 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3770,6 +3770,25 @@ typedef void (*virConnectDomainEventDeviceRemovalFailedCallback)(virConnectPtr c
                                                                  const char *devAlias,
                                                                  void *opaque);
 
+/**
+ * virConnectDomainEventMetadataChangeCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @type: a value from virDomainMetadataTypea
+ * @nsuri: XML namespace URI
+ * @opaque: application specified data
+ *
+ * This callback is triggered when the domain XML metadata is changed
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_METADATA_CHANGE with virConnectDomainEventRegisterAny().
+ */
+typedef void (*virConnectDomainEventMetadataChangeCallback)(virConnectPtr conn,
+                                                            virDomainPtr dom,
+                                                            int type,
+                                                            const char *nsuri,
+                                                            void *opaque);
+
 
 /**
  * virConnectDomainEventMigrationIterationCallback:
@@ -4195,6 +4214,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION = 20, /* virConnectDomainEventMigrationIterationCallback */
     VIR_DOMAIN_EVENT_ID_JOB_COMPLETED = 21,  /* virConnectDomainEventJobCompletedCallback */
     VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */
+    VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_ID_LAST
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 17f8524..e42ec47 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1124,6 +1124,13 @@ bhyveDomainSetMetadata(virDomainPtr dom,
                                   privconn->xmlopt, BHYVE_STATE_DIR,
                                   BHYVE_CONFIG_DIR, flags);
 
+    if (ret == 0) {
+        virObjectEventPtr ev = NULL;
+        ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
+        virObjectEventStateQueue(privconn->domainEventState, ev);
+    }
+
+
  cleanup:
     virObjectUnref(caps);
     virObjectUnlock(vm);
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 63ae9e1..da503f3 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -59,6 +59,7 @@ static virClassPtr virDomainEventDeviceAddedClass;
 static virClassPtr virDomainEventMigrationIterationClass;
 static virClassPtr virDomainEventJobCompletedClass;
 static virClassPtr virDomainEventDeviceRemovalFailedClass;
+static virClassPtr virDomainEventMetadataChangeClass;
 
 static void virDomainEventDispose(void *obj);
 static void virDomainEventLifecycleDispose(void *obj);
@@ -79,6 +80,7 @@ static void virDomainEventDeviceAddedDispose(void *obj);
 static void virDomainEventMigrationIterationDispose(void *obj);
 static void virDomainEventJobCompletedDispose(void *obj);
 static void virDomainEventDeviceRemovalFailedDispose(void *obj);
+static void virDomainEventMetadataChangeDispose(void *obj);
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -266,6 +268,15 @@ struct _virDomainEventDeviceRemovalFailed {
 typedef struct _virDomainEventDeviceRemovalFailed virDomainEventDeviceRemovalFailed;
 typedef virDomainEventDeviceRemovalFailed *virDomainEventDeviceRemovalFailedPtr;
 
+struct _virDomainEventMetadataCange {
+    virDomainEvent parent;
+
+    int type;
+    char *nsuri;
+};
+typedef struct _virDomainEventMetadataCange virDomainEventMetadataChange;
+typedef virDomainEventMetadataChange *virDomainEventMetadataChangePtr;
+
 
 
 static int
@@ -385,6 +396,12 @@ virDomainEventsOnceInit(void)
                       sizeof(virDomainEventDeviceRemovalFailed),
                       virDomainEventDeviceRemovalFailedDispose)))
         return -1;
+    if (!(virDomainEventMetadataChangeClass =
+          virClassNew(virDomainEventClass,
+                      "virDomainEventMetadataChange",
+                      sizeof(virDomainEventMetadataChange),
+                      virDomainEventMetadataChangeDispose)))
+        return -1;
     return 0;
 }
 
@@ -573,6 +590,16 @@ virDomainEventJobCompletedDispose(void *obj)
 }
 
 
+static void
+virDomainEventMetadataChangeDispose(void *obj)
+{
+    virDomainEventMetadataChangePtr event = obj;
+    VIR_DEBUG("obj=%p", event);
+
+    VIR_FREE(event->nsuri);
+}
+
+
 static void *
 virDomainEventNew(virClassPtr klass,
                   int eventID,
@@ -1600,6 +1627,53 @@ virDomainEventTunableNewFromDom(virDomainPtr dom,
 }
 
 
+static virObjectEventPtr
+virDomainEventMetadataChangeNew(int id,
+                                const char *name,
+                                unsigned char *uuid,
+                                int type,
+                                const char *nsuri)
+{
+    virDomainEventMetadataChangePtr ev;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventMetadataChangeClass,
+                                 VIR_DOMAIN_EVENT_ID_METADATA_CHANGE,
+                                 id, name, uuid)))
+        return NULL;
+
+    ev->type = type;
+    if (nsuri && VIR_STRDUP(ev->nsuri, nsuri) < 0)
+        goto error;
+
+    return (virObjectEventPtr)ev;
+
+ error:
+    virObjectUnref(ev);
+    return NULL;
+}
+
+virObjectEventPtr
+virDomainEventMetadataChangeNewFromObj(virDomainObjPtr obj,
+                                       int type,
+                                       const char *nsuri)
+{
+    return virDomainEventMetadataChangeNew(obj->def->id, obj->def->name,
+                                           obj->def->uuid, type, nsuri);
+}
+
+virObjectEventPtr
+virDomainEventMetadataChangeNewFromDom(virDomainPtr dom,
+                                       int type,
+                                       const char *nsuri)
+{
+    return virDomainEventMetadataChangeNew(dom->id, dom->name, dom->uuid,
+                                           type, nsuri);
+}
+
+
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                   virObjectEventPtr event,
@@ -1857,6 +1931,18 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
             goto cleanup;
         }
 
+    case VIR_DOMAIN_EVENT_ID_METADATA_CHANGE:
+        {
+            virDomainEventMetadataChangePtr metadataChangeEvent;
+
+            metadataChangeEvent = (virDomainEventMetadataChangePtr)event;
+            ((virConnectDomainEventMetadataChangeCallback)cb)(conn, dom,
+                                                              metadataChangeEvent->type,
+                                                              metadataChangeEvent->nsuri,
+                                                              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 54fa879..1933f47 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -234,6 +234,16 @@ virDomainEventJobCompletedNewFromDom(virDomainPtr dom,
                                      virTypedParameterPtr params,
                                      int nparams);
 
+virObjectEventPtr
+virDomainEventMetadataChangeNewFromObj(virDomainObjPtr obj,
+                                       int type,
+                                       const char *nsuri);
+
+virObjectEventPtr
+virDomainEventMetadataChangeNewFromDom(virDomainPtr dom,
+                                       int type,
+                                       const char *nsuri);
+
 int
 virDomainEventStateRegister(virConnectPtr conn,
                             virObjectEventStatePtr state,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2d23e46..3b8d227 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -558,6 +558,8 @@ virDomainEventLifecycleNew;
 virDomainEventLifecycleNewFromDef;
 virDomainEventLifecycleNewFromDom;
 virDomainEventLifecycleNewFromObj;
+virDomainEventMetadataChangeNewFromDom;
+virDomainEventMetadataChangeNewFromObj;
 virDomainEventMigrationIterationNewFromDom;
 virDomainEventMigrationIterationNewFromObj;
 virDomainEventPMSuspendDiskNewFromDom;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index a7bc9f0..04a4b8c 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -5379,6 +5379,12 @@ lxcDomainSetMetadata(virDomainPtr dom,
                                   driver->xmlopt, cfg->stateDir,
                                   cfg->configDir, flags);
 
+    if (ret == 0) {
+        virObjectEventPtr ev = NULL;
+        ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
+        virObjectEventStateQueue(driver->domainEventState, ev);
+    }
+
     virLXCDomainObjEndJob(driver, vm);
 
  cleanup:
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b359e77..2c9ef95 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18069,6 +18069,12 @@ qemuDomainSetMetadata(virDomainPtr dom,
                                   driver->xmlopt, cfg->stateDir,
                                   cfg->configDir, flags);
 
+    if (ret == 0) {
+        virObjectEventPtr ev = NULL;
+        ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
+        qemuDomainEventQueue(driver, ev);
+    }
+
     qemuDomainObjEndJob(driver, vm);
 
  cleanup:
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 46da06f..c161a56 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -355,6 +355,11 @@ remoteDomainBuildEventCallbackJobCompleted(virNetClientProgramPtr prog,
                                            void *evdata, void *opaque);
 
 static void
+remoteDomainBuildEventCallbackMetadataChange(virNetClientProgramPtr prog,
+                                             virNetClientPtr client,
+                                             void *evdata, void *opaque);
+
+static void
 remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
                                  void *evdata, void *opaque);
@@ -558,6 +563,10 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventCallbackDeviceRemovalFailed,
       sizeof(remote_domain_event_callback_device_removal_failed_msg),
       (xdrproc_t)xdr_remote_domain_event_callback_device_removal_failed_msg },
+    { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_METADATA_CHANGE,
+      remoteDomainBuildEventCallbackMetadataChange,
+      sizeof(remote_domain_event_callback_metadata_change_msg),
+      (xdrproc_t)xdr_remote_domain_event_callback_metadata_change_msg },
     { REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE,
       remoteStoragePoolBuildEventLifecycle,
       sizeof(remote_storage_pool_event_lifecycle_msg),
@@ -5121,7 +5130,7 @@ remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgramPtr prog AT
                                                   void *evdata, void *opaque)
 {
     virConnectPtr conn = opaque;
-    remote_domain_event_callback_device_added_msg *msg = evdata;
+    remote_domain_event_callback_device_removal_failed_msg *msg = evdata;
     struct private_data *priv = conn->privateData;
     virDomainPtr dom;
     virObjectEventPtr event = NULL;
@@ -5249,6 +5258,28 @@ remoteDomainBuildEventCallbackJobCompleted(virNetClientProgramPtr prog ATTRIBUTE
 
 
 static void
+remoteDomainBuildEventCallbackMetadataChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                             virNetClientPtr client ATTRIBUTE_UNUSED,
+                                             void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_callback_metadata_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 = virDomainEventMetadataChangeNewFromDom(dom, msg->type, msg->nsuri ? *msg->nsuri : NULL);
+
+    virObjectUnref(dom);
+
+    remoteEventQueue(priv, event, msg->callbackID);
+}
+
+
+static void
 remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
                                  void *evdata, void *opaque)
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index b846ef2..f268e1c 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3353,6 +3353,13 @@ struct remote_domain_set_guest_vcpus_args {
 };
 
 
+struct remote_domain_event_callback_metadata_change_msg {
+    int callbackID;
+    remote_nonnull_domain dom;
+    int type;
+    remote_string nsuri;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -5952,5 +5959,11 @@ enum remote_procedure {
      * @priority: high
      * @acl: storage_vol:read
      */
-    REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS = 378
+    REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS = 378,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_METADATA_CHANGE = 379
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 41bc3bd..2fc9e46 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2800,6 +2800,12 @@ struct remote_domain_set_guest_vcpus_args {
         int                        state;
         u_int                      flags;
 };
+struct remote_domain_event_callback_metadata_change_msg {
+        int                        callbackID;
+        remote_nonnull_domain      dom;
+        int                        type;
+        remote_string              nsuri
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3179,4 +3185,5 @@ enum remote_procedure {
         REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE = 376,
         REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377,
         REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS = 378,
+        REMOTE_PROC_DOMAIN_EVENT_CALLBACK_METADATA_CHANGE = 379,
 };
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index de92a01..6820298 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2721,6 +2721,12 @@ static int testDomainSetMetadata(virDomainPtr dom,
                                   privconn->caps, privconn->xmlopt,
                                   NULL, NULL, flags);
 
+    if (ret == 0) {
+        virObjectEventPtr ev = NULL;
+        ev = virDomainEventMetadataChangeNewFromObj(privdom, type, uri);
+        testObjectEventQueue(privconn, ev);
+    }
+
     virDomainObjEndAPI(&privdom);
     return ret;
 }
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 3a6fa5c..f8f5d9c 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -12750,6 +12750,29 @@ virshEventDeviceRemovalFailedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
     virshEventPrint(opaque, &buf);
 }
 
+VIR_ENUM_DECL(virshEventMetadataChangeType)
+VIR_ENUM_IMPL(virshEventMetadataChangeType,
+              VIR_DOMAIN_METADATA_LAST,
+              N_("description"),
+              N_("title"),
+              N_("element"))
+
+static void
+virshEventMetadataChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+                              virDomainPtr dom,
+                              int type,
+                              const char *nsuri,
+                              void *opaque)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf, _("event 'metdata-change' for domain %s: %s %s\n"),
+                      virDomainGetName(dom),
+                      UNKNOWNSTR(virshEventMetadataChangeTypeTypeToString(type)),
+                      NULLSTR(nsuri));
+    virshEventPrint(opaque, &buf);
+}
+
 
 static vshEventCallback vshEventCallbacks[] = {
     { "lifecycle",
@@ -12796,6 +12819,8 @@ static vshEventCallback vshEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventJobCompletedPrint), },
     { "device-removal-failed",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovalFailedPrint), },
+    { "metadata-change",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
 };
 verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
 
-- 
2.9.3




More information about the libvir-list mailing list