[Kimchi-devel] [PATCH V4 5/5] Storagepool SCSI/FC: Modifies mockmodel and implements tests for FC pool

Rodrigo Trujillo rodrigo.trujillo at linux.vnet.ibm.com
Wed Feb 12 01:08:57 UTC 2014


On 02/10/2014 12:32 PM, Aline Manera wrote:
> On 02/05/2014 12:18 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   | 53 
>> +++++++++++++++++++++++++++++++++++++++++------
>>   tests/test_rest.py        | 47 
>> +++++++++++++++++++++++++++++++++++++++++
>>   tests/test_storagepool.py | 21 +++++++++++++++++++
>>   3 files changed, 115 insertions(+), 6 deletions(-)
>>
>> diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
>> index 4e276eb..f6400a4 100644
>> --- a/src/kimchi/mockmodel.py
>> +++ b/src/kimchi/mockmodel.py
>> @@ -66,7 +66,8 @@ class MockModel(object):
>>           return {'libvirt_stream_protocols': ['http', 'https', 
>> 'ftp', 'ftps', 'tftp'],
>>                   'qemu_stream': True,
>>                   'screenshot': True,
>> -                'system_report_tool': True}
>> +                'system_report_tool': True,
>
>> +                'fc_host_support': True}
>
> As I said before you don't need to expose it as it is a backend 
> information
>
>>       def reset(self):
>>           self._mock_vms = {}
>> @@ -155,7 +156,15 @@ 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 InvalidOperation("Volume list (LUNs names) not 
>> given.")
>
> It would be MissingParameter() error
>
>> +            for vol in params['volumes']:
>> + vm.disk_paths.append(pool._volumes[vol].info['path'])
>> +        else:
>> +            vm.disk_paths = t.fork_vm_storage(vm_uuid)
>>           self._mock_vms[name] = vm
>>           return name
>>
>> @@ -298,8 +307,18 @@ 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 KeyError('adapter_name')
>
> raise MissingParameter()
ok
>
>> +                for vol in ['unit:0:0:1','unit:0:0:2',
>> +                            'unit:0:0:3','unit:0:0:4']:
>> +                    mockvol = MockStorageVolume(vol, name, 
>> self._def_lun(vol))
>> +                    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
>> @@ -388,6 +407,27 @@ class MockModel(object):
>>                   "Unable to list volumes of inactive storagepool %s" 
>> % pool)
>>           return res._volumes.keys()
>
>> +    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" }
>
> This function should be in MockStorageVolume() class
> and while creating a new volume MockStorageVolume() it knows what to do
>
ack
>> +
>> +    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'}
>> @@ -789,9 +829,10 @@ class MockStorageVolume(object):
>>           self.pool = pool
>>           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']
>> diff --git a/tests/test_rest.py b/tests/test_rest.py
>> index 0ed293b..8b033ae 100644
>> --- a/tests/test_rest.py
>> +++ b/tests/test_rest.py
>> @@ -23,6 +23,7 @@
>>   import base64
>>   import json
>>   import os
>> +import random
>>   import time
>>   import unittest
>>
>> @@ -144,6 +145,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))
>> @@ -440,6 +453,40 @@ 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({'template': '/templates/test_fc_pool',
>> +                          'volumes': [lun_name]})
>> +        resp = self.request('/vms', req, 'POST')
>> +        self.assertEquals(201, resp.status)
>> +
>
>
> Please, add test to start/stop and delete the created VM
done
>
>>       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:
>
> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>




More information about the Kimchi-devel mailing list