]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Fix performance issues with brocade zone driver.
authorAngela Smith <aallen@brocade.com>
Wed, 4 Jun 2014 19:12:15 +0000 (12:12 -0700)
committerAngela Smith <aallen@brocade.com>
Wed, 16 Jul 2014 20:00:41 +0000 (13:00 -0700)
Removed firmware checks from common path as the ssh invoke_shell
was taking 5 seconds to complete for each firmware check.
Refactored to only do cfgsave in non-activate case.
Removed extra calls to switch to get the active zoneset.

Closes-Bug: #1292119

Change-Id: Ie1c2c0c603f6dd68439f2c2db74b21ea2dd0fc11

cinder/tests/zonemanager/test_brcd_fc_zone_client_cli.py
cinder/tests/zonemanager/test_brcd_fc_zone_driver.py
cinder/tests/zonemanager/test_fc_zone_manager.py
cinder/zonemanager/drivers/brocade/brcd_fc_zone_client_cli.py
cinder/zonemanager/drivers/brocade/brcd_fc_zone_driver.py

index 2fcf2e14c9d32cc1605acf0cbba956e91501e2ed..4f0bc7c83a804ceea79967a23ff55b166023b627 100644 (file)
@@ -94,24 +94,20 @@ class TestBrcdFCZoneClientCLI(BrcdFCZoneClientCLI, test.TestCase):
                                             apply_zone_change_mock,
                                             cfg_save_mock):
         get_active_zs_mock.return_value = active_zoneset
-        self.add_zones(new_zones, False)
+        self.add_zones(new_zones, False, None)
         get_active_zs_mock.assert_called_once()
         apply_zone_change_mock.assert_called_twice()
         cfg_save_mock.assert_called_once()
 
     @mock.patch.object(BrcdFCZoneClientCLI, 'get_active_zone_set')
     @mock.patch.object(BrcdFCZoneClientCLI, 'apply_zone_change')
-    @mock.patch.object(BrcdFCZoneClientCLI, '_cfg_save')
     @mock.patch.object(BrcdFCZoneClientCLI, 'activate_zoneset')
     def test_add_zones_new_zone_activate(self, get_active_zs_mock,
                                          apply_zone_change_mock,
-                                         cfg_save_mock,
                                          activate_zoneset_mock):
         get_active_zs_mock.return_value = active_zoneset
-        self.add_zones(new_zone, True)
-        get_active_zs_mock.assert_called_once()
+        self.add_zones(new_zone, True, active_zoneset)
         apply_zone_change_mock.assert_called_once()
-        cfg_save_mock.assert_called_once()
         activate_zoneset_mock.assert_called_once()
 
     @mock.patch.object(BrcdFCZoneClientCLI, '_ssh_execute')
@@ -126,44 +122,34 @@ class TestBrcdFCZoneClientCLI(BrcdFCZoneClientCLI, test.TestCase):
         return_value = self.deactivate_zoneset()
         self.assertTrue(return_value)
 
-    @mock.patch.object(BrcdFCZoneClientCLI, 'get_active_zone_set')
     @mock.patch.object(BrcdFCZoneClientCLI, 'apply_zone_change')
     @mock.patch.object(BrcdFCZoneClientCLI, '_cfg_save')
-    def test_delete_zones_activate_false(self, get_active_zs_mock,
-                                         apply_zone_change_mock,
+    def test_delete_zones_activate_false(self, apply_zone_change_mock,
                                          cfg_save_mock):
-        get_active_zs_mock.return_value = active_zoneset_multiple_zones
         with mock.patch.object(self, '_zone_delete') \
                 as zone_delete_mock:
-            self.delete_zones(zone_names_to_delete, False)
-            get_active_zs_mock.assert_called_once()
+            self.delete_zones(zone_names_to_delete, False,
+                              active_zoneset_multiple_zones)
             apply_zone_change_mock.assert_called_once()
             zone_delete_mock.assert_called_once_with(zone_names_to_delete)
             cfg_save_mock.assert_called_once()
 
-    @patch.object(BrcdFCZoneClientCLI, 'get_active_zone_set')
     @patch.object(BrcdFCZoneClientCLI, 'apply_zone_change')
-    @patch.object(BrcdFCZoneClientCLI, '_cfg_save')
     @patch.object(BrcdFCZoneClientCLI, 'activate_zoneset')
-    def test_delete_zones_activate_true(self, get_active_zs_mock,
-                                        apply_zone_change_mock,
-                                        cfg_save_mock,
+    def test_delete_zones_activate_true(self, apply_zone_change_mock,
                                         activate_zs_mock):
-        get_active_zs_mock.return_value = active_zoneset_multiple_zones
         with mock.patch.object(self, '_zone_delete') \
                 as zone_delete_mock:
-            self.delete_zones(zone_names_to_delete, True)
-            get_active_zs_mock.assert_called_once()
+            self.delete_zones(zone_names_to_delete, True,
+                              active_zoneset_multiple_zones)
             apply_zone_change_mock.assert_called_once()
             zone_delete_mock.assert_called_once_with(zone_names_to_delete)
-            cfg_save_mock.assert_called_once()
             activate_zs_mock.assert_called_once()
 
     @patch.object(BrcdFCZoneClientCLI, '_get_switch_info')
     def test_get_nameserver_info(self, get_switch_info_mock):
         ns_info_list = []
-        ns_info_list_expected = ['20:1a:00:05:1e:e8:e3:29',
-                                 '20:1a:00:05:1e:e8:e3:29']
+        ns_info_list_expected = ['20:1a:00:05:1e:e8:e3:29']
         get_switch_info_mock.return_value = (switch_data)
         ns_info_list = self.get_nameserver_info()
         self.assertEqual(ns_info_list, ns_info_list_expected)
index 9ca645ea9ad14de44426d18be7500d87d5b448d2..091fa44326dcba5bdd999ce7d1a4ae2542603e16 100644 (file)
@@ -19,6 +19,7 @@
 
 """Unit tests for Brocade fc zone driver."""
 
+import mock
 import paramiko
 
 from oslo.config import cfg
@@ -28,6 +29,8 @@ from cinder.openstack.common import importutils
 from cinder.openstack.common import log as logging
 from cinder import test
 from cinder.volume import configuration as conf
+from cinder.zonemanager.drivers.brocade.brcd_fc_zone_driver \
+    import BrcdFCZoneDriver
 
 LOG = logging.getLogger(__name__)
 
@@ -109,45 +112,47 @@ class TestBrcdFcZoneDriver(BrcdFcZoneDriverBaseTest, test.TestCase):
             'cinder.zonemanager.drivers.brocade.brcd_fc_zone_driver'
             '.BrcdFCZoneDriver', configuration=config)
 
-    def fake_get_active_zone_set(self, fabric_ip, fabric_user, fabric_pwd):
+    def fake__get_active_zone_set(self, brcd_sb_connector, fabric_ip):
         return GlobalVars._active_cfg
 
     def fake_get_san_context(self, target_wwn_list):
         fabric_map = {}
         return fabric_map
 
-    def test_add_connection(self):
+    @mock.patch.object(BrcdFCZoneDriver, '_get_active_zone_set')
+    def test_add_connection(self, get_active_zs_mock):
         """Normal flow for i-t mode."""
-        GlobalVars._active_cfg = _active_cfg_before_add
         GlobalVars._is_normal_test = True
         GlobalVars._zone_state = []
-        LOG.info(_("In Add GlobalVars._active_cfg:"
-                   " %s"), GlobalVars._active_cfg)
         LOG.info(_("In Add GlobalVars._is_normal_test: "
                    "%s"), GlobalVars._is_normal_test)
         LOG.info(_("In Add GlobalVars._zone_state:"
                    " %s"), GlobalVars._zone_state)
+        get_active_zs_mock.return_value = _active_cfg_before_add
         self.driver.add_connection('BRCD_FAB_1', _initiator_target_map)
         self.assertTrue(_zone_name in GlobalVars._zone_state)
 
-    def test_delete_connection(self):
+    @mock.patch.object(BrcdFCZoneDriver, '_get_active_zone_set')
+    def test_delete_connection(self, get_active_zs_mock):
         GlobalVars._is_normal_test = True
-        GlobalVars._active_cfg = _active_cfg_before_delete
+        get_active_zs_mock.return_value = _active_cfg_before_delete
         self.driver.delete_connection(
             'BRCD_FAB_1', _initiator_target_map)
         self.assertFalse(_zone_name in GlobalVars._zone_state)
 
-    def test_add_connection_for_initiator_mode(self):
+    @mock.patch.object(BrcdFCZoneDriver, '_get_active_zone_set')
+    def test_add_connection_for_initiator_mode(self, get_active_zs_mock):
         """Normal flow for i mode."""
         GlobalVars._is_normal_test = True
-        GlobalVars._active_cfg = _active_cfg_before_add
+        get_active_zs_mock.return_value = _active_cfg_before_add
         self.setup_driver(self.setup_config(True, 2))
         self.driver.add_connection('BRCD_FAB_1', _initiator_target_map)
         self.assertTrue(_zone_name in GlobalVars._zone_state)
 
-    def test_delete_connection_for_initiator_mode(self):
+    @mock.patch.object(BrcdFCZoneDriver, '_get_active_zone_set')
+    def test_delete_connection_for_initiator_mode(self, get_active_zs_mock):
         GlobalVars._is_normal_test = True
-        GlobalVars._active_cfg = _active_cfg_before_delete
+        get_active_zs_mock.return_value = _active_cfg_before_delete
         self.setup_driver(self.setup_config(True, 2))
         self.driver.delete_connection(
             'BRCD_FAB_1', _initiator_target_map)
@@ -178,6 +183,7 @@ class FakeBrcdFCZoneClientCLI(object):
     def __init__(self, ipaddress, username, password, port):
         LOG.info(_("User: %s"), username)
         LOG.info(_("_zone_state: %s"), GlobalVars._zone_state)
+        self.firmware_supported = True
         if not GlobalVars._is_normal_test:
             raise paramiko.SSHException("Unable to connect to fabric")
 
@@ -185,10 +191,10 @@ class FakeBrcdFCZoneClientCLI(object):
         LOG.debug("Inside get_active_zone_set %s", GlobalVars._active_cfg)
         return GlobalVars._active_cfg
 
-    def add_zones(self, zones, isActivate):
+    def add_zones(self, zones, isActivate, active_zone_set):
         GlobalVars._zone_state.extend(zones.keys())
 
-    def delete_zones(self, zone_names, isActivate):
+    def delete_zones(self, zone_names, isActivate, active_zone_set):
         zone_list = zone_names.split(';')
         GlobalVars._zone_state = [
             x for x in GlobalVars._zone_state if x not in zone_list]
index 656630f5079c23172788ad43afd7f4796d237744..7d04ab23de818e06786d486dcb85027cdda97104 100644 (file)
@@ -48,6 +48,9 @@ class TestFCZoneManager(test.TestCase):
                        fake_build_driver)
 
         self.zm = fc_zone_manager.ZoneManager(configuration=config)
+        self.configuration = conf.Configuration(None)
+        self.configuration.fc_fabric_names = fabric_name
+        self.driver = Mock(FCZoneDriver)
 
     def __init__(self, *args, **kwargs):
         test.TestCase.__init__(self, *args, **kwargs)
index bfd0863b802195505299fa765c46dda00cada37e..95cb7a5b7dab3d61b766e6a3dcba08e233d302ce 100644 (file)
@@ -113,7 +113,7 @@ class BrcdFCZoneClientCLI(object):
         switch_data = None
         return zone_set
 
-    def add_zones(self, zones, activate):
+    def add_zones(self, zones, activate, active_zone_set=None):
         """Add zone configuration.
 
         This method will add the zone configuration passed by user.
@@ -126,22 +126,24 @@ class BrcdFCZoneClientCLI(object):
                     ['50:06:0b:00:00:c2:66:04', '20:19:00:05:1e:e8:e3:29']
                 }
             activate - True/False
+            active_zone_set - active zone set dict retrieved from
+                              get_active_zone_set method
         """
         LOG.debug("Add Zones - Zones passed: %s", zones)
         cfg_name = None
         iterator_count = 0
         zone_with_sep = ''
-        active_zone_set = self.get_active_zone_set()
-        LOG.debug("Active zone set:%s", active_zone_set)
+        if not active_zone_set:
+            active_zone_set = self.get_active_zone_set()
+            LOG.debug("Active zone set:%s", active_zone_set)
         zone_list = active_zone_set[ZoneConstant.CFG_ZONES]
         LOG.debug("zone list:%s", zone_list)
         for zone in zones.keys():
             # if zone exists, its an update. Delete & insert
             # TODO(skolathur): This can be optimized to an update call later
-            LOG.debug("Update call")
             if (zone in zone_list):
                 try:
-                    self.delete_zones(zone, activate)
+                    self.delete_zones(zone, activate, active_zone_set)
                 except exception.BrocadeZoningCliException:
                     with excutils.save_and_reraise_exception():
                         LOG.error(_("Deleting zone failed %s"), zone)
@@ -171,9 +173,10 @@ class BrcdFCZoneClientCLI(object):
                     % {'zoneset': cfg_name, 'zones': zone_with_sep}
             LOG.debug("New zone %s", cmd)
             self.apply_zone_change(cmd.split())
-            self._cfg_save()
             if activate:
                 self.activate_zoneset(cfg_name)
+            else:
+                self._cfg_save()
         except Exception as e:
             self._cfg_trans_abort()
             msg = _("Creating and activating zone set failed: "
@@ -191,18 +194,20 @@ class BrcdFCZoneClientCLI(object):
         """Method to deActivate the zone config."""
         return self._ssh_execute([ZoneConstant.DEACTIVATE_ZONESET], True, 1)
 
-    def delete_zones(self, zone_names, activate):
+    def delete_zones(self, zone_names, activate, active_zone_set=None):
         """Delete zones from fabric.
 
         Method to delete the active zone config zones
 
         params zone_names: zoneNames separated by semicolon
         params activate: True/False
+        params active_zone_set: the active zone set dict retrieved
+                                from get_active_zone_set method
         """
         active_zoneset_name = None
-        active_zone_set = None
         zone_list = []
-        active_zone_set = self.get_active_zone_set()
+        if not active_zone_set:
+            active_zone_set = self.get_active_zone_set()
         active_zoneset_name = active_zone_set[
             ZoneConstant.ACTIVE_ZONE_CONFIG]
         zone_list = active_zone_set[ZoneConstant.CFG_ZONES]
@@ -213,7 +218,7 @@ class BrcdFCZoneClientCLI(object):
                 self.deactivate_zoneset()
                 cmd = 'cfgdelete "%(active_zoneset_name)s"' \
                     % {'active_zoneset_name': active_zoneset_name}
-                # Active zoneset is being deleted, hence reset is_active
+                # Active zoneset is being deleted, hence reset activate flag
                 activate = False
             else:
                 cmd = 'cfgremove "%(active_zoneset_name)s", "%(zone_names)s"' \
@@ -224,9 +229,10 @@ class BrcdFCZoneClientCLI(object):
             self.apply_zone_change(cmd.split())
             for zone in zones:
                 self._zone_delete(zone)
-            self._cfg_save()
             if activate:
                 self.activate_zoneset(active_zoneset_name)
+            else:
+                self._cfg_save()
         except Exception as e:
             msg = _("Deleting zones failed: (command=%(cmd)s error=%(err)s)."
                     ) % {'cmd': cmd, 'err': e}
@@ -243,21 +249,16 @@ class BrcdFCZoneClientCLI(object):
         cli_output = None
         return_list = []
         try:
-            cli_output = self._get_switch_info([ZoneConstant.NS_SHOW])
+            cmd = '%(nsshow)s;%(nscamshow)s' % {
+                'nsshow': ZoneConstant.NS_SHOW,
+                'nscamshow': ZoneConstant.NS_CAM_SHOW}
+            cli_output = self._get_switch_info([cmd])
         except exception.BrocadeZoningCliException:
             with excutils.save_and_reraise_exception():
                 LOG.error(_("Failed collecting nsshow "
                             "info for fabric %s"), self.switch_ip)
         if (cli_output):
             return_list = self._parse_ns_output(cli_output)
-        try:
-            cli_output = self._get_switch_info([ZoneConstant.NS_CAM_SHOW])
-        except exception.BrocadeZoningCliException:
-            with excutils.save_and_reraise_exception():
-                LOG.error(_("Failed collecting nscamshow "
-                            "info for fabric %s"), self.switch_ip)
-        if (cli_output):
-            return_list.extend(self._parse_ns_output(cli_output))
         cli_output = None
         return return_list
 
@@ -536,7 +537,6 @@ exit
                 channel.close()
             except Exception as e:
                 LOG.exception(e)
-            LOG.debug("_execute_cmd: stdout to return:%s" % stdout)
             LOG.debug("_execute_cmd: stderr to return:%s" % stderr)
         return (stdout, stderr)
 
index 6466eb311b36fb1b8a555a6b9d476a97b1121570..2da6b3eb8fd5ffa7c6e6ea8135d996b0b35da527 100644 (file)
@@ -61,12 +61,14 @@ class BrcdFCZoneDriver(FCZoneDriver):
 
     Version history:
         1.0 - Initial Brocade FC zone driver
+        1.1 - Implements performance enhancements
     """
 
-    VERSION = "1.0"
+    VERSION = "1.1"
 
     def __init__(self, **kwargs):
         super(BrcdFCZoneDriver, self).__init__(**kwargs)
+        self.sb_conn_map = {}
         self.configuration = kwargs.get('configuration', None)
         if self.configuration:
             self.configuration.append_config_values(brcd_opts)
@@ -133,10 +135,6 @@ class BrcdFCZoneDriver(FCZoneDriver):
         LOG.debug("Add connection for Fabric:%s", fabric)
         LOG.info(_("BrcdFCZoneDriver - Add connection "
                    "for I-T map: %s"), initiator_target_map)
-        fabric_ip = self.fabric_configs[fabric].safe_get('fc_fabric_address')
-        fabric_user = self.fabric_configs[fabric].safe_get('fc_fabric_user')
-        fabric_pwd = self.fabric_configs[fabric].safe_get('fc_fabric_password')
-        fabric_port = self.fabric_configs[fabric].safe_get('fc_fabric_port')
         zoning_policy = self.configuration.zoning_policy
         zoning_policy_fab = self.fabric_configs[fabric].safe_get(
             'zoning_policy')
@@ -144,29 +142,9 @@ class BrcdFCZoneDriver(FCZoneDriver):
             zoning_policy = zoning_policy_fab
 
         LOG.info(_("Zoning policy for Fabric %s"), zoning_policy)
-        cli_client = None
-        try:
-            cli_client = importutils.import_object(
-                self.configuration.brcd_sb_connector,
-                ipaddress=fabric_ip,
-                username=fabric_user,
-                password=fabric_pwd,
-                port=fabric_port)
-            if not cli_client.is_supported_firmware():
-                msg = _("Unsupported firmware on switch %s. Make sure "
-                        "switch is running firmware v6.4 or higher"
-                        ) % fabric_ip
-                LOG.error(msg)
-                raise exception.FCZoneDriverException(msg)
-        except exception.BrocadeZoningCliException as brocade_ex:
-            raise exception.FCZoneDriverException(brocade_ex)
-        except Exception as e:
-            LOG.error(e)
-            msg = _("Failed to add zoning configuration %s") % e
-            raise exception.FCZoneDriverException(msg)
+        cli_client = self._get_cli_client(fabric)
+        cfgmap_from_fabric = self._get_active_zone_set(cli_client)
 
-        cfgmap_from_fabric = self.get_active_zone_set(
-            fabric_ip, fabric_user, fabric_pwd, fabric_port)
         zone_names = []
         if cfgmap_from_fabric.get('zones'):
             zone_names = cfgmap_from_fabric['zones'].keys()
@@ -218,7 +196,8 @@ class BrcdFCZoneDriver(FCZoneDriver):
             if len(zone_map) > 0:
                 try:
                     cli_client.add_zones(
-                        zone_map, self.configuration.zone_activate)
+                        zone_map, self.configuration.zone_activate,
+                        cfgmap_from_fabric)
                     cli_client.cleanup()
                 except exception.BrocadeZoningCliException as brocade_ex:
                     raise exception.FCZoneDriverException(brocade_ex)
@@ -242,10 +221,6 @@ class BrcdFCZoneDriver(FCZoneDriver):
         LOG.debug("Delete connection for fabric:%s", fabric)
         LOG.info(_("BrcdFCZoneDriver - Delete connection for I-T map: %s"),
                  initiator_target_map)
-        fabric_ip = self.fabric_configs[fabric].safe_get('fc_fabric_address')
-        fabric_user = self.fabric_configs[fabric].safe_get('fc_fabric_user')
-        fabric_pwd = self.fabric_configs[fabric].safe_get('fc_fabric_password')
-        fabric_port = self.fabric_configs[fabric].safe_get('fc_fabric_port')
         zoning_policy = self.configuration.zoning_policy
         zoning_policy_fab = self.fabric_configs[fabric].safe_get(
             'zoning_policy')
@@ -253,29 +228,9 @@ class BrcdFCZoneDriver(FCZoneDriver):
             zoning_policy = zoning_policy_fab
 
         LOG.info(_("Zoning policy for fabric %s"), zoning_policy)
-        conn = None
-        try:
-            conn = importutils.import_object(
-                self.configuration.brcd_sb_connector,
-                ipaddress=fabric_ip,
-                username=fabric_user,
-                password=fabric_pwd,
-                port=fabric_port)
-            if not conn.is_supported_firmware():
-                msg = _("Unsupported firmware on switch %s. Make sure "
-                        "switch is running firmware v6.4 or higher"
-                        ) % fabric_ip
-                LOG.error(msg)
-                raise exception.FCZoneDriverException(msg)
-        except exception.BrocadeZoningCliException as brocade_ex:
-            raise exception.FCZoneDriverException(brocade_ex)
-        except Exception as e:
-            LOG.error(e)
-            msg = _("Failed to delete zoning configuration %s") % e
-            raise exception.FCZoneDriverException(msg)
+        conn = self._get_cli_client(fabric)
+        cfgmap_from_fabric = self._get_active_zone_set(conn)
 
-        cfgmap_from_fabric = self.get_active_zone_set(
-            fabric_ip, fabric_user, fabric_pwd, fabric_port)
         zone_names = []
         if cfgmap_from_fabric.get('zones'):
             zone_names = cfgmap_from_fabric['zones'].keys()
@@ -301,8 +256,8 @@ class BrcdFCZoneDriver(FCZoneDriver):
                     LOG.debug("Zone name to del: %s", zone_name)
                     if len(zone_names) > 0 and (zone_name in zone_names):
                         # delete zone.
-                        LOG.debug(("Added zone to delete to "
-                                   "list: %s"), zone_name)
+                        LOG.debug("Added zone to delete to "
+                                  "list: %s", zone_name)
                         zones_to_delete.append(zone_name)
 
             elif zoning_policy == 'initiator':
@@ -344,7 +299,8 @@ class BrcdFCZoneDriver(FCZoneDriver):
                 # Update zone membership.
                 if zone_map:
                     conn.add_zones(
-                        zone_map, self.configuration.zone_activate)
+                        zone_map, self.configuration.zone_activate,
+                        cfgmap_from_fabric)
                 # Delete zones ~sk.
                 if zones_to_delete:
                     zone_name_string = ''
@@ -359,7 +315,8 @@ class BrcdFCZoneDriver(FCZoneDriver):
                                 zone_name_string, ';', zones_to_delete[i])
 
                     conn.delete_zones(
-                        zone_name_string, self.configuration.zone_activate)
+                        zone_name_string, self.configuration.zone_activate,
+                        cfgmap_from_fabric)
                 conn.cleanup()
             except Exception as e:
                 LOG.error(e)
@@ -385,34 +342,7 @@ class BrcdFCZoneDriver(FCZoneDriver):
             LOG.debug("Formatted Target wwn List:"
                       " %s", formatted_target_list)
             for fabric_name in fabrics:
-                fabric_ip = self.fabric_configs[fabric_name].safe_get(
-                    'fc_fabric_address')
-                fabric_user = self.fabric_configs[fabric_name].safe_get(
-                    'fc_fabric_user')
-                fabric_pwd = self.fabric_configs[fabric_name].safe_get(
-                    'fc_fabric_password')
-                fabric_port = self.fabric_configs[fabric_name].safe_get(
-                    'fc_fabric_port')
-                conn = None
-                try:
-                    conn = importutils.import_object(
-                        self.configuration.brcd_sb_connector,
-                        ipaddress=fabric_ip,
-                        username=fabric_user,
-                        password=fabric_pwd,
-                        port=fabric_port)
-                    if not conn.is_supported_firmware():
-                        msg = _("Unsupported firmware on switch %s. Make sure "
-                                "switch is running firmware v6.4 or higher"
-                                ) % fabric_ip
-                        LOG.error(msg)
-                        raise exception.FCZoneDriverException(msg)
-                except exception.BrocadeZoningCliException as brocade_ex:
-                    raise exception.FCZoneDriverException(brocade_ex)
-                except Exception as e:
-                    LOG.error(e)
-                    msg = _("Failed to get SAN context %s") % e
-                    raise exception.FCZoneDriverException(msg)
+                conn = self._get_cli_client(fabric_name)
 
                 # Get name server data from fabric and get the targets
                 # logged in.
@@ -422,6 +352,12 @@ class BrcdFCZoneDriver(FCZoneDriver):
                     LOG.debug("name server info from fabric:%s", nsinfo)
                     conn.cleanup()
                 except exception.BrocadeZoningCliException as ex:
+                    if not conn.is_supported_firmware():
+                        msg = _("Unsupported firmware on switch %s. Make sure "
+                                "switch is running firmware v6.4 or higher"
+                                ) % conn.switch_ip
+                        LOG.error(msg)
+                        raise exception.FCZoneDriverException(msg)
                     with excutils.save_and_reraise_exception():
                         LOG.error(_("Error getting name server "
                                     "info: %s"), ex)
@@ -447,31 +383,43 @@ class BrcdFCZoneDriver(FCZoneDriver):
         LOG.debug("Return SAN context output:%s", fabric_map)
         return fabric_map
 
-    def get_active_zone_set(self, fabric_ip,
-                            fabric_user, fabric_pwd, fabric_port):
-        """Gets active zone config from fabric."""
-        cfgmap = {}
-        conn = None
+    def _get_active_zone_set(self, conn):
+        cfgmap = None
         try:
-            LOG.debug("Southbound connector:"
-                      " %s", self.configuration.brcd_sb_connector)
-            conn = importutils.import_object(
-                self.configuration.brcd_sb_connector,
-                ipaddress=fabric_ip, username=fabric_user,
-                password=fabric_pwd, port=fabric_port)
+            cfgmap = conn.get_active_zone_set()
+        except exception.BrocadeZoningCliException:
             if not conn.is_supported_firmware():
                 msg = _("Unsupported firmware on switch %s. Make sure "
                         "switch is running firmware v6.4 or higher"
-                        ) % fabric_ip
+                        ) % conn.switch_ip
                 LOG.error(msg)
                 raise exception.FCZoneDriverException(msg)
-            cfgmap = conn.get_active_zone_set()
-            conn.cleanup()
-        except exception.BrocadeZoningCliException as brocade_ex:
-            raise exception.FCZoneDriverException(brocade_ex)
         except Exception as e:
-            msg = (_("Failed to access active zoning configuration:%s") % e)
-            LOG.error(msg)
+            LOG.error(e)
+            msg = _("Failed to retrieve active zoning configuration %s") % e
             raise exception.FCZoneDriverException(msg)
         LOG.debug("Active zone set from fabric: %s", cfgmap)
         return cfgmap
+
+    def _get_cli_client(self, fabric):
+        fabric_ip = self.fabric_configs[fabric].safe_get('fc_fabric_address')
+        fabric_user = self.fabric_configs[fabric].safe_get('fc_fabric_user')
+        fabric_pwd = self.fabric_configs[fabric].safe_get('fc_fabric_password')
+        fabric_port = self.fabric_configs[fabric].safe_get('fc_fabric_port')
+        cli_client = None
+        try:
+            cli_client = self.sb_conn_map.get(fabric_ip)
+            if not cli_client:
+                LOG.debug("CLI client not found, creating for %s", fabric_ip)
+                cli_client = importutils.import_object(
+                    self.configuration.brcd_sb_connector,
+                    ipaddress=fabric_ip,
+                    username=fabric_user,
+                    password=fabric_pwd,
+                    port=fabric_port)
+                self.sb_conn_map[fabric_ip] = cli_client
+        except Exception as e:
+            LOG.error(e)
+            msg = _("Failed to create sb connector for %s") % fabric_ip
+            raise exception.FCZoneDriverException(msg)
+        return cli_client