]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add support for event tray moved of removable disks
authorOsier Yang <jyang@redhat.com>
Fri, 23 Mar 2012 13:44:50 +0000 (21:44 +0800)
committerOsier Yang <jyang@redhat.com>
Fri, 23 Mar 2012 15:10:26 +0000 (23:10 +0800)
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_CHANGE

The event's data includes the device alias and the reason
for tray status' changing, which indicates why the tray
status was changed. Thus the callback definition for the event
is:

enum {
    VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN = 0,
    VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE,

\#ifdef VIR_ENUM_SENTINELS
    VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST
\#endif
} virDomainEventTrayChangeReason;

typedef void
(*virConnectDomainEventTrayChangeCallback)(virConnectPtr conn,
                                           virDomainPtr dom,
                                           const char *devAlias,
                                           int reason,
                                           void *opaque);

16 files changed:
daemon/remote.c
examples/domain-events/events-c/event-test.c
examples/domain-events/events-python/event-test.py
include/libvirt/libvirt.h.in
python/libvirt-override-virConnect.py
python/libvirt-override.c
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_process.c
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs

index 0dd4f2e35410b43426d85dd53917d22c06d6db8e..060f77b2a542d97b074545abe3d0ce02d713a702 100644 (file)
@@ -506,6 +506,38 @@ mem_error:
 }
 
 
+static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                            virDomainPtr dom,
+                                            const char *devAlias,
+                                            int reason,
+                                            void *opaque) {
+    virNetServerClientPtr client = opaque;
+    remote_domain_event_tray_change_msg data;
+
+    if (!client)
+        return -1;
+
+    VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d",
+              dom->name, dom->id, devAlias, reason);
+
+    /* build return data */
+    memset(&data, 0, sizeof data);
+
+    if (!(data.devAlias = strdup(devAlias))) {
+        virReportOOMError();
+        return -1;
+    }
+    data.reason = reason;
+
+    make_nonnull_domain(&data.dom, dom);
+
+    remoteDispatchDomainEventSend(client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE,
+                                  (xdrproc_t)xdr_remote_domain_event_tray_change_msg, &data);
+
+    return 0;
+}
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -517,6 +549,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventControlError),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDiskChange),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTrayChange),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
index f4938c438d0f8bb0c7ab0eb6d65e452727124ed5..cca9a1a358cd0f001d436118024d4f65d942d61c 100644 (file)
@@ -313,6 +313,22 @@ static int myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
     return 0;
 }
 
+const char *trayChangeReasonStrings[] = {
+    "open",
+    "close",
+};
+
+static int myDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                           virDomainPtr dom,
+                                           const char *devAlias,
+                                           int reason,
+                                           void *opaque ATTRIBUTE_UNUSED)
+{
+    printf("%s EVENT: Domain %s(%d) removable disk's tray change devAlias: %s reason: %s\n",
+           __func__, virDomainGetName(dom), virDomainGetID(dom),
+           devAlias, trayChangeReasonStrings[reason]);
+    return 0;
+}
 
 static void myFreeFunc(void *opaque)
 {
@@ -349,6 +365,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 +436,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_CHANGE,
+                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventTrayChangeCallback),
+                                                     strdup("tray change"), myFreeFunc);
 
     if ((callback1ret != -1) &&
         (callback2ret != -1) &&
@@ -427,7 +449,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 +475,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);
     }
index 0c750914e9babdc0242a3a0582c9208b5690b400..6e0409d564c3be02b246421aa61f306be74f147a 100644 (file)
@@ -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 myDomainEventTrayChangeCallback(conn, dom, devAlias, reason, opaque):
+    print "myDomainEventTrayChangeCallback: Domain %s(%s) tray change devAlias: %s reason: %s" % (
+            dom.name(), dom.ID(), devAlias, reason)
 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_CHANGE, myDomainEventTrayChangeCallback, None)
 
     vc.setKeepAlive(5, 3)
 
index 7d41642e2c665a5e9836e4f53feecc7866e8da6d..7bf1004cfc589e5722430faea1b0582574ba4c8e 100644 (file)
@@ -3667,6 +3667,40 @@ typedef void (*virConnectDomainEventDiskChangeCallback)(virConnectPtr conn,
                                                        int reason,
                                                        void *opaque);
 
+/**
+ * virConnectDomainEventTrayChangeReason:
+ *
+ * The reason describing why the callback was called
+ */
+enum {
+    VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN = 0,
+    VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE,
+
+#ifdef VIR_ENUM_SENTINELS
+    VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST
+#endif
+} virDomainEventTrayChangeReason;
+
+/**
+ * virConnectDomainEventTrayChangeCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @devAlias: device alias
+ * @reason: why the tray status was changed?
+ * @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_CHANGE with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventTrayChangeCallback)(virConnectPtr conn,
+                                                        virDomainPtr dom,
+                                                        const char *devAlias,
+                                                        int reason,
+                                                        void *opaque);
+
+
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
  *
@@ -3687,6 +3721,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_CHANGE = 10,    /* virConnectDomainEventTrayChangeCallback */
 
 #ifdef VIR_ENUM_SENTINELS
     /*
index b908b32dfb28ee900d81b17ef7566d03942f416c..82c24371925bdde8385543a202c95027db315092 100644 (file)
         cb(self, virDomain(self, _obj=dom), oldSrcPath, newSrcPath, devAlias, reason, opaque)
         return 0;
 
+    def _dispatchDomainEventTrayChangeCallback(self, dom, devAlias, reason, cbData):
+        """Dispatches event to python user domain trayChange event callbacks
+        """
+        cb = cbData["cb"]
+        opaque = cbData["opaque"]
+
+        cb(self, virDomain(self, _obj=dom), devAlias, reason, 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 """
index 129f29c7b69d6792aad7128ae95e8554d5c5d5de..42a441e39a4102d45017d4dd41f54aaaeace90b6 100644 (file)
@@ -5105,6 +5105,53 @@ libvirt_virConnectDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNU
     return ret;
 }
 
+static int
+libvirt_virConnectDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                                virDomainPtr dom,
+                                                const char *devAlias,
+                                                int reason,
+                                                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*)"_dispatchDomainEventTrayChangeCallback",
+                                    (char*)"OsiO",
+                                    pyobj_dom,
+                                    devAlias, reason, 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)
@@ -5165,6 +5212,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_CHANGE:
+        cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventTrayChangeCallback);
+        break;
     }
 
     if (!cb) {
index 1d8b45deb7838153793ea1bd993a1b607b79342d..9c2a0520ba7dc132350ebdb1ddeddb37d9e1b3ea 100644 (file)
@@ -117,6 +117,10 @@ struct _virDomainEvent {
             char *devAlias;
             int reason;
         } diskChange;
+        struct {
+            char *devAlias;
+            int reason;
+        } trayChange;
     } 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_CHANGE:
+        VIR_FREE(event->data.trayChange.devAlias);
+        break;
     }
 
     VIR_FREE(event->dom.name);
@@ -1043,6 +1050,50 @@ virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
                                        devAlias, reason);
 }
 
+static virDomainEventPtr
+virDomainEventTrayChangeNew(int id, const char *name,
+                            unsigned char *uuid,
+                            const char *devAlias,
+                            int reason)
+{
+    virDomainEventPtr ev =
+        virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
+                                  id, name, uuid);
+
+    if (ev) {
+        if (!(ev->data.trayChange.devAlias = strdup(devAlias)))
+            goto error;
+
+        ev->data.trayChange.reason = reason;
+    }
+
+    return ev;
+
+error:
+    virReportOOMError();
+    virDomainEventFree(ev);
+    return NULL;
+}
+
+virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj,
+                                                     const char *devAlias,
+                                                     int reason)
+{
+    return virDomainEventTrayChangeNew(obj->def->id,
+                                       obj->def->name,
+                                       obj->def->uuid,
+                                       devAlias,
+                                       reason);
+}
+
+virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom,
+                                                     const char *devAlias,
+                                                     int reason)
+{
+    return virDomainEventTrayChangeNew(dom->id, dom->name, dom->uuid,
+                                       devAlias, reason);
+}
+
 
 /**
  * virDomainEventQueuePush:
@@ -1167,6 +1218,13 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                                       cbopaque);
         break;
 
+    case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
+        ((virConnectDomainEventTrayChangeCallback)cb)(conn, dom,
+                                                      event->data.trayChange.devAlias,
+                                                      event->data.trayChange.reason,
+                                                      cbopaque);
+        break;
+
     default:
         VIR_WARN("Unexpected event ID %d", event->eventID);
         break;
index 0e7cd75c31c522aa997774dae81776fdb5f41395..e5010a35c2263f735c3157995146f3f6ea80a93d 100644 (file)
@@ -114,6 +114,12 @@ virDomainEventPtr virDomainEventDiskChangeNewFromDom(virDomainPtr dom,
                                                      const char *newSrcPath,
                                                      const char *devAlias,
                                                      int reason);
+virDomainEventPtr virDomainEventTrayChangeNewFromObj(virDomainObjPtr obj,
+                                                     const char *devAlias,
+                                                     int reason);
+virDomainEventPtr virDomainEventTrayChangeNewFromDom(virDomainPtr dom,
+                                                     const char *devAlias,
+                                                     int reason);
 
 void virDomainEventFree(virDomainEventPtr event);
 
index 57c2c134a2dab9d909df091ea45c536acf38c8f0..b08a916cebfb69fb616eccfb08bbe7c34fc9a109 100644 (file)
@@ -522,6 +522,8 @@ virDomainEventStateRegisterID;
 virDomainEventStateFree;
 virDomainEventStateNew;
 virDomainEventStateQueue;
+virDomainEventTrayChangeNewFromDom;
+virDomainEventTrayChangeNewFromObj;
 virDomainEventWatchdogNewFromDom;
 virDomainEventWatchdogNewFromObj;
 
index 78eb492e15e8d150b45134a0e10e825a586a80e7..90b8e129288eaa950689842cece8e00682d755bc 100644 (file)
@@ -1040,6 +1040,19 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
     return ret;
 }
 
+int qemuMonitorEmitTrayChange(qemuMonitorPtr mon,
+                              const char *devAlias,
+                              int reason)
+{
+    int ret = -1;
+    VIR_DEBUG("mon=%p", mon);
+
+    QEMU_MONITOR_CALLBACK(mon, ret, domainTrayChange, mon->vm,
+                          devAlias, reason);
+
+    return ret;
+}
+
 int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
                             const char *diskAlias,
                             int type,
index 654d9bd6bab02922f6afca1397860b41d3941e2f..b5a0c302cd4b3fbf33bee61ac56c55c6af0bec3b 100644 (file)
@@ -124,9 +124,12 @@ struct _qemuMonitorCallbacks {
                           const char *diskAlias,
                           int type,
                           int status);
+    int (*domainTrayChange)(qemuMonitorPtr mon,
+                            virDomainObjPtr vm,
+                            const char *devAlias,
+                            int reason);
 };
 
-
 char *qemuMonitorEscapeArg(const char *in);
 char *qemuMonitorUnescapeArg(const char *in);
 
@@ -191,13 +194,14 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
                             const char *authScheme,
                             const char *x509dname,
                             const char *saslUsername);
+int qemuMonitorEmitTrayChange(qemuMonitorPtr mon,
+                              const char *devAlias,
+                              int reason);
 int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
                             const char *diskAlias,
                             int type,
                             int status);
 
-
-
 int qemuMonitorStartCPUs(qemuMonitorPtr mon,
                          virConnectPtr conn);
 int qemuMonitorStopCPUs(qemuMonitorPtr mon);
index ce68e69f5f8476b0971ee3d82a2d1168b53cb07d..fe9c9b91f055127deeea721507ab4fa7ad967f2e 100644 (file)
@@ -62,6 +62,7 @@ static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr da
 static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data);
 static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
 static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, virJSONValuePtr data);
 
 static struct {
     const char *type;
@@ -81,6 +82,7 @@ static struct {
     { "SPICE_CONNECTED", qemuMonitorJSONHandleSPICEConnect, },
     { "SPICE_INITIALIZED", qemuMonitorJSONHandleSPICEInitialize, },
     { "SPICE_DISCONNECTED", qemuMonitorJSONHandleSPICEDisconnect, },
+    { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
 };
 
 
@@ -773,6 +775,31 @@ out:
     qemuMonitorEmitBlockJob(mon, device, type, status);
 }
 
+static void
+qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon,
+                                virJSONValuePtr data)
+{
+    const char *devAlias = NULL;
+    bool trayOpened;
+    int reason;
+
+    if ((devAlias = virJSONValueObjectGetString(data, "device")) == NULL) {
+        VIR_WARN("missing device in tray change event");
+        return;
+    }
+
+    if (virJSONValueObjectGetBoolean(data, "tray-open", &trayOpened) < 0) {
+        VIR_WARN("missing tray-open in tray change event");
+        return;
+    }
+
+    if (trayOpened)
+        reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN;
+    else
+        reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE;
+
+    qemuMonitorEmitTrayChange(mon, devAlias, reason);
+}
 
 int
 qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
index 8915a9a8b62c78289184a3feea16f65a1835f3a3..3c785ce055a276e8088be2309dd28ed6881ef8eb 100644 (file)
@@ -1021,6 +1021,37 @@ static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon,
         virDomainObjUnlock(vm);
 }
 
+static int
+qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                            virDomainObjPtr vm,
+                            const char *devAlias,
+                            int reason)
+{
+    struct qemud_driver *driver = qemu_driver;
+    virDomainEventPtr event = NULL;
+    virDomainDiskDefPtr disk;
+
+    virDomainObjLock(vm);
+    disk = qemuProcessFindDomainDiskByAlias(vm, devAlias);
+
+    if (disk) {
+        event = virDomainEventTrayChangeNewFromObj(vm,
+                                                   devAlias,
+                                                   reason);
+    }
+
+    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,
+    .domainTrayChange = qemuProcessHandleTrayChange,
 };
 
 static int
index 72b4b8fa37bd70060bcc0ef177d2ae723d05c140..f11e957f577d5696e850737c5848b396ba2ca83a 100644 (file)
@@ -239,6 +239,11 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog,
                                  virNetClientPtr client,
                                  void *evdata, void *opaque);
 
+static void
+remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog,
+                                 virNetClientPtr client,
+                                 void *evdata, void *opaque);
+
 static virNetClientProgramEvent remoteDomainEvents[] = {
     { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
       remoteDomainBuildEventRTCChange,
@@ -280,6 +285,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_CHANGE,
+      remoteDomainBuildEventTrayChange,
+      sizeof(remote_domain_event_tray_change_msg),
+      (xdrproc_t)xdr_remote_domain_event_tray_change_msg },
 };
 
 enum virDrvOpenRemoteFlags {
@@ -3731,6 +3740,31 @@ remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 }
 
 
+static void
+remoteDomainBuildEventTrayChange(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_change_msg *msg = evdata;
+    virDomainPtr dom;
+    virDomainEventPtr event = NULL;
+
+    dom = get_nonnull_domain(conn, msg->dom);
+    if (!dom)
+        return;
+
+    event = virDomainEventTrayChangeNewFromDom(dom,
+                                               msg->devAlias,
+                                               msg->reason);
+
+    virDomainFree(dom);
+
+    remoteDomainEventQueue(priv, event);
+}
+
+
 static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
                  unsigned int flags)
index 4d845e74b82339e4477177809c810ade3e3b9b92..6c8c4978ea7ffdb14e2bddbb0604683df731e0d5 100644 (file)
@@ -2178,6 +2178,12 @@ struct remote_domain_event_disk_change_msg {
     int reason;
 };
 
+struct remote_domain_event_tray_change_msg {
+    remote_nonnull_domain dom;
+    remote_nonnull_string devAlias;
+    int reason;
+};
+
 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_CHANGE = 268 /* autogen autogen */
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
index 8f882b74bd4a35787d52063453812e779f224942..0ce7c1c68df4f81fcb5fd965d2aff2870333ca97 100644 (file)
@@ -1650,6 +1650,11 @@ struct remote_domain_event_disk_change_msg {
         remote_nonnull_string      devAlias;
         int                        reason;
 };
+struct remote_domain_event_tray_change_msg {
+        remote_nonnull_domain      dom;
+        remote_nonnull_string      devAlias;
+        int                        reason;
+}
 struct remote_domain_managed_save_args {
         remote_nonnull_domain      dom;
         u_int                      flags;
@@ -2178,4 +2183,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_GET_METADATA = 265,
         REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266,
         REMOTE_PROC_DOMAIN_PM_WAKEUP = 267,
+        REMOTE_PROC_DOMAIN_TRAY_CHANGE = 268,
 };