}
+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),
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);
}
+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)
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 {
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:
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
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);
static virClassPtr virDomainEventMigrationIterationClass;
static virClassPtr virDomainEventJobCompletedClass;
static virClassPtr virDomainEventDeviceRemovalFailedClass;
+static virClassPtr virDomainEventMetadataChangeClass;
static void virDomainEventDispose(void *obj);
static void virDomainEventLifecycleDispose(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,
typedef struct _virDomainEventDeviceRemovalFailed virDomainEventDeviceRemovalFailed;
typedef virDomainEventDeviceRemovalFailed *virDomainEventDeviceRemovalFailedPtr;
+struct _virDomainEventMetadataCange {
+ virDomainEvent parent;
+
+ int type;
+ char *nsuri;
+};
+typedef struct _virDomainEventMetadataCange virDomainEventMetadataChange;
+typedef virDomainEventMetadataChange *virDomainEventMetadataChangePtr;
+
static int
sizeof(virDomainEventDeviceRemovalFailed),
virDomainEventDeviceRemovalFailedDispose)))
return -1;
+ if (!(virDomainEventMetadataChangeClass =
+ virClassNew(virDomainEventClass,
+ "virDomainEventMetadataChange",
+ sizeof(virDomainEventMetadataChange),
+ virDomainEventMetadataChangeDispose)))
+ return -1;
return 0;
}
}
+static void
+virDomainEventMetadataChangeDispose(void *obj)
+{
+ virDomainEventMetadataChangePtr event = obj;
+ VIR_DEBUG("obj=%p", event);
+
+ VIR_FREE(event->nsuri);
+}
+
+
static void *
virDomainEventNew(virClassPtr klass,
int eventID,
}
+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,
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;
}
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,
virDomainEventLifecycleNewFromDef;
virDomainEventLifecycleNewFromDom;
virDomainEventLifecycleNewFromObj;
+virDomainEventMetadataChangeNewFromDom;
+virDomainEventMetadataChangeNewFromObj;
virDomainEventMigrationIterationNewFromDom;
virDomainEventMigrationIterationNewFromObj;
virDomainEventPMSuspendDiskNewFromDom;
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:
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:
virNetClientPtr client,
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,
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),
}
+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,
};
+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. */
* @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
};
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,
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,
};
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;
}
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",
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));