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),
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);
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:
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
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 """
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)
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;
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) {
/* In unit of 1024 bytes */
unsigned long long actual;
} balloonChange;
+ struct {
+ char *devAlias;
+ } deviceRemoved;
} data;
};
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
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,
event->data.ioError.devAlias,
event->data.ioError.action,
cbopaque);
- break;
+ goto cleanup;
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom,
event->data.ioError.action,
event->data.ioError.reason,
cbopaque);
- break;
+ goto cleanup;
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
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,
event->data.blockJob.type,
event->data.blockJob.status,
cbopaque);
- break;
+ goto cleanup;
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
((virConnectDomainEventDiskChangeCallback)cb)(conn, dom,
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);
}
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);
virDomainEventBlockJobNewFromObj;
virDomainEventControlErrorNewFromDom;
virDomainEventControlErrorNewFromObj;
+virDomainEventDeviceRemovedNewFromDom;
+virDomainEventDeviceRemovedNewFromObj;
virDomainEventDiskChangeNewFromDom;
virDomainEventDiskChangeNewFromObj;
virDomainEventFree;
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,
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 {
}
+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)
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. */
* @generate: none
* @acl: domain:start
*/
- REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310
+ REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
+
+ /**
+ * @generate: both
+ * @acl: none
+ */
+ REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311
};
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,
REMOTE_PROC_DOMAIN_SET_MEMORY_STATS_PERIOD = 308,
REMOTE_PROC_DOMAIN_CREATE_XML_WITH_FILES = 309,
REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
+ REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
};