]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Dell SC driver has insufficient iscsi logging
authorTom Swanson <tom_swanson@dell.com>
Thu, 2 Apr 2015 22:55:44 +0000 (17:55 -0500)
committerTom Swanson <tom_swanson@dell.com>
Fri, 3 Apr 2015 15:33:04 +0000 (10:33 -0500)
In the case where a volume was mapped but the server could not
locate the volume not enough information was being logged to
sort out the failure. Added logging to Dell SC ISCSI driver.
Now returns much more connection information on trying to map
a volume. Also tries to return iscsi properties associated with
the controller on which the volume in question is active.

Updated tests.

Minor comment change.

Change-Id: I76bf501152802c5421be316703615fdc27a49072
Closes-Bug: 1439852

cinder/tests/test_dellsc.py
cinder/tests/test_dellscapi.py
cinder/volume/drivers/dell/dell_storagecenter_api.py
cinder/volume/drivers/dell/dell_storagecenter_common.py
cinder/volume/drivers/dell/dell_storagecenter_iscsi.py

index 9115d53f214dff3b8015c2bc10da7ed077aac582..19c60bb434193cc657da0a130f3c9936f8f7cd5c 100644 (file)
@@ -180,7 +180,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
     ISCSI_PROPERTIES = {'access_mode': 'rw',
                         'target_discovered': False,
                         'target_iqns':
-                            [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
+                        [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
                         'target_luns': [1],
                         'target_portals': [u'192.168.0.21:3260']}
 
@@ -343,7 +343,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=MAPPINGS[0])
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES)
+                       return_value=(0, ISCSI_PROPERTIES))
     def test_initialize_connection(self,
                                    mock_find_iscsi_props,
                                    mock_map_volume,
@@ -388,7 +388,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=MAPPINGS[0])
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES)
+                       return_value=(0, ISCSI_PROPERTIES))
     def test_initialize_connection_multi_path(self,
                                               mock_find_iscsi_props,
                                               mock_map_volume,
@@ -432,7 +432,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=MAPPINGS)
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES_EMPTY)
+                       return_value=(0, ISCSI_PROPERTIES_EMPTY))
     def test_initialize_connection_no_iqn(self,
                                           mock_find_iscsi_properties,
                                           mock_map_volume,
@@ -466,7 +466,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=MAPPINGS)
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES_EMPTY)
+                       return_value=(0, ISCSI_PROPERTIES_EMPTY))
     def test_initialize_connection_no_server(self,
                                              mock_find_iscsi_properties,
                                              mock_map_volume,
@@ -498,7 +498,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=MAPPINGS)
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES_EMPTY)
+                       return_value=(0, ISCSI_PROPERTIES_EMPTY))
     def test_initialize_connection_vol_not_found(self,
                                                  mock_find_iscsi_properties,
                                                  mock_map_volume,
@@ -532,7 +532,7 @@ class DellSCSanISCSIDriverTestCase(test.TestCase):
                        return_value=None)
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        'find_iscsi_properties',
-                       return_value=ISCSI_PROPERTIES)
+                       return_value=(0, ISCSI_PROPERTIES))
     def test_initialize_connection_map_vol_fail(self,
                                                 mock_find_iscsi_props,
                                                 mock_map_volume,
index 4bb964e6bf2c73f38b5d48d173d945691ac6798d..85f38ebeb9d79a0bc129e83712bcab86d0551b94 100644 (file)
@@ -110,6 +110,51 @@ class DellSCSanAPITestCase(test.TestCase):
               u'mapped': False,
               u'cmmSource': False}
 
+    VOLUME_CONFIG = \
+        {u'instanceId': u'64702.3494',
+         u'scSerialNumber': 64702,
+         u'maximumSiblingCount': 100,
+         u'writeCacheStatus': u'Up',
+         u'objectType': u'ScVolumeConfiguration',
+         u'currentSiblingConfiguredSize': u'2.147483648E9 Bytes',
+         u'compressionPaused': False,
+         u'enforceConsumptionLimit': False,
+         u'volumeSpaceConsumptionLimit': u'2.147483648E9 Bytes',
+         u'readCacheEnabled': True,
+         u'writeCacheEnabled': True,
+         u'instanceName': u'volume-ff9589d3-2d41-48d5-9ef5-2713a875e85b',
+         u'dateModified': u'04/03/2015 12:01:08 AM',
+         u'modifyUser': u'Admin',
+         u'replayExpirationPaused': False,
+         u'currentSiblingCount': 1,
+         u'replayCreationPaused': False,
+         u'replayProfileList': [{u'instanceId': u'64702.2',
+                                 u'instanceName': u'Daily',
+                                 u'objectType': u'ScReplayProfile'}],
+         u'dateCreated': u'04/04/2014 03:54:26 AM',
+         u'volume': {u'instanceId': u'64702.3494',
+                     u'instanceName':
+                     u'volume-37883deb-85cd-426a-9a98-62eaad8671ea',
+                     u'objectType': u'ScVolume'},
+         u'controller': {u'instanceId': u'64702.64703',
+                         u'instanceName': u'SN 64703',
+                         u'objectType': u'ScController'},
+         u'coalesceIntoActive': False,
+         u'createUser': u'Admin',
+         u'importToLowestTier': False,
+         u'readCacheStatus': u'Up',
+         u'maximumSiblingConfiguredSpace': u'5.49755813888E14 Bytes',
+         u'storageProfile': {u'instanceId': u'64702.1',
+                             u'instanceName': u'Recommended',
+                             u'objectType': u'ScStorageProfile'},
+         u'scName': u'Storage Center 64702',
+         u'notes': u'',
+         u'diskFolder': {u'instanceId': u'64702.3',
+                         u'instanceName': u'Assigned',
+                         u'objectType': u'ScDiskFolder'},
+         u'openVmsUniqueDiskId': 48,
+         u'compressionEnabled': False}
+
     INACTIVE_VOLUME = \
         {u'instanceId': u'64702.3494',
          u'scSerialNumber': 64702,
@@ -623,6 +668,110 @@ class DellSCSanAPITestCase(test.TestCase):
                     u'transport': u'FibreChannel',
                     u'objectType': u'ScMapping'}]
 
+    FC_MAPPINGS_LUN_MISMATCH = \
+        [{u'profile': {u'instanceId': u'64702.2941',
+                       u'instanceName': u'6025-47',
+                       u'objectType': u'ScMappingProfile'},
+          u'status': u'Up',
+          u'statusMessage': u'',
+          u'instanceId': u'64702.7639.64702',
+          u'scName': u'Storage Center 64702',
+          u'scSerialNumber': 64702,
+          u'controller': {u'instanceId': u'64702.64703',
+                          u'instanceName': u'SN 64703',
+                          u'objectType': u'ScController'},
+          u'server': {u'instanceId': u'64702.47',
+                      u'instanceName': u'Server_21000024ff30441d',
+                      u'objectType': u'ScPhysicalServer'},
+          u'volume': {u'instanceId': u'64702.6025',
+                      u'instanceName':
+                      u'Server_21000024ff30441d Test Vol',
+                      u'objectType': u'ScVolume'},
+          u'readOnly': False,
+          u'lun': 1,
+          u'serverHba': {u'instanceId': u'64702.3282218607',
+                         u'instanceName': u'21000024FF30441C',
+                         u'objectType': u'ScServerHba'},
+          u'path': {u'instanceId': u'64702.64702.64703.27.73',
+                    u'instanceName':
+                    u'21000024FF30441C-5000D31000FCBE36',
+                    u'objectType': u'ScServerHbaPath'},
+          u'controllerPort':
+          {u'instanceId': u'64702.5764839588723736118.50',
+           u'instanceName': u'5000D31000FCBE36',
+           u'objectType': u'ScControllerPort'},
+          u'instanceName': u'64702-7639',
+          u'transport': u'FibreChannel',
+          u'objectType': u'ScMapping'},
+         {u'profile': {u'instanceId': u'64702.2941',
+                       u'instanceName': u'6025-47',
+                       u'objectType': u'ScMappingProfile'},
+          u'status': u'Up',
+          u'statusMessage': u'',
+          u'instanceId': u'64702.7640.64702',
+          u'scName': u'Storage Center 64702',
+          u'scSerialNumber': 64702,
+          u'controller': {u'instanceId': u'64702.64703',
+                          u'instanceName': u'SN 64703',
+                          u'objectType': u'ScController'},
+          u'server': {u'instanceId': u'64702.47',
+                      u'instanceName': u'Server_21000024ff30441d',
+                      u'objectType': u'ScPhysicalServer'},
+          u'volume':
+          {u'instanceId': u'64702.6025',
+           u'instanceName': u'Server_21000024ff30441d Test Vol',
+           u'objectType': u'ScVolume'},
+          u'readOnly': False,
+          u'lun': 1,
+          u'serverHba': {u'instanceId': u'64702.3282218606',
+                         u'instanceName': u'21000024FF30441D',
+                         u'objectType': u'ScServerHba'},
+          u'path':
+          {u'instanceId': u'64702.64702.64703.27.78',
+           u'instanceName': u'21000024FF30441D-5000D31000FCBE36',
+           u'objectType': u'ScServerHbaPath'},
+          u'controllerPort':
+          {u'instanceId': u'64702.5764839588723736118.50',
+           u'instanceName': u'5000D31000FCBE36',
+           u'objectType': u'ScControllerPort'},
+          u'instanceName': u'64702-7640',
+          u'transport': u'FibreChannel',
+          u'objectType': u'ScMapping'},
+            {u'profile': {u'instanceId': u'64702.2941',
+                          u'instanceName': u'6025-47',
+                          u'objectType': u'ScMappingProfile'},
+             u'status': u'Up',
+             u'statusMessage': u'',
+             u'instanceId': u'64702.7638.64702',
+             u'scName': u'Storage Center 64702',
+             u'scSerialNumber': 64702,
+             u'controller': {u'instanceId': u'64702.64703',
+                             u'instanceName': u'SN 64703',
+                             u'objectType': u'ScController'},
+             u'server': {u'instanceId': u'64702.47',
+                         u'instanceName': u'Server_21000024ff30441d',
+                         u'objectType': u'ScPhysicalServer'},
+             u'volume': {u'instanceId': u'64702.6025',
+                         u'instanceName':
+                         u'Server_21000024ff30441d Test Vol',
+                         u'objectType': u'ScVolume'},
+             u'readOnly': False,
+             u'lun': 2,
+             u'serverHba': {u'instanceId': u'64702.3282218606',
+                            u'instanceName': u'21000024FF30441D',
+                            u'objectType': u'ScServerHba'},
+             u'path':
+                        {u'instanceId': u'64702.64702.64703.28.76',
+                         u'instanceName': u'21000024FF30441D-5000D31000FCBE3E',
+                         u'objectType': u'ScServerHbaPath'},
+             u'controllerPort': {u'instanceId':
+                                 u'64702.5764839588723736126.60',
+                                 u'instanceName': u'5000D31000FCBE3E',
+                                 u'objectType': u'ScControllerPort'},
+             u'instanceName': u'64702-7638',
+             u'transport': u'FibreChannel',
+             u'objectType': u'ScMapping'}]
+
     RPLAY = {u'scSerialNumber': 64702,
              u'globalIndex': u'64702-46-250',
              u'description': u'Cinder Clone Replay',
@@ -1070,6 +1219,40 @@ class DellSCSanAPITestCase(test.TestCase):
                      u'statusMessage': u'',
                      u'objectType': u'ScControllerPort'}
 
+    FC_CTRLR_PORT_WWN_ERROR = \
+        {u'preferredParent':
+         {u'instanceId': u'64702.5764839588723736093.57',
+          u'instanceName': u'5000D31000FCBE1D',
+          u'objectType': u'ScControllerPort'},
+         u'status': u'Up',
+         u'iscsiIpAddress': u'0.0.0.0',
+         u'Wwn': u'5000D31000FCBE36',
+         u'name': u'5000D31000FCBE36',
+         u'parent':
+         {u'instanceId': u'64702.5764839588723736093.57',
+          u'instanceName': u'5000D31000FCBE1D',
+          u'objectType': u'ScControllerPort'},
+         u'iscsiGateway': u'0.0.0.0',
+         u'instanceId': u'64702.5764839588723736118.50',
+         u'scName': u'Storage Center 64702',
+         u'scSerialNumber': 64702,
+         u'transportType': u'FibreChannel',
+         u'virtual': True,
+         u'controller': {u'instanceId': u'64702.64703',
+                         u'instanceName': u'SN 64703',
+                         u'objectType': u'ScController'},
+         u'iscsiName': u'',
+         u'purpose': u'FrontEnd',
+         u'iscsiSubnetMask': u'0.0.0.0',
+         u'faultDomain':
+         {u'instanceId': u'64702.1.0',
+          u'instanceName': u'Domain 0',
+          u'objectType': u'ScControllerPortFaultDomain'},
+         u'instanceName': u'5000D31000FCBE36',
+         u'childStatus': u'Up',
+         u'statusMessage': u'',
+         u'objectType': u'ScControllerPort'}
+
     STRG_USAGE = {u'systemSpace': u'7.38197504E8 Bytes',
                   u'freeSpace': u'1.297659461632E13 Bytes',
                   u'oversubscribedSpace': u'0.0 Bytes',
@@ -1094,6 +1277,10 @@ class DellSCSanAPITestCase(test.TestCase):
     WWNS = [u'21000024FF30441C',
             u'21000024FF30441D']
 
+    # Used to test finding no match in find_wwns
+    WWNS_NO_MATCH = [u'21000024FF30451C',
+                     u'21000024FF30451D']
+
     FLDR_PATH = 'StorageCenter/ScVolumeFolder/'
 
     # Create a Response object that indicates OK
@@ -2464,6 +2651,125 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertEqual([], wwns, 'WWNs is not empty')
         self.assertEqual({}, itmap, 'WWN mapping not empty')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_controller_port',
+                       return_value=FC_CTRLR_PORT_WWN_ERROR)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_mappings',
+                       return_value=FC_MAPPINGS)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_fc_initiators',
+                       return_value=WWNS)
+    def test_find_wwns_wwn_error(self,
+                                 mock_find_fc_initiators,
+                                 mock_find_mappings,
+                                 mock_find_controller_port,
+                                 mock_close_connection,
+                                 mock_open_connection,
+                                 mock_init):
+        # Test case where ScControllerPort object has WWn instead of wwn for a
+        # property
+        lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
+                                                self.SCSERVER)
+        self.assertTrue(mock_find_fc_initiators.called)
+        self.assertTrue(mock_find_mappings.called)
+        self.assertTrue(mock_find_controller_port.called)
+
+        self.assertEqual(None, lun, 'Incorrect LUN')
+        self.assertEqual([], wwns, 'WWNs is not empty')
+        self.assertEqual({}, itmap, 'WWN mapping not empty')
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_controller_port',
+                       return_value=FC_CTRLR_PORT)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_mappings',
+                       return_value=FC_MAPPINGS)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_fc_initiators',
+                       return_value=WWNS_NO_MATCH)
+    # Test case where HBA name is not found in list of initiators
+    def test_find_wwns_hbaname_not_found(self,
+                                         mock_find_fc_initiators,
+                                         mock_find_mappings,
+                                         mock_find_controller_port,
+                                         mock_close_connection,
+                                         mock_open_connection,
+                                         mock_init):
+        lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
+                                                self.SCSERVER)
+        self.assertTrue(mock_find_fc_initiators.called)
+        self.assertTrue(mock_find_mappings.called)
+        self.assertTrue(mock_find_controller_port.called)
+
+        self.assertEqual(None, lun, 'Incorrect LUN')
+        self.assertEqual([], wwns, 'WWNs is not empty')
+        self.assertEqual({}, itmap, 'WWN mapping not empty')
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_controller_port',
+                       return_value=FC_CTRLR_PORT)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_mappings',
+                       return_value=FC_MAPPINGS_LUN_MISMATCH)
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_fc_initiators',
+                       return_value=WWNS)
+    # Test case where FC mappings contain a LUN mismatch
+    def test_find_wwns_lun_mismatch(self,
+                                    mock_find_fc_initiators,
+                                    mock_find_mappings,
+                                    mock_find_controller_port,
+                                    mock_close_connection,
+                                    mock_open_connection,
+                                    mock_init):
+        lun, wwns, itmap = self.scapi.find_wwns(self.VOLUME,
+                                                self.SCSERVER)
+        self.assertTrue(mock_find_fc_initiators.called)
+        self.assertTrue(mock_find_mappings.called)
+        self.assertTrue(mock_find_controller_port.called)
+        # The _find_controller_port is Mocked, so all mapping pairs
+        # will have the same WWN for the ScControllerPort
+        itmapCompare = {u'21000024FF30441C': [u'5000D31000FCBE36'],
+                        u'21000024FF30441D':
+                        [u'5000D31000FCBE36', u'5000D31000FCBE36']}
+        self.assertEqual(1, lun, 'Incorrect LUN')
+        self.assertIsNotNone(wwns, 'WWNs is None')
+        self.assertEqual(itmapCompare, itmap, 'WWN mapping incorrect')
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_first_result',
+                       return_value=VOLUME_CONFIG)
+    @mock.patch.object(dell_storagecenter_api.HttpClient,
+                       'get',
+                       return_value=RESPONSE_200)
+    def test_find_active_controller(self,
+                                    mock_get,
+                                    mock_first_result,
+                                    mock_close_connection,
+                                    mock_open_connection,
+                                    mock_init):
+        res = self.scapi._find_active_controller(self.VOLUME)
+        self.assertTrue(mock_get.called)
+        self.assertTrue(mock_first_result.called)
+        self.assertEqual('64702.64703', res, 'Unexpected Active Controller')
+
+    @mock.patch.object(dell_storagecenter_api.HttpClient,
+                       'get',
+                       return_value=RESPONSE_204)
+    def test_find_active_controller_failure(self,
+                                            mock_get,
+                                            mock_close_connection,
+                                            mock_open_connection,
+                                            mock_init):
+        # Test case of where get of ScVolume MappingList fails
+        res = self.scapi._find_active_controller(self.VOLUME)
+        self.assertTrue(mock_get.called)
+        self.assertEqual(None, res, 'Expected None')
+
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2477,6 +2783,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                             mock_find_mappings,
                                             mock_find_domain,
                                             mock_find_ctrl_port,
+                                            mock_find_active_controller,
                                             mock_close_connection,
                                             mock_open_connection,
                                             mock_init):
@@ -2484,14 +2791,19 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns':
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns':
                         [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
-                    'target_luns': [1],
-                    'target_portals': [u'192.168.0.21:3260']}
+                     'target_luns': [1],
+                     'target_portals': [u'192.168.0.21:3260']})
         self.assertEqual(expected, res, 'Wrong Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2505,6 +2817,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                               mock_find_mappings,
                                               mock_find_domain,
                                               mock_find_ctrl_port,
+                                              mock_find_active_controller,
                                               mock_close_connection,
                                               mock_open_connection,
                                               mock_init):
@@ -2514,14 +2827,19 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns':
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns':
                         [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
-                    'target_luns': [1],
-                    'target_portals': [u'192.168.0.21:3260']}
+                     'target_luns': [1],
+                     'target_portals': [u'192.168.0.21:3260']})
         self.assertEqual(expected, res, 'Wrong Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2535,6 +2853,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                                         mock_find_mappings,
                                                         mock_find_domain,
                                                         mock_find_ctrl_port,
+                                                        mock_find_active_ctrl,
                                                         mock_close_connection,
                                                         mock_open_connection,
                                                         mock_init):
@@ -2544,31 +2863,42 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns': [],
-                    'target_luns': [],
-                    'target_portals': []}
+        self.assertTrue(mock_find_active_ctrl.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns': [],
+                     'target_luns': [],
+                     'target_portals': []})
         self.assertEqual(expected, res, 'Wrong Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_mappings',
                        return_value=[])
     def test_find_iscsi_properties_no_mapping(self,
                                               mock_find_mappings,
+                                              mock_find_active_controller,
                                               mock_close_connection,
                                               mock_open_connection,
                                               mock_init):
         # Test case where there are no ScMapping(s)
         res = self.scapi.find_iscsi_properties(self.VOLUME)
         self.assertTrue(mock_find_mappings.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns': [],
-                    'target_luns': [],
-                    'target_portals': []}
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns': [],
+                     'target_luns': [],
+                     'target_portals': []})
         self.assertEqual(expected, res, 'Expected empty Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2582,6 +2912,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                              mock_find_mappings,
                                              mock_find_domain,
                                              mock_find_ctrl_port,
+                                             mock_find_active_controller,
                                              mock_close_connection,
                                              mock_open_connection,
                                              mock_init):
@@ -2590,13 +2921,18 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertFalse(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns': [],
-                    'target_luns': [],
-                    'target_portals': []}
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns': [],
+                     'target_luns': [],
+                     'target_portals': []})
         self.assertEqual(expected, res, 'Expected empty Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=None)
@@ -2610,6 +2946,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                                 mock_find_mappings,
                                                 mock_find_domain,
                                                 mock_find_ctrl_port,
+                                                mock_find_active_controller,
                                                 mock_close_connection,
                                                 mock_open_connection,
                                                 mock_init):
@@ -2618,13 +2955,18 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns': [],
-                    'target_luns': [],
-                    'target_portals': []}
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns': [],
+                     'target_luns': [],
+                     'target_portals': []})
         self.assertEqual(expected, res, 'Expected empty Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2638,6 +2980,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                       mock_find_mappings,
                                       mock_find_domain,
                                       mock_find_ctrl_port,
+                                      mock_find_active_controller,
                                       mock_close_connection,
                                       mock_open_connection,
                                       mock_init):
@@ -2646,14 +2989,19 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'ro',
-                    'target_discovered': False,
-                    'target_iqns':
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'ro',
+                     'target_discovered': False,
+                     'target_iqns':
                         [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
-                    'target_luns': [1],
-                    'target_portals': [u'192.168.0.21:3260']}
+                     'target_luns': [1],
+                     'target_portals': [u'192.168.0.21:3260']})
         self.assertEqual(expected, res, 'Wrong Target Info')
 
+    @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
+                       '_find_active_controller',
+                       return_value='64702.5764839588723736131.91')
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
                        '_find_controller_port',
                        return_value=ISCSI_CTRLR_PORT)
@@ -2667,6 +3015,7 @@ class DellSCSanAPITestCase(test.TestCase):
                                                  mock_find_mappings,
                                                  mock_find_domain,
                                                  mock_find_ctrl_port,
+                                                 mock_find_active_controller,
                                                  mock_close_connection,
                                                  mock_open_connection,
                                                  mock_init):
@@ -2675,13 +3024,15 @@ class DellSCSanAPITestCase(test.TestCase):
         self.assertTrue(mock_find_mappings.called)
         self.assertTrue(mock_find_domain.called)
         self.assertTrue(mock_find_ctrl_port.called)
-        expected = {'access_mode': 'rw',
-                    'target_discovered': False,
-                    'target_iqns':
+        self.assertTrue(mock_find_active_controller.called)
+        expected = (0,
+                    {'access_mode': 'rw',
+                     'target_discovered': False,
+                     'target_iqns':
                         [u'iqn.2002-03.com.compellent:5000d31000fcbe43'],
-                    'target_luns': [1],
-                    'target_portals':
-                        [u'192.168.0.21:3260', u'192.168.0.25:3260']}
+                     'target_luns': [1],
+                     'target_portals':
+                        [u'192.168.0.21:3260', u'192.168.0.25:3260']})
         self.assertEqual(expected, res, 'Wrong Target Info')
 
     @mock.patch.object(dell_storagecenter_api.StorageCenterApi,
index 31f6428f49b233ca4f07d7b266093c7218bc5857..3f1d39625b063ca58158b665b55a563864652a22 100644 (file)
@@ -358,6 +358,10 @@ class StorageCenterApi(object):
             scservers = self._get_json(r)
             # Sort through the servers looking for one with connectivity.
             for scserver in scservers:
+                # TODO(tom_swanson): Add check for server type.
+                # This needs to be either a physical or virtual server.
+                # Outside of tempest tests this should not matter as we only
+                # "init" a volume to allow snapshotting of an empty volume.
                 if scserver.get('status', '').lower() != 'down':
                     # Map to actually create the volume
                     self.map_volume(scvolume,
@@ -795,23 +799,42 @@ class StorageCenterApi(object):
         # pretend we succeeded.
         return lun, wwns, itmap
 
+    def _find_active_controller(self, scvolume):
+        LOG.debug('find_active_controller')
+        activecontroller = None
+        r = self.client.get('StorageCenter/ScVolume/%s/VolumeConfiguration'
+                            % self._get_id(scvolume))
+        if r.status_code == 200:
+            volumeconfiguration = self._first_result(r)
+            controller = volumeconfiguration.get('controller')
+            activecontroller = self._get_id(controller)
+        LOG.debug('activecontroller %s', activecontroller)
+        return activecontroller
+
     def find_iscsi_properties(self, scvolume, ip=None, port=None):
+        LOG.debug('enter find_iscsi_properties')
+        LOG.debug('scvolume: %s', scvolume)
+        activeindex = -1
         luns = []
         iqns = []
         portals = []
         access_mode = 'rw'
         mappings = self._find_mappings(scvolume)
+        activecontroller = self._find_active_controller(scvolume)
         if len(mappings) > 0:
             for mapping in mappings:
+                LOG.debug('mapping: %s', mapping)
                 # find the controller port for this mapping
                 cport = mapping.get('controllerPort')
                 cportid = self._get_id(cport)
                 domains = self._find_domains(cportid)
                 if domains:
                     controllerport = self._find_controller_port(cportid)
+                    LOG.debug('controllerport: %s', controllerport)
                     if controllerport is not None:
                         appendproperties = False
                         for d in domains:
+                            LOG.debug('domain: %s', d)
                             ipaddress = d.get('targetIpv4Address',
                                               d.get('wellKnownIpAddress'))
                             portnumber = d.get('portNumber')
@@ -825,6 +848,9 @@ class StorageCenterApi(object):
                                 if portals.count(portal) == 0:
                                     appendproperties = True
                                     portals.append(portal)
+                                else:
+                                    LOG.debug('Domain %s has two portals.',
+                                              self._get_id(d))
                         # We do not report lun and iqn info unless it is for
                         # the configured port OR the user has not enabled
                         # multipath.  (In which case ip and port sent in
@@ -832,17 +858,27 @@ class StorageCenterApi(object):
                         if appendproperties is True:
                             iqns.append(controllerport.get('iscsiName'))
                             luns.append(mapping.get('lun'))
+                            if activeindex == -1:
+                                controller = controllerport.get('controller')
+                                controllerid = self._get_id(controller)
+                                if controllerid == activecontroller:
+                                    activeindex = len(iqns) - 1
                         if mapping['readOnly'] is True:
                             access_mode = 'ro'
 
+        if activeindex == -1:
+            LOG.debug('Volume is not yet active on any controller.')
+            activeindex = 0
+
         data = {'target_discovered': False,
                 'target_iqns': iqns,
                 'target_portals': portals,
                 'target_luns': luns,
                 'access_mode': access_mode
                 }
+        LOG.debug('find_iscsi_properties return: %s', data)
 
-        return data
+        return activeindex, data
 
     def map_volume(self, scvolume, scserver):
         '''map_volume
index f72333a6d2c63ba5422144f77ace3843512c1078..47511ab7b49cb137a4344a9e05c61ca5bc103671 100644 (file)
@@ -330,8 +330,8 @@ class DellCommonDriver(san.SanDriver):
             data['driver_version'] = self.VERSION
             data['storage_protocol'] = 'iSCSI'
             data['reserved_percentage'] = 0
-            # in theory if storageusage is None then we should have
-            # blown up getting it.  If not just report inifinite.
+            # In theory if storageusage is None then we should have
+            # blown up getting it.  If not just report unavailable.
             if storageusage is not None:
                 totalcapacity = storageusage.get('availableSpace')
                 totalcapacitygb = self._bytes_to_gb(totalcapacity)
index 40eb7614cc9d161dbe52c940644e7e858d8fef6f..45cf5cb0dfe365965fc17ec5ad168e91770ea136 100644 (file)
@@ -80,7 +80,7 @@ class DellStorageCenterISCSIDriver(san.SanISCSIDriver,
 
                         if multipath:
                             # Just return our properties with all the mappings
-                            iscsiproperties = (
+                            idx, iscsiproperties = (
                                 api.find_iscsi_properties(scvolume,
                                                           None,
                                                           None))
@@ -90,7 +90,7 @@ class DellStorageCenterISCSIDriver(san.SanISCSIDriver,
                             # Only return the iqn for the user specified port.
                             ip = self.configuration.iscsi_ip_address
                             port = self.configuration.iscsi_port
-                            iscsiproperties = (
+                            idx, iscsiproperties = (
                                 api.find_iscsi_properties(scvolume,
                                                           ip,
                                                           port))
@@ -101,11 +101,11 @@ class DellStorageCenterISCSIDriver(san.SanISCSIDriver,
                             # one listed we can assume that we found what
                             # we are looking for.  Otherwise error.
                             if len(portals) > 0:
-                                properties['target_portal'] = portals[0]
+                                properties['target_portal'] = portals[idx]
                                 properties['target_iqn'] = (
-                                    iscsiproperties['target_iqns'][0])
+                                    iscsiproperties['target_iqns'][idx])
                                 properties['target_lun'] = (
-                                    iscsiproperties['target_luns'][0])
+                                    iscsiproperties['target_luns'][idx])
                                 properties['access_mode'] = (
                                     iscsiproperties['access_mode'])
                                 LOG.debug(properties)