--- Notes: Already ACKed in version 1 Version 2: - no change daemon/remote.c | 32 +++++++++++++ include/libvirt/libvirt.h.in | 18 ++++++++ python/libvirt-override-virConnect.py | 9 ++++ python/libvirt-override.c | 52 ++++++++++++++++++++- src/conf/domain_event.c | 85 +++++++++++++++++++++++++++-------- src/conf/domain_event.h | 5 +++ src/libvirt_private.syms | 2 + src/remote/remote_driver.c | 32 +++++++++++++ src/remote/remote_protocol.x | 13 +++++- src/remote_protocol-structs | 5 +++ 10 files changed, 233 insertions(+), 20 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 5847e60..a10a308 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -600,6 +600,37 @@ static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUS return 0; } +static int +remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *devAlias, + void *opaque) +{ + virNetServerClientPtr client = opaque; + remote_domain_event_device_removed_msg data; + + if (!client) + return -1; + + VIR_DEBUG("Relaying domain device removed event %s %d %s", + dom->name, dom->id, devAlias); + + /* build return data */ + memset(&data, 0, sizeof(data)); + + if (VIR_STRDUP(data.devAlias, devAlias) < 0) + return -1; + + make_nonnull_domain(&data.dom, dom); + + remoteDispatchDomainEventSend(client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, + (xdrproc_t)xdr_remote_domain_event_device_removed_msg, + &data); + + return 0; +} + static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), @@ -617,6 +648,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspend), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBalloonChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspendDisk), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemoved), }; verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 32c36f1..25cbe48 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -4854,6 +4854,23 @@ typedef void (*virConnectDomainEventPMSuspendDiskCallback)(virConnectPtr conn, int reason, void *opaque); +/** + * virConnectDomainEventDeviceRemovedCallback: + * @conn: connection object + * @dom: domain on which the event occurred + * @devAlias: device alias + * @opaque: application specified data + * + * This callback occurs when a device is removed from the domain. + * + * The callback signature to use when registering for an event of type + * VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED with virConnectDomainEventRegisterAny() + */ +typedef void (*virConnectDomainEventDeviceRemovedCallback)(virConnectPtr conn, + virDomainPtr dom, + const char *devAlias, + void *opaque); + /** * VIR_DOMAIN_EVENT_CALLBACK: @@ -4880,6 +4897,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_PMSUSPEND = 12, /* virConnectDomainEventPMSuspendCallback */ VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE = 13, /* virConnectDomainEventBalloonChangeCallback */ VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK = 14, /* virConnectDomainEventPMSuspendDiskCallback */ + VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED = 15, /* virConnectDomainEventDeviceRemovedCallback */ #ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_ID_LAST diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py index 5495b70..f2b4b23 100644 --- a/python/libvirt-override-virConnect.py +++ b/python/libvirt-override-virConnect.py @@ -179,6 +179,15 @@ cb(self, virDomain(self, _obj=dom), reason, opaque) return 0 + def _dispatchDomainEventDeviceRemovedCallback(self, dom, devAlias, cbData): + """Dispatches event to python user domain device removed event callbacks + """ + cb = cbData["cb"] + opaque = cbData["opaque"] + + cb(self, virDomain(self, _obj=dom), devAlias, opaque) + return 0 + def domainEventDeregisterAny(self, callbackID): """Removes a Domain Event Callback. De-registering for a domain callback will disable delivery of this event type """ diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 01c941e..2e94de9 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -6225,6 +6225,51 @@ libvirt_virConnectDomainEventPMSuspendDiskCallback(virConnectPtr conn ATTRIBUTE_ return ret; } +static int +libvirt_virConnectDomainEventDeviceRemovedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *devAlias, + void *opaque) +{ + PyObject *pyobj_cbData = (PyObject*)opaque; + PyObject *pyobj_dom; + PyObject *pyobj_ret; + PyObject *pyobj_conn; + PyObject *dictKey; + int ret = -1; + + LIBVIRT_ENSURE_THREAD_STATE; + /* Create a python instance of this virDomainPtr */ + virDomainRef(dom); + + pyobj_dom = libvirt_virDomainPtrWrap(dom); + Py_INCREF(pyobj_cbData); + + dictKey = libvirt_constcharPtrWrap("conn"); + pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); + Py_DECREF(dictKey); + + /* Call the Callback Dispatcher */ + pyobj_ret = PyObject_CallMethod(pyobj_conn, + (char*)"_dispatchDomainEventDeviceRemovedCallback", + (char*)"OsO", + pyobj_dom, devAlias, pyobj_cbData); + + Py_DECREF(pyobj_cbData); + Py_DECREF(pyobj_dom); + + if (!pyobj_ret) { + DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); + PyErr_Print(); + } else { + Py_DECREF(pyobj_ret); + ret = 0; + } + + LIBVIRT_RELEASE_THREAD_STATE; + return ret; +} + static PyObject * libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self, PyObject * args) @@ -6254,7 +6299,7 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self, else dom = PyvirDomain_Get(pyobj_dom); - switch (eventID) { + switch ((virDomainEventID) eventID) { case VIR_DOMAIN_EVENT_ID_LIFECYCLE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventLifecycleCallback); break; @@ -6300,6 +6345,11 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self, case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventPMSuspendDiskCallback); break; + case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: + cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDeviceRemovedCallback); + + case VIR_DOMAIN_EVENT_ID_LAST: + break; } if (!cb) { diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index fde24be..640463c 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -122,6 +122,9 @@ struct _virDomainEvent { /* In unit of 1024 bytes */ unsigned long long actual; } balloonChange; + struct { + char *devAlias; + } deviceRemoved; } data; }; @@ -1157,6 +1160,44 @@ virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, return ev; } +static virDomainEventPtr +virDomainEventDeviceRemovedNew(int id, + const char *name, + unsigned char *uuid, + const char *devAlias) +{ + virDomainEventPtr ev = + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, + id, name, uuid); + + if (ev) { + if (VIR_STRDUP(ev->data.deviceRemoved.devAlias, devAlias) < 0) + goto error; + } + + return ev; + +error: + virDomainEventFree(ev); + return NULL; +} + +virDomainEventPtr +virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, + const char *devAlias) +{ + return virDomainEventDeviceRemovedNew(obj->def->id, obj->def->name, + obj->def->uuid, devAlias); +} + +virDomainEventPtr +virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, + const char *devAlias) +{ + return virDomainEventDeviceRemovedNew(dom->id, dom->name, dom->uuid, + devAlias); +} + /** * virDomainEventQueuePush: * @evtQueue: the dom event queue @@ -1204,30 +1245,30 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, return; dom->id = event->dom.id; - switch (event->eventID) { + switch ((virDomainEventID) event->eventID) { case VIR_DOMAIN_EVENT_ID_LIFECYCLE: ((virConnectDomainEventCallback)cb)(conn, dom, event->data.lifecycle.type, event->data.lifecycle.detail, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_REBOOT: (cb)(conn, dom, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_RTC_CHANGE: ((virConnectDomainEventRTCChangeCallback)cb)(conn, dom, event->data.rtcChange.offset, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_WATCHDOG: ((virConnectDomainEventWatchdogCallback)cb)(conn, dom, event->data.watchdog.action, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_IO_ERROR: ((virConnectDomainEventIOErrorCallback)cb)(conn, dom, @@ -1235,7 +1276,7 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, event->data.ioError.devAlias, event->data.ioError.action, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: ((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom, @@ -1244,7 +1285,7 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, event->data.ioError.action, event->data.ioError.reason, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_GRAPHICS: ((virConnectDomainEventGraphicsCallback)cb)(conn, dom, @@ -1254,12 +1295,12 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, event->data.graphics.authScheme, event->data.graphics.subject, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR: (cb)(conn, dom, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: ((virConnectDomainEventBlockJobCallback)cb)(conn, dom, @@ -1267,7 +1308,7 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, event->data.blockJob.type, event->data.blockJob.status, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: ((virConnectDomainEventDiskChangeCallback)cb)(conn, dom, @@ -1276,38 +1317,46 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, event->data.diskChange.devAlias, event->data.diskChange.reason, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: ((virConnectDomainEventTrayChangeCallback)cb)(conn, dom, event->data.trayChange.devAlias, event->data.trayChange.reason, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_PMWAKEUP: ((virConnectDomainEventPMWakeupCallback)cb)(conn, dom, 0, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_PMSUSPEND: ((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE: ((virConnectDomainEventBalloonChangeCallback)cb)(conn, dom, event->data.balloonChange.actual, cbopaque); - break; + goto cleanup; case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: ((virConnectDomainEventPMSuspendDiskCallback)cb)(conn, dom, 0, cbopaque); - break; + goto cleanup; - default: - VIR_WARN("Unexpected event ID %d", event->eventID); + case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: + ((virConnectDomainEventDeviceRemovedCallback)cb)(conn, dom, + event->data.deviceRemoved.devAlias, + cbopaque); + goto cleanup; + + case VIR_DOMAIN_EVENT_ID_LAST: break; } + VIR_WARN("Unexpected event ID %d", event->eventID); + +cleanup: virDomainFree(dom); } diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index 5f64a47..f6b957d 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -132,6 +132,11 @@ virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, uns virDomainEventPtr virDomainEventPMSuspendDiskNewFromObj(virDomainObjPtr obj); virDomainEventPtr virDomainEventPMSuspendDiskNewFromDom(virDomainPtr dom); +virDomainEventPtr virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj, + const char *devAlias); +virDomainEventPtr virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom, + const char *devAlias); + void virDomainEventFree(virDomainEventPtr event); void virDomainEventStateFree(virDomainEventStatePtr state); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fc4e750..d4bf8e3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -407,6 +407,8 @@ virDomainEventBlockJobNewFromDom; virDomainEventBlockJobNewFromObj; virDomainEventControlErrorNewFromDom; virDomainEventControlErrorNewFromObj; +virDomainEventDeviceRemovedNewFromDom; +virDomainEventDeviceRemovedNewFromObj; virDomainEventDiskChangeNewFromDom; virDomainEventDiskChangeNewFromObj; virDomainEventFree; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 0298aab..3d58e31 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -268,6 +268,11 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog, virNetClientPtr client, void *evdata, void *opaque); +static void +remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + static virNetClientProgramEvent remoteDomainEvents[] = { { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, remoteDomainBuildEventRTCChange, @@ -329,6 +334,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = { remoteDomainBuildEventPMSuspendDisk, sizeof(remote_domain_event_pmsuspend_disk_msg), (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg }, + { REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED, + remoteDomainBuildEventDeviceRemoved, + sizeof(remote_domain_event_device_removed_msg), + (xdrproc_t)xdr_remote_domain_event_device_removed_msg }, }; enum virDrvOpenRemoteFlags { @@ -4695,6 +4704,29 @@ remoteDomainBuildEventPMSuspendDisk(virNetClientProgramPtr prog ATTRIBUTE_UNUSED } +static void +remoteDomainBuildEventDeviceRemoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn = opaque; + struct private_data *priv = conn->privateData; + remote_domain_event_device_removed_msg *msg = evdata; + virDomainPtr dom; + virDomainEventPtr event = NULL; + + dom = get_nonnull_domain(conn, msg->dom); + if (!dom) + return; + + event = virDomainEventDeviceRemovedNewFromDom(dom, msg->devAlias); + + virDomainFree(dom); + + remoteDomainEventQueue(priv, event); +} + + static virDrvOpenStatus ATTRIBUTE_NONNULL(1) remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d1c77f5..84d696b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2814,6 +2814,11 @@ struct remote_domain_migrate_confirm3_params_args { int cancelled; }; +struct remote_domain_event_device_removed_msg { + remote_nonnull_domain dom; + remote_nonnull_string devAlias; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -4958,5 +4963,11 @@ enum remote_procedure { * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ - REMOTE_PROC_DOMAIN_SET_MEMORY_STATS_PERIOD = 308 + REMOTE_PROC_DOMAIN_SET_MEMORY_STATS_PERIOD = 308, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 309 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 86e7650..cfc84dd 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2298,6 +2298,10 @@ struct remote_domain_migrate_confirm3_params_args { u_int flags; int cancelled; }; +struct remote_domain_event_device_removed_msg { + remote_nonnull_domain dom; + remote_nonnull_string devAlias; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -2607,4 +2611,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_FINISH3_PARAMS = 306, REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307, REMOTE_PROC_DOMAIN_SET_MEMORY_STATS_PERIOD = 308, + REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 309, }; -- 1.8.3.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list