]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Adds storwize_svc_npiv_compatibility_mode flag to Storwize/SVC driver
authorGeraint North <geraint.north@uk.ibm.com>
Mon, 21 Jul 2014 21:23:48 +0000 (22:23 +0100)
committerGeraint North <geraint.north@uk.ibm.com>
Tue, 22 Jul 2014 12:21:10 +0000 (13:21 +0100)
This configuration option allows the driver to function in an
environment where an attach operation occurs before the virtual FC
ports are logged into the fabric.

Today's behaviour (which is maintained as default behaviour) is to
only build the initiator_target_map for initiator ports that are
logged into the fabric, and error if there are no such ports.

If this new flag is set to True, then if no initiator ports are
found on the fabric, ALL initiator ports are placed into the
initiator_target_map, rather than none, which is the case today.

Closes-Bug: 1346622
Change-Id: Ie722612bc5a9af2816348392c0c39da003b99028

cinder/tests/test_storwize_svc.py
cinder/volume/drivers/ibm/storwize_svc/__init__.py
etc/cinder/cinder.conf.sample

index 6ac863ecd0bd7c5d31a674f9f00a86fe30f96759..074a23b80025a9b693fb61380449bce0e7ff1611 100644 (file)
@@ -1979,7 +1979,35 @@ class StorwizeSVCDriverTestCase(test.TestCase):
                                       self.driver.initialize_connection,
                                       volume2, self._connector)
 
+                # with storwize_svc_npiv_compatibility_mode set to True,
+                # lsfabric can return [] and initilize_connection will still
+                # complete successfully
+
+                with mock.patch.object(helpers.StorwizeHelpers,
+                                       'get_conn_fc_wwpns') as conn_fc_wwpns:
+                    conn_fc_wwpns.return_value = []
+                    self._set_flag('storwize_svc_npiv_compatibility_mode',
+                                   True)
+                    expected_fc_npiv = {
+                        'driver_volume_type': 'fibre_channel',
+                        'data': {'target_lun': 1,
+                                 'target_wwn': '500507680220C744',
+                                 'target_discovered': False}}
+                    ret = self.driver.initialize_connection(volume2,
+                                                            self._connector)
+                    self.assertEqual(
+                        ret['driver_volume_type'],
+                        expected_fc_npiv['driver_volume_type'])
+                    for k, v in expected_fc_npiv['data'].iteritems():
+                        self.assertEqual(ret['data'][k], v)
+                    self._set_flag('storwize_svc_npiv_compatibility_mode',
+                                   False)
+
             self.driver.terminate_connection(volume1, self._connector)
+            # for npiv compatibility test case, we need to terminate connection
+            # to the 2nd volume
+            if protocol == 'FC' and self.USESIM:
+                self.driver.terminate_connection(volume2, self._connector)
             if self.USESIM:
                 ret = self.driver._helpers.get_host_from_connector(
                     self._connector)
@@ -2565,6 +2593,64 @@ class StorwizeSVCDriverTestCase(test.TestCase):
 
         self.assertEqual(term_data, term_ret)
 
+    def test_storwize_initiator_target_map_npiv(self):
+        # Create two volumes to be used in mappings
+        ctxt = context.get_admin_context()
+        self._set_flag('storwize_svc_npiv_compatibility_mode', True)
+
+        # Generate us a test volume
+        volume = self._generate_vol_info(None, None)
+        self.driver.create_volume(volume)
+
+        # FIbre Channel volume type
+        vol_type = volume_types.create(ctxt, 'FC', {'protocol': 'FC'})
+
+        volume['volume_type_id'] = vol_type['id']
+
+        # Make sure that the volumes have been created
+        self._assert_vol_exists(volume['name'], True)
+
+        wwpns = ['ff00000000000000', 'ff00000000000001']
+        connector = {'host': 'storwize-svc-test', 'wwpns': wwpns}
+
+        # Initialise the connection
+        with mock.patch.object(helpers.StorwizeHelpers,
+                               'get_conn_fc_wwpns') as conn_fc_wwpns:
+            conn_fc_wwpns.return_value = []
+            init_ret = self.driver.initialize_connection(volume, connector)
+
+        # Check that the initiator_target_map is as expected
+        init_data = {'driver_volume_type': 'fibre_channel',
+                     'data': {'initiator_target_map':
+                              {'ff00000000000000': ['500507680220C744',
+                                                    '500507680210C744',
+                                                    '500507680220C745',
+                                                    '500507680230C745'],
+                               'ff00000000000001': ['500507680220C744',
+                                                    '500507680210C744',
+                                                    '500507680220C745',
+                                                    '500507680230C745']},
+                              'target_discovered': False,
+                              'target_lun': 0,
+                              'target_wwn': '500507680220C744',
+                              'volume_id': volume['id']
+                              }
+                     }
+
+        self.assertEqual(init_data, init_ret)
+
+        # Terminate connection
+        term_ret = self.driver.terminate_connection(volume, connector)
+        # Check that the initiator_target_map is as expected
+        term_data = {'driver_volume_type': 'fibre_channel',
+                     'data': {'initiator_target_map':
+                              {'ff00000000000000': ['AABBCCDDEEFF0011'],
+                               'ff00000000000001': ['AABBCCDDEEFF0011']}
+                              }
+                     }
+
+        self.assertEqual(term_data, term_ret)
+
     def _get_vdisk_uid(self, vdisk_name):
         """Return vdisk_UID for given vdisk.
 
index 70659626c40d7f93e8c7ce43571f542c874c98e3..dcc5368ead1ed70a4302a645942a6890aae07787 100644 (file)
@@ -101,6 +101,12 @@ storwize_svc_opts = [
     cfg.BoolOpt('storwize_svc_multihostmap_enabled',
                 default=True,
                 help='Allows vdisk to multi host mapping'),
+    cfg.BoolOpt('storwize_svc_npiv_compatibility_mode',
+                default=False,
+                help='Indicate whether svc driver is compatible for NPIV '
+                     'setup. If it is compatible, it will allow no wwpns '
+                     'being returned on get_conn_fc_wwpns during '
+                     'initialize_connection'),
 ]
 
 CONF = cfg.CONF
@@ -410,12 +416,25 @@ class StorwizeSVCDriver(san.SanDriver):
             else:
                 type_str = 'fibre_channel'
                 conn_wwpns = self._helpers.get_conn_fc_wwpns(host_name)
+
+                # If conn_wwpns is empty, then that means that there were
+                # no target ports with visibility to any of the initiators.
+                # We will either fail the attach, or return all target
+                # ports, depending on the value of the
+                # storwize_svc_npiv_compatibity_mode flag.
                 if len(conn_wwpns) == 0:
-                    msg = (_('Could not get FC connection information for the '
-                             'host-volume connection. Is the host configured '
-                             'properly for FC connections?'))
-                    LOG.error(msg)
-                    raise exception.VolumeBackendAPIException(data=msg)
+                    npiv_compat = self.configuration.\
+                        storwize_svc_npiv_compatibility_mode
+                    if not npiv_compat:
+                        msg = (_('Could not get FC connection information for '
+                                 'the host-volume connection. Is the host '
+                                 'configured properly for FC connections?'))
+                        LOG.error(msg)
+                        raise exception.VolumeBackendAPIException(data=msg)
+                    else:
+                        for node in self._state['storage_nodes'].itervalues():
+                            conn_wwpns.extend(node['WWPN'])
+
                 if not vol_opts['multipath']:
                     # preferred_node_entry can have a list of WWPNs while only
                     # one WWPN may be available on the storage host.  Here we
index e6c7af015a1e43863b8f487ebe773038b45f720b..ec24b09f8a66bffd3335fcb515e13164e365feb1 100644 (file)
 # Allows vdisk to multi host mapping (boolean value)
 #storwize_svc_multihostmap_enabled=true
 
+# Indicate whether svc driver is compatible for NPIV setup. If
+# it is compatible, it will allow no wwpns being returned on
+# get_conn_fc_wwpns during initialize_connection (boolean
+# value)
+#storwize_svc_npiv_compatibility_mode=false
+
 
 #
 # Options defined in cinder.volume.drivers.ibm.xiv_ds8k