From 1882c0bd8d9ebedea527419df32098bdd24b4047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Mon, 30 Mar 2015 18:46:21 +0200 Subject: [PATCH] Add VIR_DOMAIN_EVENT_ID_DEVICE_ADDED event The counterpart to VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED. https://bugzilla.redhat.com/show_bug.cgi?id=1206114 --- daemon/remote.c | 37 +++++++++++++++ include/libvirt/libvirt-domain.h | 18 ++++++++ src/conf/domain_event.c | 77 ++++++++++++++++++++++++++++++++ src/conf/domain_event.h | 6 +++ src/libvirt_private.syms | 2 + src/remote/remote_driver.c | 29 ++++++++++++ src/remote/remote_protocol.x | 14 +++++- src/remote_protocol-structs | 6 +++ tools/virsh-domain.c | 20 +++++++++ 9 files changed, 208 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index 2e1f973b94..3a3f1683e9 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1045,6 +1045,42 @@ remoteRelayDomainEventAgentLifecycle(virConnectPtr conn, } +static int +remoteRelayDomainEventDeviceAdded(virConnectPtr conn, + virDomainPtr dom, + const char *devAlias, + void *opaque) +{ + daemonClientEventCallbackPtr callback = opaque; + remote_domain_event_callback_device_added_msg data; + + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) + return -1; + + VIR_DEBUG("Relaying domain device added event %s %d %s, callback %d", + dom->name, dom->id, devAlias, callback->callbackID); + + /* build return data */ + memset(&data, 0, sizeof(data)); + + if (VIR_STRDUP(data.devAlias, devAlias) < 0) + return -1; + + make_nonnull_domain(&data.dom, dom); + data.callbackID = callback->callbackID, + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED, + (xdrproc_t)xdr_remote_domain_event_callback_device_added_msg, + &data); + + return 0; +} + + + + static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), @@ -1065,6 +1101,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob2), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTunable), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventAgentLifecycle), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceAdded), }; verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 7be421942d..8a4fe531d2 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3201,6 +3201,23 @@ typedef void (*virConnectDomainEventDeviceRemovedCallback)(virConnectPtr conn, const char *devAlias, void *opaque); +/** + * virConnectDomainEventDeviceAddedCallback: + * @conn: connection object + * @dom: domain on which the event occurred + * @devAlias: device alias + * @opaque: application specified data + * + * This callback occurs when a device is added to the domain. + * + * The callback signature to use when registering for an event of type + * VIR_DOMAIN_EVENT_ID_DEVICE_ADDED with virConnectDomainEventRegisterAny() + */ +typedef void (*virConnectDomainEventDeviceAddedCallback)(virConnectPtr conn, + virDomainPtr dom, + const char *devAlias, + void *opaque); + /** * VIR_DOMAIN_TUNABLE_CPU_VCPUPIN: * @@ -3483,6 +3500,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 = 16, /* virConnectDomainEventBlockJobCallback */ VIR_DOMAIN_EVENT_ID_TUNABLE = 17, /* virConnectDomainEventTunableCallback */ VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE = 18,/* virConnectDomainEventAgentLifecycleCallback */ + VIR_DOMAIN_EVENT_ID_DEVICE_ADDED = 19, /* virConnectDomainEventDeviceAddedCallback */ # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_ID_LAST diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 2786c1eeb0..20d66e11c8 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -55,6 +55,7 @@ static virClassPtr virDomainEventPMClass; static virClassPtr virDomainQemuMonitorEventClass; static virClassPtr virDomainEventTunableClass; static virClassPtr virDomainEventAgentLifecycleClass; +static virClassPtr virDomainEventDeviceAddedClass; static void virDomainEventDispose(void *obj); @@ -72,6 +73,7 @@ static void virDomainEventPMDispose(void *obj); static void virDomainQemuMonitorEventDispose(void *obj); static void virDomainEventTunableDispose(void *obj); static void virDomainEventAgentLifecycleDispose(void *obj); +static void virDomainEventDeviceAddedDispose(void *obj); static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, @@ -189,6 +191,14 @@ struct _virDomainEventDeviceRemoved { typedef struct _virDomainEventDeviceRemoved virDomainEventDeviceRemoved; typedef virDomainEventDeviceRemoved *virDomainEventDeviceRemovedPtr; +struct _virDomainEventDeviceAdded { + virDomainEvent parent; + + char *devAlias; +}; +typedef struct _virDomainEventDeviceAdded virDomainEventDeviceAdded; +typedef virDomainEventDeviceAdded *virDomainEventDeviceAddedPtr; + struct _virDomainEventPM { virDomainEvent parent; @@ -296,6 +306,12 @@ virDomainEventsOnceInit(void) sizeof(virDomainEventDeviceRemoved), virDomainEventDeviceRemovedDispose))) return -1; + if (!(virDomainEventDeviceAddedClass = + virClassNew(virDomainEventClass, + "virDomainEventDeviceAdded", + sizeof(virDomainEventDeviceAdded), + virDomainEventDeviceAddedDispose))) + return -1; if (!(virDomainEventPMClass = virClassNew(virDomainEventClass, "virDomainEventPM", @@ -438,6 +454,15 @@ virDomainEventDeviceRemovedDispose(void *obj) VIR_FREE(event->devAlias); } +static void +virDomainEventDeviceAddedDispose(void *obj) +{ + virDomainEventDeviceAddedPtr event = obj; + VIR_DEBUG("obj=%p", event); + + VIR_FREE(event->devAlias); +} + static void virDomainEventPMDispose(void *obj) { @@ -1226,6 +1251,47 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, devAlias); } +static virObjectEventPtr +virDomainEventDeviceAddedNew(int id, + const char *name, + unsigned char *uuid, + const char *devAlias) +{ + virDomainEventDeviceAddedPtr ev; + + if (virDomainEventsInitialize() < 0) + return NULL; + + if (!(ev = virDomainEventNew(virDomainEventDeviceAddedClass, + VIR_DOMAIN_EVENT_ID_DEVICE_ADDED, + id, name, uuid))) + return NULL; + + if (VIR_STRDUP(ev->devAlias, devAlias) < 0) + goto error; + + return (virObjectEventPtr)ev; + + error: + virObjectUnref(ev); + return NULL; +} + +virObjectEventPtr +virDomainEventDeviceAddedNewFromObj(virDomainObjPtr obj, + const char *devAlias) +{ + return virDomainEventDeviceAddedNew(obj->def->id, obj->def->name, + obj->def->uuid, devAlias); +} + +virObjectEventPtr +virDomainEventDeviceAddedNewFromDom(virDomainPtr dom, + const char *devAlias) +{ + return virDomainEventDeviceAddedNew(dom->id, dom->name, dom->uuid, + devAlias); +} static virObjectEventPtr virDomainEventAgentLifecycleNew(int id, @@ -1537,6 +1603,17 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, goto cleanup; } + case VIR_DOMAIN_EVENT_ID_DEVICE_ADDED: + { + virDomainEventDeviceAddedPtr deviceAddedEvent; + + deviceAddedEvent = (virDomainEventDeviceAddedPtr)event; + ((virConnectDomainEventDeviceAddedCallback)cb)(conn, dom, + deviceAddedEvent->devAlias, + 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 534ff9eb4a..afbed89616 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -185,6 +185,12 @@ virObjectEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, const char *devAlias); virObjectEventPtr +virDomainEventDeviceAddedNewFromObj(virDomainObjPtr obj, + const char *devAlias); +virObjectEventPtr +virDomainEventDeviceAddedNewFromDom(virDomainPtr dom, + const char *devAlias); +virObjectEventPtr virDomainEventTunableNewFromObj(virDomainObjPtr obj, virTypedParameterPtr params, int nparams); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6dd3b6f103..216fd59a36 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -487,6 +487,8 @@ virDomainEventBlockJobNewFromDom; virDomainEventBlockJobNewFromObj; virDomainEventControlErrorNewFromDom; virDomainEventControlErrorNewFromObj; +virDomainEventDeviceAddedNewFromDom; +virDomainEventDeviceAddedNewFromObj; virDomainEventDeviceRemovedNewFromDom; virDomainEventDeviceRemovedNewFromObj; virDomainEventDiskChangeNewFromDom; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b275d86b99..9c3b53fe5d 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -321,6 +321,10 @@ static void remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); static void remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog, @@ -496,6 +500,10 @@ static virNetClientProgramEvent remoteEvents[] = { remoteDomainBuildEventCallbackAgentLifecycle, sizeof(remote_domain_event_callback_agent_lifecycle_msg), (xdrproc_t)xdr_remote_domain_event_callback_agent_lifecycle_msg }, + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED, + remoteDomainBuildEventCallbackDeviceAdded, + sizeof(remote_domain_event_callback_device_added_msg), + (xdrproc_t)xdr_remote_domain_event_callback_device_added_msg }, }; @@ -5431,6 +5439,27 @@ remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog ATTRIBUT remoteDomainBuildEventDeviceRemovedHelper(conn, &msg->msg, msg->callbackID); } +static void +remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + remote_domain_event_callback_device_added_msg *msg = evdata; + struct private_data *priv = conn->privateData; + virDomainPtr dom; + virObjectEventPtr event = NULL; + + dom = get_nonnull_domain(conn, msg->dom); + if (!dom) + return; + + event = virDomainEventDeviceAddedNewFromDom(dom, msg->devAlias); + + virObjectUnref(dom); + + remoteEventQueue(priv, event, msg->callbackID); +} static void remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d90e6b5f5f..b02e58c382 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3045,6 +3045,12 @@ struct remote_domain_event_callback_tunable_msg { remote_typed_param params; }; +struct remote_domain_event_callback_device_added_msg { + int callbackID; + remote_nonnull_domain dom; + remote_nonnull_string devAlias; +}; + struct remote_connect_get_cpu_model_names_args { remote_nonnull_string arch; int need_results; @@ -5643,5 +5649,11 @@ enum remote_procedure { * @generate: none * @acl: domain:read */ - REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 353 + REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 353, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED = 354 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index e614f772ab..2b6b47a3b4 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2487,6 +2487,11 @@ struct remote_domain_event_callback_tunable_msg { remote_typed_param * params_val; } params; }; +struct remote_domain_event_callback_device_added_msg { + int callbackID; + remote_nonnull_domain dom; + remote_nonnull_string devAlias; +}; struct remote_connect_get_cpu_model_names_args { remote_nonnull_string arch; int need_results; @@ -3017,4 +3022,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_IOTHREAD_INFO = 351, REMOTE_PROC_DOMAIN_PIN_IOTHREAD = 352, REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 353, + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED = 354, }; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 2fe3924aa5..4f58f07a6b 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -11861,6 +11861,24 @@ vshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED, vshEventDone(data->ctl); } +static void +vshEventDeviceAddedPrint(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *alias, + void *opaque) +{ + vshDomEventData *data = opaque; + + if (!data->loop && *data->count) + return; + vshPrint(data->ctl, + _("event 'device-added' for domain %s: %s\n"), + virDomainGetName(dom), alias); + (*data->count)++; + if (!data->loop) + vshEventDone(data->ctl); +} + static void vshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, @@ -11966,6 +11984,8 @@ static vshEventCallback vshEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(vshEventTunablePrint), }, { "agent-lifecycle", VIR_DOMAIN_EVENT_CALLBACK(vshEventAgentLifecyclePrint), }, + { "device-added", + VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceAddedPrint), }, }; verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));