[Kimchi-devel] [PATCH v6 (BACKEND) 4/5] Storagepool SCSI/FC: Modifies mockmodel and implements tests for FC pool

Aline Manera alinefm at linux.vnet.ibm.com
Thu Feb 13 22:24:22 UTC 2014


On 02/13/2014 04:33 PM, Rodrigo Trujillo wrote:
> 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 at 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.")

Here too.

> +            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')

And here

> +                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:




More information about the Kimchi-devel mailing list