Add domain event for metadata changes

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@redhat.com>
This commit is contained in:
Daniel P. Berrange 2016-12-22 14:41:30 +00:00
parent f1e48297cf
commit c50070173d
14 changed files with 300 additions and 1 deletions

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -558,6 +558,8 @@ virDomainEventLifecycleNew;
virDomainEventLifecycleNewFromDef;
virDomainEventLifecycleNewFromDom;
virDomainEventLifecycleNewFromObj;
virDomainEventMetadataChangeNewFromDom;
virDomainEventMetadataChangeNewFromObj;
virDomainEventMigrationIterationNewFromDom;
virDomainEventMigrationIterationNewFromObj;
virDomainEventPMSuspendDiskNewFromDom;

View File

@ -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:

View File

@ -18072,6 +18072,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:

View File

@ -354,6 +354,11 @@ remoteDomainBuildEventCallbackJobCompleted(virNetClientProgramPtr prog,
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,
@ -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),
@ -5248,6 +5257,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,

View File

@ -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
};

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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));