[Kimchi-devel] [PATCH] [Kimchi 3/4] Make attach device return an AsyncTask
pvital at linux.vnet.ibm.com
pvital at linux.vnet.ibm.com
Thu Apr 14 21:36:56 UTC 2016
From: Paulo Vital <pvital at linux.vnet.ibm.com>
Modified VMHostDevs class to be an AsyncCollection and return an AsyncTask when
creating a new resource (a.k.a. attach a device into a VM).
This patch is part of the solution for Kimchi Issue #817
Signed-off-by: Paulo Vital <pvital at linux.vnet.ibm.com>
---
control/vm/hostdevs.py | 4 +--
model/vmhostdevs.py | 79 +++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/control/vm/hostdevs.py b/control/vm/hostdevs.py
index 8a82db0..b0c4d1d 100644
--- a/control/vm/hostdevs.py
+++ b/control/vm/hostdevs.py
@@ -17,7 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-from wok.control.base import Collection, Resource
+from wok.control.base import AsyncCollection, Resource
from wok.control.utils import UrlSubNode
@@ -33,7 +33,7 @@ VMHOSTDEV_REQUESTS = {
@UrlSubNode("hostdevs")
-class VMHostDevs(Collection):
+class VMHostDevs(AsyncCollection):
def __init__(self, model, vmid):
super(VMHostDevs, self).__init__(model)
self.resource = VMHostDev
diff --git a/model/vmhostdevs.py b/model/vmhostdevs.py
index 9d1d702..0cdf032 100644
--- a/model/vmhostdevs.py
+++ b/model/vmhostdevs.py
@@ -27,8 +27,9 @@ from operator import itemgetter
from wok.exception import InvalidOperation, InvalidParameter, NotFoundError
from wok.exception import OperationFailed
+from wok.model.tasks import TaskModel
from wok.rollbackcontext import RollbackContext
-from wok.utils import run_command, wok_log
+from wok.utils import add_task, run_command, wok_log
from wok.plugins.kimchi.model.config import CapabilitiesModel
from wok.plugins.kimchi.model.host import DeviceModel, DevicesModel
@@ -46,7 +47,9 @@ class VMHostDevsModel(object):
def __init__(self, **kargs):
self.conn = kargs['conn']
self.events = kargs['eventsloop']
+ self.objstore = kargs['objstore']
self.caps = CapabilitiesModel(**kargs)
+ self.task = TaskModel(**kargs)
self._register_device_event()
def get_list(self, vmid):
@@ -72,7 +75,11 @@ class VMHostDevsModel(object):
dev_info = DeviceModel(conn=self.conn).lookup(dev_name)
if dev_info['device_type'] == 'pci':
- return self._attach_pci_device(vmid, dev_info)
+ taskid = add_task(u'/plugins/kimchi/vms/%s/hostdevs/' %
+ VMModel.get_vm(vmid, self.conn).name(),
+ self._attach_pci_device, self.objstore,
+ {'vmid': vmid, 'dev_info': dev_info})
+ return self.task.lookup(taskid)
with RollbackContext() as rollback:
try:
@@ -83,13 +90,14 @@ class VMHostDevsModel(object):
else:
rollback.prependDefer(dev.reAttach)
- attach_device = getattr(
- self, '_attach_%s_device' % dev_info['device_type'])
-
- info = attach_device(vmid, dev_info)
rollback.commitAll()
- return info
+ taskid = add_task(u'/plugins/kimchi/vms/%s/hostdevs/' %
+ VMModel.get_vm(vmid, self.conn).name(),
+ '_attach_%s_device' % dev_info['device_type'],
+ self.objstore, {'vmid': vmid, 'dev_info': dev_info})
+
+ return self.task.lookup(taskid)
def _get_pci_device_xml(self, dev_info, slot, is_multifunction):
if 'detach_driver' not in dev_info:
@@ -164,7 +172,10 @@ class VMHostDevsModel(object):
return free+1
- def _attach_pci_device(self, vmid, dev_info):
+ def _attach_pci_device(self, cb, params):
+ cb('Attaching PCI device')
+ vmid = params['vmid']
+ dev_info = params['dev_info']
self._validate_pci_passthrough_env()
dom = VMModel.get_vm(vmid, self.conn)
@@ -229,10 +240,12 @@ class VMHostDevsModel(object):
with RollbackContext() as rollback:
for pci_info in pci_infos:
pci_info['detach_driver'] = driver
+ cb('Reading source device XML')
xmlstr = self._get_pci_device_xml(pci_info,
slot,
is_multifunction)
try:
+ cb('Attaching device to VM')
dom.attachDeviceFlags(xmlstr, device_flags)
except libvirt.libvirtError:
wok_log.error(
@@ -243,7 +256,7 @@ class VMHostDevsModel(object):
xmlstr, device_flags)
rollback.commitAll()
- return dev_info['name']
+ cb('OK', True)
def _count_3D_devices_attached(self, dom):
counter = 0
@@ -350,11 +363,27 @@ class VMHostDevsModel(object):
mode='subsystem', type='scsi', sgio='unfiltered')
return etree.tostring(host_dev)
- def _attach_scsi_device(self, vmid, dev_info):
- xmlstr = self._get_scsi_device_xml(dev_info)
+ def _attach_scsi_device(self, cb, params):
+ cb('Attaching SCSI device...')
+ vmid = params['vmid']
+ dev_info = params['dev_info']
dom = VMModel.get_vm(vmid, self.conn)
- dom.attachDeviceFlags(xmlstr, get_vm_config_flag(dom, mode='all'))
- return dev_info['name']
+
+ with RollbackContext() as rollback:
+ cb('Reading source device XML')
+ xmlstr = self._get_scsi_device_xml(dev_info)
+ device_flags = get_vm_config_flag(dom, mode='all')
+ try:
+ cb('Attaching device to VM')
+ dom.attachDeviceFlags(xmlstr, device_flags)
+ except libvirt.libvirtError:
+ wok_log.error('Failed to attach host device %s to VM %s: \n%s',
+ dev_info['name'], vmid, xmlstr)
+ raise
+ rollback.prependDefer(dom.detachDeviceFlags, xmlstr, device_flags)
+ rollback.commitAll()
+
+ cb('OK', True)
def _get_usb_device_xml(self, dev_info):
source = E.source(
@@ -367,11 +396,27 @@ class VMHostDevsModel(object):
ype='usb', managed='yes')
return etree.tostring(host_dev)
- def _attach_usb_device(self, vmid, dev_info):
- xmlstr = self._get_usb_device_xml(dev_info)
+ def _attach_usb_device(self, cb, params):
+ cb('Attaching USB device...')
+ vmid = params['vmid']
+ dev_info = params['dev_info']
dom = VMModel.get_vm(vmid, self.conn)
- dom.attachDeviceFlags(xmlstr, get_vm_config_flag(dom, mode='all'))
- return dev_info['name']
+
+ with RollbackContext() as rollback:
+ cb('Reading source device XML')
+ xmlstr = self._get_usb_device_xml(dev_info)
+ device_flags = get_vm_config_flag(dom, mode='all')
+ try:
+ cb('Attaching device to VM')
+ dom.attachDeviceFlags(xmlstr, device_flags)
+ except libvirt.libvirtError:
+ wok_log.error('Failed to attach host device %s to VM %s: \n%s',
+ dev_info['name'], vmid, xmlstr)
+ raise
+ rollback.prependDefer(dom.detachDeviceFlags, xmlstr, device_flags)
+ rollback.commitAll()
+
+ cb('OK', True)
def _vm_event_device_added_cb(self, conn, dom, dev, opaque):
"""
--
2.5.5
More information about the Kimchi-devel
mailing list