
This patch modifies the Mock model functions to allow user to create a SCSI FC pool in test environment. Then implements functions to test API and rest. Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 55 +++++++++++++++++++++++++++++++++++++---- tests/test_rest.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test_storagepool.py | 21 ++++++++++++++++ 3 files changed, 133 insertions(+), 5 deletions(-) diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index f0f96eb..98715af 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -156,7 +156,16 @@ class MockModel(object): if icon: vm.info['icon'] = icon - vm.disk_paths = t.fork_vm_storage(vm_uuid) + pool = t._storage_validate() + if pool.info['type'] == 'scsi': + vm.disk_paths = [] + if not params.get('volumes'): + raise MissingParameter("Volume list (LUNs names) not given.") + for vol in params['volumes']: + vm.disk_paths.append({'pool': pool.name, + 'volume': vol}) + else: + vm.disk_paths = t.fork_vm_storage(vm_uuid) self._mock_vms[name] = vm return name @@ -302,8 +311,19 @@ class MockModel(object): name = params['name'] pool = MockStoragePool(name) pool.info['type'] = params['type'] - pool.info['path'] = params['path'] - if params['type'] == 'dir': + if params['type'] == 'scsi': + pool.info['path'] = '/dev/disk/by-path' + pool.info['source'] = params['source'] + if not pool.info['source'].get('adapter_name'): + raise MissingParameter('adapter_name') + for vol in ['unit:0:0:1','unit:0:0:2', + 'unit:0:0:3','unit:0:0:4']: + mockvol = MockStorageVolume(name, vol, + dict([('type','lun')])) + pool._volumes[vol] = mockvol + else: + pool.info['path'] = params['path'] + if params['type'] in ['dir','scsi']: pool.info['autostart'] = True else: pool.info['autostart'] = False @@ -405,6 +425,16 @@ class MockModel(object): raise InvalidOperation("KCHVOL0006E", {'pool': pool}) return res._volumes.keys() + def devices_get_list(self, _cap=None): + return ['scsi_host3', 'scsi_host4','scsi_host5'] + + def device_lookup(self, nodedev_name): + return { + 'name': nodedev_name, + 'adapter_type': 'fc_host', + 'wwnn': uuid.uuid4().hex[:16], + 'wwpn': uuid.uuid4().hex[:16]} + def isopool_lookup(self, name): return {'state': 'active', 'type': 'kimchi-iso'} @@ -873,11 +903,15 @@ class MockStorageVolume(object): def __init__(self, pool, name, params={}): self.name = name self.pool = pool + # Check if volume should be scsi lun + if params.get('type') == 'lun': + params = self._def_lun(name) fmt = params.get('format', 'raw') capacity = params.get('capacity', 1024) - self.info = {'type': 'disk', + self.info = {'type': params.get('type','disk'), 'capacity': capacity << 20, - 'allocation': 512, + 'allocation': params.get('allocation','512'), + 'path': params.get('path'), 'format': fmt} if fmt == 'iso': self.info['allocation'] = self.info['capacity'] @@ -885,6 +919,17 @@ class MockStorageVolume(object): self.info['os_distro'] = 'fedora' self.info['bootable'] = True + def _def_lun(self, name): + capacity = int(random.uniform(100, 300)) << 20 + path = "/dev/disk/by-path/pci-0000:0e:00.0-fc-0x20999980e52e4492-lun" + return { + "capacity": capacity, + "name": name, + "format": random.choice(['dos','unknown']), + "allocation": capacity, + "path": path + name[-1], + "type": "block" } + class MockVMScreenshot(VMScreenshot): OUTDATED_SECS = 5 diff --git a/tests/test_rest.py b/tests/test_rest.py index cd3a462..ce3e471 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -24,6 +24,7 @@ import base64 import json import os +import random import time import unittest @@ -145,6 +146,18 @@ class RestTests(unittest.TestCase): h = {'Accept': 'text/plain'} self.assertHTTPStatus(406, "/", None, 'GET', h) + def test_host_devices(self): + nodedevs = json.loads(self.request('/host/devices').read()) + # Mockmodel brings 3 preconfigured scsi fc_host + self.assertEquals(3, len(nodedevs)) + + nodedev = json.loads(self.request('/host/devices/scsi_host4').read()) + # Mockmodel generates random wwpn and wwnn + self.assertEquals('scsi_host4', nodedev['name']) + self.assertEquals('fc_host', nodedev['adapter_type']) + self.assertEquals(16, len(nodedev['wwpn'])) + self.assertEquals(16, len(nodedev['wwnn'])) + def test_get_vms(self): vms = json.loads(self.request('/vms').read()) self.assertEquals(0, len(vms)) @@ -514,6 +527,55 @@ class RestTests(unittest.TestCase): # Verify the volume was deleted self.assertHTTPStatus(404, vol_uri) + def test_scsi_fc_storage(self): + # Create scsi fc pool + req = json.dumps({'name': 'scsi_fc_pool', + 'type': 'scsi', + 'source': {'adapter_name': 'scsi_host3'}}) + resp = self.request('/storagepools', req, 'POST') + self.assertEquals(201, resp.status) + + # Create template with this pool + req = json.dumps({'name': 'test_fc_pool', 'cdrom': '/nonexistent.iso', + 'storagepool': '/storagepools/scsi_fc_pool'}) + resp = self.request('/templates', req, 'POST') + self.assertEquals(201, resp.status) + + # Test create vms using lun of this pool + ### activate the storage pool + resp = self.request('/storagepools/scsi_fc_pool/activate', '{}', 'POST') + + ### Get scsi pool luns and choose one + resp = self.request('/storagepools/scsi_fc_pool/storagevolumes') + luns = json.loads(resp.read()) + lun_name = random.choice(luns).get('name') + + ### Create vm in scsi pool without volumes: Error + req = json.dumps({'template': '/templates/test_fc_pool'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(400, resp.status) + + ### Create vm in scsi pool + req = json.dumps({'name': 'test-vm', + 'template': '/templates/test_fc_pool', + 'volumes': [lun_name]}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + + # Start the VM + resp = self.request('/vms/test-vm/start', '{}', 'POST') + vm = json.loads(self.request('/vms/test-vm').read()) + self.assertEquals('running', vm['state']) + + # Force stop the VM + resp = self.request('/vms/test-vm/stop', '{}', 'POST') + vm = json.loads(self.request('/vms/test-vm').read()) + self.assertEquals('shutoff', vm['state']) + + # Delete the VM + resp = self.request('/vms/test-vm', '{}', 'DELETE') + self.assertEquals(204, resp.status) + def test_template_customise_storage(self): req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso', 'disks': [{'size': 1}]}) diff --git a/tests/test_storagepool.py b/tests/test_storagepool.py index a3f4983..700c66e 100644 --- a/tests/test_storagepool.py +++ b/tests/test_storagepool.py @@ -141,6 +141,27 @@ class storagepoolTests(unittest.TestCase): <path>/dev/disk/by-id</path> </target> </pool> + """}, + {'def': + {'type': 'scsi', + 'name': 'unitTestSCSIFCPool', + 'path': '/dev/disk/by-path', + 'source': { + 'name': 'scsi_host3', + 'adapter_type': 'fc_host', + 'wwpn': '0123456789abcdef', + 'wwnn': 'abcdef0123456789' }}, + 'xml': + """ + <pool type='scsi'> + <name>unitTestSCSIFCPool</name> + <source> + <adapter type='fc_host' name='scsi_host3' wwnn='abcdef0123456789' wwpn='0123456789abcdef'></adapter> + </source> + <target> + <path>/dev/disk/by-path</path> + </target> + </pool> """}] for poolDef in poolDefs: -- 1.8.5.3