mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
Introduce node device update event as top level event
This event is emitted when a nodedev XML definition is updated, like when cdrom media is changed in a cdrom block device. Also includes node device update event implementation for udev backend, virsh nodedev-event support, and event-test support
This commit is contained in:
parent
18701e9d62
commit
43a6b37b24
@ -1388,8 +1388,37 @@ remoteRelayNodeDeviceEventLifecycle(virConnectPtr conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remoteRelayNodeDeviceEventUpdate(virConnectPtr conn,
|
||||
virNodeDevicePtr dev,
|
||||
void *opaque)
|
||||
{
|
||||
daemonClientEventCallbackPtr callback = opaque;
|
||||
remote_node_device_event_update_msg data;
|
||||
|
||||
if (callback->callbackID < 0 ||
|
||||
!remoteRelayNodeDeviceEventCheckACL(callback->client, conn, dev))
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Relaying node device update event callback %d",
|
||||
callback->callbackID);
|
||||
|
||||
/* build return data */
|
||||
memset(&data, 0, sizeof(data));
|
||||
make_nonnull_node_device(&data.dev, dev);
|
||||
data.callbackID = callback->callbackID;
|
||||
|
||||
remoteDispatchObjectEventSend(callback->client, remoteProgram,
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE,
|
||||
(xdrproc_t)xdr_remote_node_device_event_update_msg,
|
||||
&data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virConnectNodeDeviceEventGenericCallback nodeDeviceEventCallbacks[] = {
|
||||
VIR_NODE_DEVICE_EVENT_CALLBACK(remoteRelayNodeDeviceEventLifecycle),
|
||||
VIR_NODE_DEVICE_EVENT_CALLBACK(remoteRelayNodeDeviceEventUpdate),
|
||||
};
|
||||
|
||||
verify(ARRAY_CARDINALITY(nodeDeviceEventCallbacks) == VIR_NODE_DEVICE_EVENT_ID_LAST);
|
||||
|
@ -717,6 +717,17 @@ myNodeDeviceEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
myNodeDeviceEventUpdateCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virNodeDevicePtr dev,
|
||||
void *opaque ATTRIBUTE_UNUSED)
|
||||
{
|
||||
printf("%s EVENT: Node device %s update\n", __func__,
|
||||
virNodeDeviceGetName(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
eventTypedParamsPrint(virTypedParameterPtr params,
|
||||
int nparams)
|
||||
@ -989,6 +1000,7 @@ struct nodeDeviceEventData {
|
||||
|
||||
struct nodeDeviceEventData nodeDeviceEvents[] = {
|
||||
NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE, myNodeDeviceEventCallback),
|
||||
NODE_DEVICE_EVENT(VIR_NODE_DEVICE_EVENT_ID_UPDATE, myNodeDeviceEventUpdateCallback),
|
||||
};
|
||||
|
||||
/* make sure that the events are kept in sync */
|
||||
|
@ -138,6 +138,7 @@ int virNodeDeviceDestroy (virNodeDevicePtr dev);
|
||||
*/
|
||||
typedef enum {
|
||||
VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE = 0, /* virConnectNodeDeviceEventLifecycleCallback */
|
||||
VIR_NODE_DEVICE_EVENT_ID_UPDATE = 1, /* virConnectNodeDeviceEventUpdateCallback */
|
||||
|
||||
# ifdef VIR_ENUM_SENTINELS
|
||||
VIR_NODE_DEVICE_EVENT_ID_LAST
|
||||
|
@ -48,10 +48,20 @@ struct _virNodeDeviceEventLifecycle {
|
||||
typedef struct _virNodeDeviceEventLifecycle virNodeDeviceEventLifecycle;
|
||||
typedef virNodeDeviceEventLifecycle *virNodeDeviceEventLifecyclePtr;
|
||||
|
||||
struct _virNodeDeviceEventUpdate {
|
||||
virNodeDeviceEvent parent;
|
||||
|
||||
bool dummy;
|
||||
};
|
||||
typedef struct _virNodeDeviceEventUpdate virNodeDeviceEventUpdate;
|
||||
typedef virNodeDeviceEventUpdate *virNodeDeviceEventUpdatePtr;
|
||||
|
||||
static virClassPtr virNodeDeviceEventClass;
|
||||
static virClassPtr virNodeDeviceEventLifecycleClass;
|
||||
static virClassPtr virNodeDeviceEventUpdateClass;
|
||||
static void virNodeDeviceEventDispose(void *obj);
|
||||
static void virNodeDeviceEventLifecycleDispose(void *obj);
|
||||
static void virNodeDeviceEventUpdateDispose(void *obj);
|
||||
|
||||
static int
|
||||
virNodeDeviceEventsOnceInit(void)
|
||||
@ -68,6 +78,12 @@ virNodeDeviceEventsOnceInit(void)
|
||||
sizeof(virNodeDeviceEventLifecycle),
|
||||
virNodeDeviceEventLifecycleDispose)))
|
||||
return -1;
|
||||
if (!(virNodeDeviceEventUpdateClass =
|
||||
virClassNew(virNodeDeviceEventClass,
|
||||
"virNodeDeviceEventUpdate",
|
||||
sizeof(virNodeDeviceEventUpdate),
|
||||
virNodeDeviceEventUpdateDispose)))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -89,6 +105,14 @@ virNodeDeviceEventLifecycleDispose(void *obj)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virNodeDeviceEventUpdateDispose(void *obj)
|
||||
{
|
||||
virNodeDeviceEventUpdatePtr event = obj;
|
||||
VIR_DEBUG("obj=%p", event);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virNodeDeviceEventDispatchDefaultFunc(virConnectPtr conn,
|
||||
virObjectEventPtr event,
|
||||
@ -114,6 +138,13 @@ virNodeDeviceEventDispatchDefaultFunc(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
case VIR_NODE_DEVICE_EVENT_ID_UPDATE:
|
||||
{
|
||||
((virConnectNodeDeviceEventGenericCallback)cb)(conn, dev,
|
||||
cbopaque);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
case VIR_NODE_DEVICE_EVENT_ID_LAST:
|
||||
break;
|
||||
}
|
||||
@ -232,3 +263,27 @@ virNodeDeviceEventLifecycleNew(const char *name,
|
||||
|
||||
return (virObjectEventPtr)event;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNodeDeviceEventUpdateNew:
|
||||
* @name: name of the node device object the event describes
|
||||
*
|
||||
* Create a new node device update event.
|
||||
*/
|
||||
virObjectEventPtr
|
||||
virNodeDeviceEventUpdateNew(const char *name)
|
||||
{
|
||||
virNodeDeviceEventUpdatePtr event;
|
||||
|
||||
if (virNodeDeviceEventsInitialize() < 0)
|
||||
return NULL;
|
||||
|
||||
if (!(event = virObjectEventNew(virNodeDeviceEventUpdateClass,
|
||||
virNodeDeviceEventDispatchDefaultFunc,
|
||||
VIR_NODE_DEVICE_EVENT_ID_UPDATE,
|
||||
0, name, NULL, name)))
|
||||
return NULL;
|
||||
|
||||
return (virObjectEventPtr)event;
|
||||
}
|
||||
|
@ -56,4 +56,7 @@ virNodeDeviceEventLifecycleNew(const char *name,
|
||||
int type,
|
||||
int detail);
|
||||
|
||||
virObjectEventPtr
|
||||
virNodeDeviceEventUpdateNew(const char *name);
|
||||
|
||||
#endif
|
||||
|
@ -687,6 +687,7 @@ virNodeDeviceObjUnlock;
|
||||
# conf/node_device_event.h
|
||||
virNodeDeviceEventLifecycleNew;
|
||||
virNodeDeviceEventStateRegisterID;
|
||||
virNodeDeviceEventUpdateNew;
|
||||
|
||||
|
||||
# conf/numa_conf.h
|
||||
|
@ -1147,6 +1147,8 @@ static int udevAddOneDevice(struct udev_device *device)
|
||||
event = virNodeDeviceEventLifecycleNew(dev->def->name,
|
||||
VIR_NODE_DEVICE_EVENT_CREATED,
|
||||
0);
|
||||
else
|
||||
event = virNodeDeviceEventUpdateNew(dev->def->name);
|
||||
|
||||
virNodeDeviceObjUnlock(dev);
|
||||
|
||||
|
@ -374,6 +374,11 @@ remoteNodeDeviceBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
void *evdata, void *opaque);
|
||||
|
||||
static void
|
||||
remoteNodeDeviceBuildEventUpdate(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
void *evdata, void *opaque);
|
||||
|
||||
static void
|
||||
remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
@ -565,6 +570,10 @@ static virNetClientProgramEvent remoteEvents[] = {
|
||||
remoteNodeDeviceBuildEventLifecycle,
|
||||
sizeof(remote_node_device_event_lifecycle_msg),
|
||||
(xdrproc_t)xdr_remote_node_device_event_lifecycle_msg },
|
||||
{ REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE,
|
||||
remoteNodeDeviceBuildEventUpdate,
|
||||
sizeof(remote_node_device_event_update_msg),
|
||||
(xdrproc_t)xdr_remote_node_device_event_update_msg },
|
||||
};
|
||||
|
||||
static void
|
||||
@ -5285,6 +5294,27 @@ remoteNodeDeviceBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED
|
||||
remoteEventQueue(priv, event, msg->callbackID);
|
||||
}
|
||||
|
||||
static void
|
||||
remoteNodeDeviceBuildEventUpdate(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
void *evdata, void *opaque)
|
||||
{
|
||||
virConnectPtr conn = opaque;
|
||||
struct private_data *priv = conn->privateData;
|
||||
remote_node_device_event_update_msg *msg = evdata;
|
||||
virNodeDevicePtr dev;
|
||||
virObjectEventPtr event = NULL;
|
||||
|
||||
dev = get_nonnull_node_device(conn, msg->dev);
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
event = virNodeDeviceEventUpdateNew(dev->name);
|
||||
virObjectUnref(dev);
|
||||
|
||||
remoteEventQueue(priv, event, msg->callbackID);
|
||||
}
|
||||
|
||||
static void
|
||||
remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
|
@ -3151,6 +3151,11 @@ struct remote_node_device_event_lifecycle_msg {
|
||||
int detail;
|
||||
};
|
||||
|
||||
struct remote_node_device_event_update_msg {
|
||||
int callbackID;
|
||||
remote_nonnull_node_device dev;
|
||||
};
|
||||
|
||||
struct remote_domain_fsfreeze_args {
|
||||
remote_nonnull_domain dom;
|
||||
remote_nonnull_string mountpoints<REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX>; /* (const char **) */
|
||||
@ -5923,5 +5928,11 @@ enum remote_procedure {
|
||||
* @generate: both
|
||||
* @acl: none
|
||||
*/
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE = 376
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE = 376,
|
||||
|
||||
/**
|
||||
* @generate: both
|
||||
* @acl: none
|
||||
*/
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377
|
||||
};
|
||||
|
@ -2587,6 +2587,10 @@ struct remote_node_device_event_lifecycle_msg {
|
||||
int event;
|
||||
int detail;
|
||||
};
|
||||
struct remote_node_device_event_update_msg {
|
||||
int callbackID;
|
||||
remote_nonnull_node_device dev;
|
||||
};
|
||||
struct remote_domain_fsfreeze_args {
|
||||
remote_nonnull_domain dom;
|
||||
struct {
|
||||
@ -3164,4 +3168,5 @@ enum remote_procedure {
|
||||
REMOTE_PROC_CONNECT_NODE_DEVICE_EVENT_REGISTER_ANY = 374,
|
||||
REMOTE_PROC_CONNECT_NODE_DEVICE_EVENT_DEREGISTER_ANY = 375,
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE = 376,
|
||||
REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377,
|
||||
};
|
||||
|
@ -756,19 +756,21 @@ virshNodeDeviceEventToString(int event)
|
||||
return str ? _(str) : _("unknown");
|
||||
}
|
||||
|
||||
struct vshEventCallback {
|
||||
const char *name;
|
||||
virConnectNodeDeviceEventGenericCallback cb;
|
||||
};
|
||||
typedef struct vshEventCallback vshEventCallback;
|
||||
|
||||
struct virshNodeDeviceEventData {
|
||||
vshControl *ctl;
|
||||
bool loop;
|
||||
bool timestamp;
|
||||
int count;
|
||||
vshEventCallback *cb;
|
||||
};
|
||||
typedef struct virshNodeDeviceEventData virshNodeDeviceEventData;
|
||||
|
||||
VIR_ENUM_DECL(virshNodeDeviceEventId)
|
||||
VIR_ENUM_IMPL(virshNodeDeviceEventId,
|
||||
VIR_NODE_DEVICE_EVENT_ID_LAST,
|
||||
"lifecycle")
|
||||
|
||||
static void
|
||||
vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virNodeDevicePtr dev,
|
||||
@ -800,6 +802,45 @@ vshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
vshEventDone(data->ctl);
|
||||
}
|
||||
|
||||
static void
|
||||
vshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virNodeDevicePtr dev,
|
||||
void *opaque)
|
||||
{
|
||||
virshNodeDeviceEventData *data = opaque;
|
||||
|
||||
if (!data->loop && data->count)
|
||||
return;
|
||||
|
||||
if (data->timestamp) {
|
||||
char timestamp[VIR_TIME_STRING_BUFLEN];
|
||||
|
||||
if (virTimeStringNowRaw(timestamp) < 0)
|
||||
timestamp[0] = '\0';
|
||||
|
||||
vshPrint(data->ctl, _("%s: event '%s'' for node device %s\n"),
|
||||
timestamp,
|
||||
data->cb->name,
|
||||
virNodeDeviceGetName(dev));
|
||||
} else {
|
||||
vshPrint(data->ctl, _("event '%s' for node device %s\n"),
|
||||
data->cb->name,
|
||||
virNodeDeviceGetName(dev));
|
||||
}
|
||||
|
||||
data->count++;
|
||||
if (!data->loop)
|
||||
vshEventDone(data->ctl);
|
||||
}
|
||||
|
||||
static vshEventCallback vshEventCallbacks[] = {
|
||||
{ "lifecycle",
|
||||
VIR_NODE_DEVICE_EVENT_CALLBACK(vshEventLifecyclePrint), },
|
||||
{ "update", vshEventGenericPrint, }
|
||||
};
|
||||
verify(VIR_NODE_DEVICE_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
|
||||
|
||||
|
||||
static const vshCmdInfo info_node_device_event[] = {
|
||||
{.name = "help",
|
||||
.data = N_("Node Device Events")
|
||||
@ -855,7 +896,7 @@ cmdNodeDeviceEvent(vshControl *ctl, const vshCmd *cmd)
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < VIR_NODE_DEVICE_EVENT_ID_LAST; i++)
|
||||
vshPrint(ctl, "%s\n", virshNodeDeviceEventIdTypeToString(i));
|
||||
vshPrint(ctl, "%s\n", vshEventCallbacks[i].name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -865,7 +906,11 @@ cmdNodeDeviceEvent(vshControl *ctl, const vshCmd *cmd)
|
||||
vshError(ctl, "%s", _("either --list or event type is required"));
|
||||
return false;
|
||||
}
|
||||
if ((event = virshNodeDeviceEventIdTypeFromString(eventName)) < 0) {
|
||||
|
||||
for (event = 0; event < VIR_NODE_DEVICE_EVENT_ID_LAST; event++)
|
||||
if (STREQ(eventName, vshEventCallbacks[event].name))
|
||||
break;
|
||||
if (event == VIR_NODE_DEVICE_EVENT_ID_LAST) {
|
||||
vshError(ctl, _("unknown event type %s"), eventName);
|
||||
return false;
|
||||
}
|
||||
@ -874,6 +919,7 @@ cmdNodeDeviceEvent(vshControl *ctl, const vshCmd *cmd)
|
||||
data.loop = vshCommandOptBool(cmd, "loop");
|
||||
data.timestamp = vshCommandOptBool(cmd, "timestamp");
|
||||
data.count = 0;
|
||||
data.cb = &vshEventCallbacks[event];
|
||||
if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
|
||||
return false;
|
||||
if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0)
|
||||
@ -890,7 +936,7 @@ cmdNodeDeviceEvent(vshControl *ctl, const vshCmd *cmd)
|
||||
goto cleanup;
|
||||
|
||||
if ((eventId = virConnectNodeDeviceEventRegisterAny(priv->conn, dev, event,
|
||||
VIR_NODE_DEVICE_EVENT_CALLBACK(vshEventLifecyclePrint),
|
||||
data.cb->cb,
|
||||
&data, NULL)) < 0)
|
||||
goto cleanup;
|
||||
switch (vshEventWait(ctl)) {
|
||||
|
Loading…
Reference in New Issue
Block a user