[Kimchi-devel] [PATCH] [Kimchi] Handle libvirt events for device attachment/detachment

Jose Ricardo Ziviani joserz at linux.vnet.ibm.com
Mon Jul 11 19:31:25 UTC 2016


 - kimchi will only finish the device attachment/detachment after
   receiving the appropriate event from libvirt.

Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
---
 model/libvirtevents.py | 48 ++++++++++++++++++++++++++++++++++++++++
 model/vmhostdevs.py    | 60 +++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 98 insertions(+), 10 deletions(-)

diff --git a/model/libvirtevents.py b/model/libvirtevents.py
index dfd22c6..0f3bfd5 100644
--- a/model/libvirtevents.py
+++ b/model/libvirtevents.py
@@ -89,3 +89,51 @@ class LibvirtEvents(object):
             else:
                 reason = e.message
             wok_log.error("Register of ENOSPC event failed: %s" % reason)
+
+    def registerAttachDevicesEvent(self, conn, cb, arg):
+        """
+        register libvirt event to listen to devices attachment
+        """
+        try:
+            return conn.get().domainEventRegisterAny(
+                None,
+                libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_ADDED,
+                cb,
+                arg)
+
+        except libvirt.libvirtError as e:
+            wok_log.error("register attach event failed: %s" % e.message)
+
+    def registerDetachDevicesEvent(self, conn, cb, arg):
+        """
+        register libvirt event to listen to devices detachment
+        """
+        try:
+            return conn.get().domainEventRegisterAny(
+                None,
+                libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED,
+                cb,
+                arg)
+
+        except libvirt.libvirtError as e:
+            wok_log.error("register detach event failed: %s" % e.message)
+
+    def deregisterAttachDevicesEvent(self, conn, id):
+        """
+        deregister libvirt event to listen to devices attachment
+        """
+        try:
+            conn.get().domainEventDeregisterAny(id)
+
+        except libvirt.libvirtError as e:
+            wok_log.error("deregister attach event failed: %s" % e.message)
+
+    def deregisterDetachDevicesEvent(self, conn, id):
+        """
+        deregister libvirt event to listen to devices detachment
+        """
+        try:
+            conn.get().domainEventDeregisterAny(id)
+
+        except libvirt.libvirtError as e:
+            wok_log.error("deregister detach event failed: %s" % e.message)
diff --git a/model/vmhostdevs.py b/model/vmhostdevs.py
index 2130ac4..676e40a 100644
--- a/model/vmhostdevs.py
+++ b/model/vmhostdevs.py
@@ -47,8 +47,10 @@ class VMHostDevsModel(object):
     def __init__(self, **kargs):
         self.conn = kargs['conn']
         self.objstore = kargs['objstore']
+        self.events = kargs['eventsloop']
         self.caps = CapabilitiesModel(**kargs)
         self.task = TaskModel(**kargs)
+        self._eid = None
 
     def get_list(self, vmid):
         dom = VMModel.get_vm(vmid, self.conn)
@@ -67,6 +69,17 @@ class VMHostDevsModel(object):
         if dev_name not in eligible_dev_names:
             raise InvalidParameter('KCHVMHDEV0002E', {'dev_name': dev_name})
 
+    def _event_devices(self, conn, dom, alias, opaque):
+        """
+        Callback to handle add/remove devices event
+        """
+        if self._eid is None:
+            wok_log.error("callbackID cannot be None")
+            return
+
+        wok_log.info("Device %s added successfuly" % alias)
+        opaque('OK', True)
+
     def create(self, vmid, params):
         dev_name = params['name']
         self._passthrough_device_validate(dev_name)
@@ -224,6 +237,12 @@ class VMHostDevsModel(object):
             raise InvalidOperation('KCHVMHDEV0006E',
                                    {'name': dev_info['name']})
 
+        if self._eid is None:
+            self._eid = self.events.registerAttachDevicesEvent(
+                self.conn,
+                self._event_devices,
+                cb)
+
         # all devices in the group that is going to be attached to the vm
         # must be detached from the host first
         with RollbackContext() as rollback:
@@ -273,7 +292,6 @@ class VMHostDevsModel(object):
                 rollback.prependDefer(dom.detachDeviceFlags, xmlstr,
                                       device_flags)
                 rollback.commitAll()
-                cb('OK', True)
                 return
 
             for pci_info in pci_infos:
@@ -294,8 +312,6 @@ class VMHostDevsModel(object):
                                       xmlstr, device_flags)
             rollback.commitAll()
 
-        cb('OK', True)
-
     def _count_3D_devices_attached(self, dom):
         counter = 0
         root = objectify.fromstring(dom.XMLDesc(0))
@@ -407,6 +423,12 @@ class VMHostDevsModel(object):
         dev_info = params['dev_info']
         dom = VMModel.get_vm(vmid, self.conn)
 
+        if self._eid is None:
+            self._eid = self.events.registerAttachDevicesEvent(
+                self.conn,
+                self._event_devices,
+                cb)
+
         with RollbackContext() as rollback:
             cb('Reading source device XML')
             xmlstr = self._get_scsi_device_xml(dev_info)
@@ -421,8 +443,6 @@ class VMHostDevsModel(object):
             rollback.prependDefer(dom.detachDeviceFlags, xmlstr, device_flags)
             rollback.commitAll()
 
-        cb('OK', True)
-
     def _get_usb_device_xml(self, dev_info):
         source = E.source(
             E.vendor(id=dev_info['vendor']['id']),
@@ -440,6 +460,12 @@ class VMHostDevsModel(object):
         dev_info = params['dev_info']
         dom = VMModel.get_vm(vmid, self.conn)
 
+        if self._eid is None:
+            self._eid = self.events.registerAttachDevicesEvent(
+                self.conn,
+                self._event_devices,
+                cb)
+
         with RollbackContext() as rollback:
             cb('Reading source device XML')
             xmlstr = self._get_usb_device_xml(dev_info)
@@ -454,14 +480,14 @@ class VMHostDevsModel(object):
             rollback.prependDefer(dom.detachDeviceFlags, xmlstr, device_flags)
             rollback.commitAll()
 
-        cb('OK', True)
-
 
 class VMHostDevModel(object):
     def __init__(self, **kargs):
         self.conn = kargs['conn']
         self.objstore = kargs['objstore']
+        self.events = kargs['eventsloop']
         self.task = TaskModel(**kargs)
+        self._eid = None
 
     def lookup(self, vmid, dev_name):
         dom = VMModel.get_vm(vmid, self.conn)
@@ -509,6 +535,17 @@ class VMHostDevModel(object):
                           task_params)
         return self.task.lookup(taskid)
 
+    def _event_devices(self, conn, dom, alias, opaque):
+        """
+        Callback to handle add/remove devices event
+        """
+        if self._eid is None:
+            wok_log.error("callbackID cannot be None")
+            return
+
+        wok_log.info("Device %s removed successfuly" % alias)
+        opaque('OK', True)
+
     def _detach_device(self, cb, params):
         cb('Detaching device.')
         vmid = params['vmid']
@@ -526,12 +563,17 @@ class VMHostDevModel(object):
             raise InvalidOperation('KCHVMHDEV0006E',
                                    {'name': dev_info['name']})
 
+        if self._eid is None:
+            self._eid = self.events.registerDetachDevicesEvent(
+                self.conn,
+                self._event_devices,
+                cb)
+
         if self._hotunplug_multifunction_pci(dom, hostdev, dev_name):
             if is_3D_device:
                 cb('Updating MMIO from VM...')
                 devsmodel = VMHostDevsModel(conn=self.conn)
                 devsmodel.update_mmio_guest(vmid, False)
-            cb('OK', True)
             return
 
         for e in hostdev:
@@ -552,8 +594,6 @@ class VMHostDevModel(object):
             raise NotFoundError('KCHVMHDEV0001E',
                                 {'vmid': vmid, 'dev_name': dev_name})
 
-        cb('OK', True)
-
     def _get_devices_same_addr(self, hostdev, domain, bus, slot):
         devices = []
         for device in hostdev:
-- 
2.7.4




More information about the Kimchi-devel mailing list