[libvirt] [PATCH 01/12] Add VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event

Jiri Denemark jdenemar at redhat.com
Mon Jul 15 17:11:02 UTC 2013


---
 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 b87255a..bd7417f 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4851,6 +4851,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:
@@ -4877,6 +4894,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 0ab7632..49f07c1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -405,6 +405,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 81ecef1..b4bb926 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 2e9dc1d..d42e5af 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2808,6 +2808,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. */
@@ -4944,6 +4949,12 @@ enum remote_procedure {
      * @generate: none
      * @acl: domain:migrate
      */
-    REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307
+    REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 308
 
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index e38d24a..8d064fe 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2293,6 +2293,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,
@@ -2601,4 +2605,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3_PARAMS = 305,
         REMOTE_PROC_DOMAIN_MIGRATE_FINISH3_PARAMS = 306,
         REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS = 307,
+        REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 308,
 };
-- 
1.8.3.2




More information about the libvir-list mailing list