On Mon, Mar 05, 2012 at 06:25:39PM +0800, Osier Yang wrote: > This patch introduces a new event type for the QMP event > DEVICE_TRAY_MOVED, which occurs when the tray of a removable > disk is moved (i.e opened or closed): > > VIR_DOMAIN_EVENT_ID_TRAY_MOVED > > The event's data includes the device alias and the tray's > status, which indicates whether the tray has been opened > or closed. Thus the callback definition for the event is: > > typedef void > (*virConnectDomainEventTrayMovedCallback)(virConnectPtr conn, > virDomainPtr dom, > const char *devAlias, > unsigned int trayOpened, > void *opaque); Hum ... could we make that slightly more generic. Instead of just being able to report on tray opened or not (i.e. closed) Let's report TrayChangeCallback, and have an 'int reason' instead. Then for example the API would be able to cope with more set of events, one of the thing I can think of now would be the ability to emulate multiple device in one as disk changers, and also possibly be able to provide invormations about the kind of media, i.e. switch from a CD-ROM to a DVD-WR in the tray. > --- > daemon/remote.c | 33 +++++++++++ > examples/domain-events/events-c/event-test.c | 21 +++++++- > examples/domain-events/events-python/event-test.py | 4 ++ > include/libvirt/libvirt.h.in | 20 +++++++ > python/libvirt-override-virConnect.py | 10 ++++ > python/libvirt-override.c | 50 +++++++++++++++++ > src/conf/domain_event.c | 58 ++++++++++++++++++++ > src/conf/domain_event.h | 6 ++ > src/libvirt_private.syms | 2 + > src/qemu/qemu_monitor.c | 13 +++++ > src/qemu/qemu_monitor.h | 7 +++ > src/qemu/qemu_monitor_json.c | 18 ++++++ > src/qemu/qemu_process.c | 32 +++++++++++ > src/remote/remote_driver.c | 34 ++++++++++++ > src/remote/remote_protocol.x | 9 +++- > src/remote_protocol-structs | 5 ++ > 16 files changed, 320 insertions(+), 2 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index 74a5f16..cc464fd 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -505,6 +505,38 @@ mem_error: > } > > > +static int remoteRelayDomainEventTrayMoved(virConnectPtr conn ATTRIBUTE_UNUSED, > + virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened, > + void *opaque) { > + virNetServerClientPtr client = opaque; > + remote_domain_event_tray_moved_msg data; > + > + if (!client) > + return -1; > + > + VIR_DEBUG("Relaying domain %s %d tray moved devAlias: %s trayOpened: %s", > + dom->name, dom->id, devAlias, trayOpened ? "yes": "no"); > + > + /* build return data */ > + memset(&data, 0, sizeof data); > + > + if (!(data.devAlias = strdup(devAlias))) { > + virReportOOMError(); > + return -1; > + } > + data.trayOpened = trayOpened; > + > + make_nonnull_domain(&data.dom, dom); > + > + remoteDispatchDomainEventSend(client, remoteProgram, > + REMOTE_PROC_DOMAIN_EVENT_TRAY_MOVED, > + (xdrproc_t)xdr_remote_domain_event_tray_moved_msg, &data); > + > + return 0; > +} > + > static virConnectDomainEventGenericCallback domainEventCallbacks[] = { > VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), > VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), > @@ -516,6 +548,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = { > VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventControlError), > VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob), > VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDiskChange), > + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTrayMoved), > }; > > verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); > diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c > index f4938c4..c7bcaeb 100644 > --- a/examples/domain-events/events-c/event-test.c > +++ b/examples/domain-events/events-c/event-test.c > @@ -313,6 +313,17 @@ static int myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, > return 0; > } > > +static int myDomainEventTrayMovedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, > + virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened, > + void *opaque ATTRIBUTE_UNUSED) > +{ > + printf("%s EVENT: Domain %s(%d) removable disk's tray moved devAlias: %s trayOpened: %s\n", > + __func__, virDomainGetName(dom), virDomainGetID(dom), > + devAlias, trayOpened ? "yes" : "no"); > + return 0; > +} > > static void myFreeFunc(void *opaque) > { > @@ -349,6 +360,7 @@ int main(int argc, char **argv) > int callback7ret = -1; > int callback8ret = -1; > int callback9ret = -1; > + int callback10ret = -1; > struct sigaction action_stop; > > memset(&action_stop, 0, sizeof action_stop); > @@ -419,6 +431,11 @@ int main(int argc, char **argv) > VIR_DOMAIN_EVENT_ID_DISK_CHANGE, > VIR_DOMAIN_EVENT_CALLBACK(myDomainEventDiskChangeCallback), > strdup("disk change"), myFreeFunc); > + callback10ret = virConnectDomainEventRegisterAny(dconn, > + NULL, > + VIR_DOMAIN_EVENT_ID_TRAY_MOVED, > + VIR_DOMAIN_EVENT_CALLBACK(myDomainEventTrayMovedCallback), > + strdup("tray moved"), myFreeFunc); > > if ((callback1ret != -1) && > (callback2ret != -1) && > @@ -427,7 +444,8 @@ int main(int argc, char **argv) > (callback5ret != -1) && > (callback6ret != -1) && > (callback7ret != -1) && > - (callback9ret != -1)) { > + (callback9ret != -1) && > + (callback10ret != -1)) { > if (virConnectSetKeepAlive(dconn, 5, 3) < 0) { > virErrorPtr err = virGetLastError(); > fprintf(stderr, "Failed to start keepalive protocol: %s\n", > @@ -452,6 +470,7 @@ int main(int argc, char **argv) > virConnectDomainEventDeregisterAny(dconn, callback6ret); > virConnectDomainEventDeregisterAny(dconn, callback7ret); > virConnectDomainEventDeregisterAny(dconn, callback9ret); > + virConnectDomainEventDeregisterAny(dconn, callback10ret); > if (callback8ret != -1) > virConnectDomainEventDeregisterAny(dconn, callback8ret); > } > diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py > index 0c75091..f2f5597 100644 > --- a/examples/domain-events/events-python/event-test.py > +++ b/examples/domain-events/events-python/event-test.py > @@ -474,6 +474,9 @@ def myDomainEventGraphicsCallback(conn, dom, phase, localAddr, remoteAddr, authS > def myDomainEventDiskChangeCallback(conn, dom, oldSrcPath, newSrcPath, devAlias, reason, opaque): > print "myDomainEventDiskChangeCallback: Domain %s(%s) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s" % ( > dom.name(), dom.ID(), oldSrcPath, newSrcPath, devAlias, reason) > +def myDomainEventTrayMovedCallback(conn, dom, devAlias, trayOpened, opaque): > + print "myDomainEventTrayMovedCallback: Domain %s(%s) tray moved devAlias: %s trayOpened: %d" % ( > + dom.name(), dom.ID(), devAlias, trayOpened) > def usage(out=sys.stderr): > print >>out, "usage: "+os.path.basename(sys.argv[0])+" [-hdl] [uri]" > print >>out, " uri will default to qemu:///system" > @@ -532,6 +535,7 @@ def main(): > vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback, None) > vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback, None) > vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DISK_CHANGE, myDomainEventDiskChangeCallback, None) > + vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_TRAY_MOVED, myDomainEventTrayMovedCallback, None) > > vc.setKeepAlive(5, 3) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 58c4366..730f2a3 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -3643,6 +3643,25 @@ typedef void (*virConnectDomainEventDiskChangeCallback)(virConnectPtr conn, > const char *devAlias, > int reason, > void *opaque); > +/** > + * virConnectDomainEventTrayMovedCallback: > + * @conn: connection object > + * @dom: domain on which the event occurred > + * @devAlias: device alias > + * @trayOpened: the tray has been opened? > + * @opaque: application specified data > + * > + * This callback occurs when the tray of a removable device is moved. > + * > + * The callback signature to use when registering for an event of type > + * VIR_DOMAIN_EVENT_ID_TRAY_MOVED with virConnectDomainEventRegisterAny() > + */ > +typedef void (*virConnectDomainEventTrayMovedCallback)(virConnectPtr conn, > + virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened, > + void *opaque); > + > > /** > * VIR_DOMAIN_EVENT_CALLBACK: > @@ -3664,6 +3683,7 @@ typedef enum { > VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = 7, /* virConnectDomainEventGenericCallback */ > VIR_DOMAIN_EVENT_ID_BLOCK_JOB = 8, /* virConnectDomainEventBlockJobCallback */ > VIR_DOMAIN_EVENT_ID_DISK_CHANGE = 9, /* virConnectDomainEventDiskChangeCallback */ > + VIR_DOMAIN_EVENT_ID_TRAY_MOVED = 10, /* virConnectDomainEventTrayMovedCallback */ > > #ifdef VIR_ENUM_SENTINELS > /* > diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py > index b908b32..e93efa7 100644 > --- a/python/libvirt-override-virConnect.py > +++ b/python/libvirt-override-virConnect.py > @@ -134,6 +134,16 @@ > cb(self, virDomain(self, _obj=dom), oldSrcPath, newSrcPath, devAlias, reason, opaque) > return 0; > > + def _dispatchDomainEventTrayMovedCallback(self, dom, devAlias, trayOpened, cbData): > + """Dispatches event to python user domain trayMoved event callbacks > + """ > + cb = cbData["cb"] > + opaque = cbData["opaque"] > + > + cb(self, virDomain(self, _obj=dom), devAlias, trayOpened, 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 792cfa3..976c5d8 100644 > --- a/python/libvirt-override.c > +++ b/python/libvirt-override.c > @@ -4927,6 +4927,53 @@ libvirt_virConnectDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNU > return ret; > } > > +static int > +libvirt_virConnectDomainEventTrayMovedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, > + virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened, > + 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*)"_dispatchDomainEventTrayMovedCallback", > + (char*)"OsiO", > + pyobj_dom, > + devAlias, trayOpened, 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) > @@ -4987,6 +5034,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self, > case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: > cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDiskChangeCallback); > break; > + case VIR_DOMAIN_EVENT_ID_TRAY_MOVED: > + cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventTrayMovedCallback); > + break; > } > > if (!cb) { > diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c > index 1d8b45d..dbd1bf1 100644 > --- a/src/conf/domain_event.c > +++ b/src/conf/domain_event.c > @@ -117,6 +117,10 @@ struct _virDomainEvent { > char *devAlias; > int reason; > } diskChange; > + struct { > + char *devAlias; > + unsigned int trayOpened :1; > + } trayMoved; > } data; > }; > > @@ -546,6 +550,9 @@ void virDomainEventFree(virDomainEventPtr event) > VIR_FREE(event->data.diskChange.newSrcPath); > VIR_FREE(event->data.diskChange.devAlias); > break; > + case VIR_DOMAIN_EVENT_ID_TRAY_MOVED: > + VIR_FREE(event->data.trayMoved.devAlias); > + break; > } > > VIR_FREE(event->dom.name); > @@ -1043,6 +1050,50 @@ virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, > devAlias, reason); > } > > +static virDomainEventPtr > +virDomainEventTrayMovedNew(int id, const char *name, > + unsigned char *uuid, > + const char *devAlias, > + unsigned int trayOpened) > +{ > + virDomainEventPtr ev = > + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_MOVED, > + id, name, uuid); > + > + if (ev) { > + if (!(ev->data.trayMoved.devAlias = strdup(devAlias))) > + goto error; > + > + ev->data.trayMoved.trayOpened = trayOpened; > + } > + > + return ev; > + > +error: > + virReportOOMError(); > + virDomainEventFree(ev); > + return NULL; > +} > + > +virDomainEventPtr virDomainEventTrayMovedNewFromObj(virDomainObjPtr obj, > + const char *devAlias, > + unsigned int trayOpened) > +{ > + return virDomainEventTrayMovedNew(obj->def->id, > + obj->def->name, > + obj->def->uuid, > + devAlias, > + trayOpened); > +} > + > +virDomainEventPtr virDomainEventTrayMovedNewFromDom(virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened) > +{ > + return virDomainEventTrayMovedNew(dom->id, dom->name, dom->uuid, > + devAlias, trayOpened); > +} > + > > /** > * virDomainEventQueuePush: > @@ -1167,6 +1218,13 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, > cbopaque); > break; > > + case VIR_DOMAIN_EVENT_ID_TRAY_MOVED: > + ((virConnectDomainEventTrayMovedCallback)cb)(conn, dom, > + event->data.trayMoved.devAlias, > + event->data.trayMoved.trayOpened, > + cbopaque); > + break; > + > default: > VIR_WARN("Unexpected event ID %d", event->eventID); > break; > diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h > index 0e7cd75..3351be0 100644 > --- a/src/conf/domain_event.h > +++ b/src/conf/domain_event.h > @@ -114,6 +114,12 @@ virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom, > const char *newSrcPath, > const char *devAlias, > int reason); > +virDomainEventPtr virDomainEventTrayMovedNewFromObj(virDomainObjPtr obj, > + const char *devAlias, > + unsigned int trayOpened); > +virDomainEventPtr virDomainEventTrayMovedNewFromDom(virDomainPtr dom, > + const char *devAlias, > + unsigned int trayOpened); > > void virDomainEventFree(virDomainEventPtr event); > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index a104e70..27d4ad3 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -512,6 +512,8 @@ virDomainEventStateRegisterID; > virDomainEventStateFree; > virDomainEventStateNew; > virDomainEventStateQueue; > +virDomainEventTrayMovedNewFromDom; > +virDomainEventTrayMovedNewFromObj; > virDomainEventWatchdogNewFromDom; > virDomainEventWatchdogNewFromObj; > > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index 1da73f6..dfa2960 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -1040,6 +1040,19 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon, > return ret; > } > > +int qemuMonitorEmitTrayMoved(qemuMonitorPtr mon, > + const char *devAlias, > + unsigned int trayOpened) > +{ > + int ret = -1; > + VIR_DEBUG("mon=%p", mon); > + > + QEMU_MONITOR_CALLBACK(mon, ret, domainTrayMoved, mon->vm, > + devAlias, trayOpened); > + > + return ret; > +} > + > int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, > const char *diskAlias, > int type, > diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h > index b1c956c..18e6801 100644 > --- a/src/qemu/qemu_monitor.h > +++ b/src/qemu/qemu_monitor.h > @@ -124,6 +124,10 @@ struct _qemuMonitorCallbacks { > const char *diskAlias, > int type, > int status); > + int (*domainTrayMoved)(qemuMonitorPtr mon, > + virDomainObjPtr vm, > + const char *devAlias, > + unsigned int trayOpened); > }; > > > @@ -191,6 +195,9 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon, > const char *authScheme, > const char *x509dname, > const char *saslUsername); > +int qemuMonitorEmitTrayMoved(qemuMonitorPtr mon, > + const char *devAlias, > + unsigned int trayOpened); > int qemuMonitorEmitBlockJob(qemuMonitorPtr mon, > const char *diskAlias, > int type, > diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c > index c0f148b..ac6b02c 100644 > --- a/src/qemu/qemu_monitor_json.c > +++ b/src/qemu/qemu_monitor_json.c > @@ -59,6 +59,7 @@ static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr > static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data); > static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data); > static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr data); > +static void qemuMonitorJSONHandleTrayMoved(qemuMonitorPtr mon, virJSONValuePtr data); > > static struct { > const char *type; > @@ -75,6 +76,7 @@ static struct { > { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, }, > { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, }, > { "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJob, }, > + { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayMoved, }, > }; > > > @@ -725,6 +727,22 @@ out: > qemuMonitorEmitBlockJob(mon, device, type, status); > } > > +static void qemuMonitorJSONHandleTrayMoved(qemuMonitorPtr mon, virJSONValuePtr data) > +{ > + const char *devAlias = NULL; > + bool trayOpened; > + > + if ((devAlias = virJSONValueObjectGetString(data, "device")) == NULL) { > + VIR_WARN("missing device in tray moved event"); > + return; > + } > + > + if (virJSONValueObjectGetBoolean(data, "tray-open", &trayOpened) < 0) { > + VIR_WARN("missing tray-open in tray moved event"); > + return; > + } > + qemuMonitorEmitTrayMoved(mon, devAlias, (unsigned int)trayOpened); > +} > > int > qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon, > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 7b99814..387811a 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -1021,6 +1021,37 @@ static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon, > virDomainObjUnlock(vm); > } > > +static int > +qemuProcessHandleTrayMoved(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > + virDomainObjPtr vm, > + const char *devAlias, > + unsigned int trayOpened) > +{ > + struct qemud_driver *driver = qemu_driver; > + virDomainEventPtr event = NULL; > + virDomainDiskDefPtr disk; > + > + virDomainObjLock(vm); > + disk = qemuProcessFindDomainDiskByAlias(vm, devAlias); > + > + if (disk) { > + event = virDomainEventTrayMovedNewFromObj(vm, > + devAlias, > + trayOpened); > + } > + > + virDomainObjUnlock(vm); > + > + if (event) { > + qemuDriverLock(driver); > + qemuDomainEventQueue(driver, event); > + qemuDriverUnlock(driver); > + } > + > + return 0; > +} > + > + > static qemuMonitorCallbacks monitorCallbacks = { > .destroy = qemuProcessHandleMonitorDestroy, > .eofNotify = qemuProcessHandleMonitorEOF, > @@ -1034,6 +1065,7 @@ static qemuMonitorCallbacks monitorCallbacks = { > .domainIOError = qemuProcessHandleIOError, > .domainGraphics = qemuProcessHandleGraphics, > .domainBlockJob = qemuProcessHandleBlockJob, > + .domainTrayMoved = qemuProcessHandleTrayMoved, > }; > > static int > diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c > index 9e74cea..31d09a9 100644 > --- a/src/remote/remote_driver.c > +++ b/src/remote/remote_driver.c > @@ -238,6 +238,11 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog, > virNetClientPtr client, > void *evdata, void *opaque); > > +static void > +remoteDomainBuildEventTrayMoved(virNetClientProgramPtr prog, > + virNetClientPtr client, > + void *evdata, void *opaque); > + > static virNetClientProgramEvent remoteDomainEvents[] = { > { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE, > remoteDomainBuildEventRTCChange, > @@ -279,6 +284,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = { > remoteDomainBuildEventDiskChange, > sizeof(remote_domain_event_disk_change_msg), > (xdrproc_t)xdr_remote_domain_event_disk_change_msg }, > + { REMOTE_PROC_DOMAIN_EVENT_TRAY_MOVED, > + remoteDomainBuildEventTrayMoved, > + sizeof(remote_domain_event_tray_moved_msg), > + (xdrproc_t)xdr_remote_domain_event_tray_moved_msg }, > }; > > enum virDrvOpenRemoteFlags { > @@ -3643,6 +3652,31 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, > } > > > +static void > +remoteDomainBuildEventTrayMoved(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, > + virNetClientPtr client ATTRIBUTE_UNUSED, > + void *evdata, void *opaque) > +{ > + virConnectPtr conn = opaque; > + struct private_data *priv = conn->privateData; > + remote_domain_event_tray_moved_msg *msg = evdata; > + virDomainPtr dom; > + virDomainEventPtr event = NULL; > + > + dom = get_nonnull_domain(conn, msg->dom); > + if (!dom) > + return; > + > + event = virDomainEventTrayMovedNewFromDom(dom, > + msg->devAlias, > + msg->trayOpened); > + > + 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 4d845e7..73e554c 100644 > --- a/src/remote/remote_protocol.x > +++ b/src/remote/remote_protocol.x > @@ -2178,6 +2178,12 @@ struct remote_domain_event_disk_change_msg { > int reason; > }; > > +struct remote_domain_event_tray_moved_msg { > + remote_nonnull_domain dom; > + remote_nonnull_string devAlias; > + unsigned int trayOpened; > +}; > + > struct remote_domain_managed_save_args { > remote_nonnull_domain dom; > unsigned int flags; > @@ -2765,7 +2771,8 @@ enum remote_procedure { > REMOTE_PROC_DOMAIN_SET_METADATA = 264, /* autogen autogen */ > REMOTE_PROC_DOMAIN_GET_METADATA = 265, /* autogen autogen */ > REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266, /* autogen autogen */ > - REMOTE_PROC_DOMAIN_PM_WAKEUP = 267 /* autogen autogen */ > + REMOTE_PROC_DOMAIN_PM_WAKEUP = 267, /* autogen autogen */ > + REMOTE_PROC_DOMAIN_EVENT_TRAY_MOVED = 268 /* autogen autogen */ And I would name the event "TRAY_CHANGED" Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list