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

Rodrigo Trujillo rodrigo.trujillo at linux.vnet.ibm.com
Wed Feb 12 06:25:28 UTC 2014


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 e1828ee..8b85fb7 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -155,7 +155,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
 
@@ -298,8 +307,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
@@ -410,6 +430,16 @@ class MockModel(object):
                 "Unable to list volumes of inactive storagepool %s" % 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'}
@@ -872,11 +902,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']
@@ -884,6 +918,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 dc6ed44..12896c1 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




More information about the Kimchi-devel mailing list