]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Adds friendly zone name support
authorAngela Smith <aallen@brocade.com>
Mon, 9 Nov 2015 18:14:35 +0000 (10:14 -0800)
committerAngela Smith <aallen@brocade.com>
Fri, 22 Jan 2016 23:59:46 +0000 (15:59 -0800)
Added user friendly names for zones to include host and storage
names along with ids to easily identify the host and storage port
details.

This is done by extracting the host and storage name from connection
info object in the zone manager. The host and storage names are passed
to the zone drivers to form a friendly name. The method signature has
been changed which accepts host and storage name, with default as None.

Also added test cases to test this support. Changes have been made to
zone manager test code to accommodate the change in signature of some
methods.

Moved get_friendly_zone_name method to utils.py so that it can be used
by both cisco and brocade drivers

Changed cisco driver to accommodate host_name and storage_system
parameters in add/delete connection.

Implements: blueprint brocade-zone-driver-friendly-zone-names

Change-Id: I350493b96901675a1b8910d6104f31c7d677ebda

13 files changed:
cinder/tests/unit/zonemanager/test_driverutils.py [new file with mode: 0644]
cinder/tests/unit/zonemanager/test_fc_zone_manager.py
cinder/tests/unit/zonemanager/test_volume_driver.py
cinder/zonemanager/drivers/brocade/brcd_fabric_opts.py
cinder/zonemanager/drivers/brocade/brcd_fc_zone_driver.py
cinder/zonemanager/drivers/brocade/fc_zone_constants.py
cinder/zonemanager/drivers/cisco/cisco_fc_zone_driver.py
cinder/zonemanager/drivers/driver_utils.py [new file with mode: 0644]
cinder/zonemanager/drivers/fc_zone_driver.py
cinder/zonemanager/fc_zone_manager.py
cinder/zonemanager/fczm_constants.py [new file with mode: 0644]
cinder/zonemanager/utils.py
releasenotes/notes/friendly-zone-names-d5e131d356040de0.yaml [new file with mode: 0644]

diff --git a/cinder/tests/unit/zonemanager/test_driverutils.py b/cinder/tests/unit/zonemanager/test_driverutils.py
new file mode 100644 (file)
index 0000000..bb5d34d
--- /dev/null
@@ -0,0 +1,113 @@
+#    (c) Copyright 2015 Brocade Communications Systems Inc.
+#    All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+
+"""Unit tests for friendly zone name."""
+import ddt
+import string
+
+from cinder import test
+from cinder.zonemanager.drivers import driver_utils
+
+TEST_CHAR_SET = string.ascii_letters + string.digits
+
+
+@ddt.ddt
+class TestDriverUtils(test.TestCase):
+
+    @ddt.data('OSHost10010008c7cff523b01AMCEArray20240002ac000a50')
+    def test_get_friendly_zone_name_valid_hostname_storagesystem(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50", "OS_Host100", 'AMCE'
+                             '_Array', "openstack", TEST_CHAR_SET))
+
+    @ddt.data('openstack10008c7cff523b0120240002ac000a50')
+    def test_get_friendly_zone_name_hostname_storagesystem_none(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50", None, None,
+                             "openstack", TEST_CHAR_SET))
+
+    @ddt.data('openstack10008c7cff523b0120240002ac000a50')
+    def test_get_friendly_zone_name_storagesystem_none(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50", "OS_Host100", None,
+                             "openstack", TEST_CHAR_SET))
+
+    @ddt.data('openstack10008c7cff523b0120240002ac000a50')
+    def test_get_friendly_zone_name_hostname_none(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50", None, "AMCE_Array",
+                             "openstack", TEST_CHAR_SET))
+
+    @ddt.data('OSHost10010008c7cff523b01')
+    def test_get_friendly_zone_name_initiator_mode(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator', "10:00:8c:7c:ff:52:3b:01", None,
+                             "OS_Host100", None, "openstack", TEST_CHAR_SET))
+
+    @ddt.data('openstack10008c7cff523b01')
+    def test_get_friendly_zone_name_initiator_mode_hostname_none(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator', "10:00:8c:7c:ff:52:3b:01", None,
+                             None, None, "openstack", TEST_CHAR_SET))
+
+    @ddt.data('OSHost100XXXX10008c7cff523b01AMCEArrayYYYY20240002ac000a50')
+    def test_get_friendly_zone_name_storagename_length_too_long(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50",
+                             "OS_Host100XXXXXXXXXX",
+                             "AMCE_ArrayYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
+                             "YYYY", "openstack", TEST_CHAR_SET))
+
+    @ddt.data('OSHost100XXXX10008c7cff523b01AMCEArrayYYYY20240002ac000a50')
+    def test_get_friendly_zone_name_max_length(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50",
+                             "OS_Host100XXXXXXXXXX",
+                             "AMCE_ArrayYYYYYYYYYY",
+                             "openstack", TEST_CHAR_SET))
+
+    @ddt.data('OSHost100XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX10008c7cff523b01')
+    def test_get_friendly_zone_name_initiator_mode_hostname_max_length(self,
+                                                                       value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator', "10:00:8c:7c:ff:52:3b:01", None,
+                             'OS_Host100XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
+                             'XXXXX',
+                             None, "openstack", TEST_CHAR_SET))
+
+    @ddt.data('openstack110008c7cff523b0120240002ac000a50')
+    def test_get_friendly_zone_name_invalid_characters(self, value):
+        self.assertEqual(value,
+                         driver_utils.get_friendly_zone_name(
+                             'initiator-target', "10:00:8c:7c:ff:52:3b:01",
+                             "20:24:00:02:ac:00:0a:50", None, "AMCE_Array",
+                             "open-stack*1_", TEST_CHAR_SET))
index 6ec6d93a24d577045d01c2444e73d0b8450aab2e..c2072941a3f8c6ffc0b1bfb6ab19c4ca9e37ef35 100644 (file)
@@ -29,6 +29,17 @@ from cinder.zonemanager import fc_zone_manager
 
 fabric_name = 'BRCD_FAB_3'
 init_target_map = {'10008c7cff523b01': ['20240002ac000a50']}
+conn_info = {
+    'driver_volume_type': 'fibre_channel',
+    'data': {
+        'target_discovered': True,
+        'target_lun': 1,
+        'target_wwn': '20240002ac000a50',
+        'initiator_target_map': {
+            '10008c7cff523b01': ['20240002ac000a50']
+        }
+    }
+}
 fabric_map = {'BRCD_FAB_3': ['20240002ac000a50']}
 target_list = ['20240002ac000a50']
 
@@ -60,10 +71,12 @@ class TestFCZoneManager(test.TestCase):
         with mock.patch.object(self.zm.driver, 'add_connection')\
                 as add_connection_mock:
             self.zm.driver.get_san_context.return_value = fabric_map
-            self.zm.add_connection(init_target_map)
+            self.zm.add_connection(conn_info)
             self.zm.driver.get_san_context.assert_called_once_with(target_list)
             add_connection_mock.assert_called_once_with(fabric_name,
-                                                        init_target_map)
+                                                        init_target_map,
+                                                        None,
+                                                        None)
 
     @mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
     def test_add_connection_error(self, opt_mock):
@@ -71,17 +84,19 @@ class TestFCZoneManager(test.TestCase):
                 as add_connection_mock:
             add_connection_mock.side_effect = exception.FCZoneDriverException
             self.assertRaises(exception.ZoneManagerException,
-                              self.zm.add_connection, init_target_map)
+                              self.zm.add_connection, conn_info)
 
     @mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
     def test_delete_connection(self, opt_mock):
         with mock.patch.object(self.zm.driver, 'delete_connection')\
                 as delete_connection_mock:
             self.zm.driver.get_san_context.return_value = fabric_map
-            self.zm.delete_connection(init_target_map)
+            self.zm.delete_connection(conn_info)
             self.zm.driver.get_san_context.assert_called_once_with(target_list)
             delete_connection_mock.assert_called_once_with(fabric_name,
-                                                           init_target_map)
+                                                           init_target_map,
+                                                           None,
+                                                           None)
 
     @mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
     def test_delete_connection_error(self, opt_mock):
@@ -89,4 +104,4 @@ class TestFCZoneManager(test.TestCase):
                 as del_connection_mock:
             del_connection_mock.side_effect = exception.FCZoneDriverException
             self.assertRaises(exception.ZoneManagerException,
-                              self.zm.delete_connection, init_target_map)
+                              self.zm.delete_connection, conn_info)
index f68f39defc363de2e90d9e838423eaab3b398b06..fb7e296c12272cd8994166f76e3cfac017e4300a 100644 (file)
@@ -53,8 +53,7 @@ class TestVolumeDriver(test.TestCase):
                     as mock_safe_get:
                 mock_safe_get.return_value = 'fabric'
                 conn_info = self.driver.initialize_connection(None, None)
-                init_target_map = conn_info['data']['initiator_target_map']
-                add_zone_mock.assert_called_once_with(init_target_map)
+                add_zone_mock.assert_called_once_with(conn_info)
 
     @mock.patch.object(utils, 'require_driver_initialized')
     def test_initialize_connection_no_decorator(self, utils_mock):
@@ -77,8 +76,7 @@ class TestVolumeDriver(test.TestCase):
                     as mock_safe_get:
                 mock_safe_get.return_value = 'fabric'
                 conn_info = self.driver.terminate_connection(None, None)
-                init_target_map = conn_info['data']['initiator_target_map']
-                remove_zone_mock.assert_called_once_with(init_target_map)
+                remove_zone_mock.assert_called_once_with(conn_info)
 
     @mock.patch.object(utils, 'require_driver_initialized')
     def test_terminate_connection_no_decorator(self, utils_mock):
index 1328bb1ba776339651569c1a96ba178372e76758..c6bb348273cbfca5f81d9697c614e24192dd6338 100644 (file)
@@ -41,6 +41,7 @@ brcd_zone_opts = [
                 default=True,
                 help='overridden zoning activation state'),
     cfg.StrOpt('zone_name_prefix',
+               default='openstack',
                help='overridden zone name prefix'),
     cfg.StrOpt('principal_switch_wwn',
                help='Principal switch WWN of the fabric'),
@@ -55,7 +56,8 @@ def load_fabric_configurations(fabric_names):
     fabric_configs = {}
     for fabric_name in fabric_names:
         config = configuration.Configuration(brcd_zone_opts, fabric_name)
-        LOG.debug("Loaded FC fabric config %s", fabric_name)
+        LOG.debug("Loaded FC fabric config %(fabricname)s",
+                  {'fabricname': fabric_name})
         fabric_configs[fabric_name] = config
 
     return fabric_configs
index e865ea0b833692f43217184c7c6e8c1c47c8461a..93b143855eafd5aca27ec3f5a857afea91860db3 100644 (file)
@@ -36,14 +36,17 @@ from oslo_log import log as logging
 from oslo_utils import excutils
 from oslo_utils import importutils
 import six
+import string
 
 from cinder import exception
-from cinder.i18n import _, _LE, _LI
+from cinder.i18n import _, _LE, _LI, _LW
 from cinder.zonemanager.drivers.brocade import brcd_fabric_opts as fabric_opts
+from cinder.zonemanager.drivers import driver_utils
 from cinder.zonemanager.drivers import fc_zone_driver
 
 LOG = logging.getLogger(__name__)
 
+SUPPORTED_CHARS = string.ascii_letters + string.digits + '_'
 brcd_opts = [
     cfg.StrOpt('brcd_sb_connector',
                default='cinder.zonemanager.drivers.brocade'
@@ -64,9 +67,10 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
     Version history:
         1.0 - Initial Brocade FC zone driver
         1.1 - Implements performance enhancements
+        1.2 - Added support for friendly zone name
     """
 
-    VERSION = "1.1"
+    VERSION = "1.2"
 
     def __init__(self, **kwargs):
         super(BrcdFCZoneDriver, self).__init__(**kwargs)
@@ -74,8 +78,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         self.configuration = kwargs.get('configuration', None)
         if self.configuration:
             self.configuration.append_config_values(brcd_opts)
-            # Adding a hack to hendle parameters from super classes
-            # in case configured with multi backend.
+            # Adding a hack to handle parameters from super classes
+            # in case configured with multiple back ends.
             fabric_names = self.configuration.safe_get('fc_fabric_names')
             base_san_opts = []
             if not fabric_names:
@@ -109,7 +113,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                 [wwn_str[i:i + 2] for i in range(0, len(wwn_str), 2)])
 
     @lockutils.synchronized('brcd', 'fcfabric-', True)
-    def add_connection(self, fabric, initiator_target_map):
+    def add_connection(self, fabric, initiator_target_map, host_name=None,
+                       storage_system=None):
         """Concrete implementation of add_connection.
 
         Based on zoning policy and state of each I-T pair, list of zone
@@ -121,22 +126,27 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         :param fabric: Fabric name from cinder.conf file
         :param initiator_target_map: Mapping of initiator to list of targets
         """
-        LOG.debug("Add connection for Fabric: %s", fabric)
-        LOG.info(_LI("BrcdFCZoneDriver - Add connection "
-                     "for I-T map: %s"), initiator_target_map)
+        LOG.info(_LI("BrcdFCZoneDriver - Add connection for fabric "
+                     "%(fabric)s for I-T map: %(i_t_map)s"),
+                 {'fabric': fabric,
+                  'i_t_map': initiator_target_map})
         zoning_policy = self.configuration.zoning_policy
         zoning_policy_fab = self.fabric_configs[fabric].safe_get(
             'zoning_policy')
-        if zoning_policy_fab:
-            zoning_policy = zoning_policy_fab
         zone_name_prefix = self.fabric_configs[fabric].safe_get(
             'zone_name_prefix')
-        if not zone_name_prefix:
-            zone_name_prefix = 'openstack'
         zone_activate = self.fabric_configs[fabric].safe_get(
             'zone_activate')
+        if zoning_policy_fab:
+            zoning_policy = zoning_policy_fab
+        LOG.info(_LI("Zoning policy for Fabric %(policy)s"),
+                 {'policy': zoning_policy})
+        if (zoning_policy != 'initiator'
+                and zoning_policy != 'initiator-target'):
+            LOG.info(_LI("Zoning policy is not valid, "
+                         "no zoning will be performed."))
+            return
 
-        LOG.info(_LI("Zoning policy for Fabric %s"), zoning_policy)
         cli_client = self._get_cli_client(fabric)
         cfgmap_from_fabric = self._get_active_zone_set(cli_client)
 
@@ -154,24 +164,37 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     target = t.lower()
                     zone_members = [self.get_formatted_wwn(initiator),
                                     self.get_formatted_wwn(target)]
-                    zone_name = (zone_name_prefix
-                                 + initiator.replace(':', '')
-                                 + target.replace(':', ''))
+                    zone_name = driver_utils.get_friendly_zone_name(
+                        zoning_policy,
+                        initiator,
+                        target,
+                        host_name,
+                        storage_system,
+                        zone_name_prefix,
+                        SUPPORTED_CHARS)
                     if (
                         len(cfgmap_from_fabric) == 0 or (
                             zone_name not in zone_names)):
                         zone_map[zone_name] = zone_members
                     else:
                         # This is I-T zoning, skip if zone already exists.
-                        LOG.info(_LI("Zone exists in I-T mode. "
-                                     "Skipping zone creation %s"), zone_name)
+                        LOG.info(_LI("Zone exists in I-T mode. Skipping "
+                                     "zone creation for %(zonename)s"),
+                                 {'zonename': zone_name})
             elif zoning_policy == 'initiator':
                 zone_members = [self.get_formatted_wwn(initiator)]
                 for t in t_list:
                     target = t.lower()
                     zone_members.append(self.get_formatted_wwn(target))
 
-                zone_name = zone_name_prefix + initiator.replace(':', '')
+                zone_name = driver_utils.get_friendly_zone_name(
+                    zoning_policy,
+                    initiator,
+                    target,
+                    host_name,
+                    storage_system,
+                    zone_name_prefix,
+                    SUPPORTED_CHARS)
 
                 if len(zone_names) > 0 and (zone_name in zone_names):
                     zone_members = zone_members + filter(
@@ -179,13 +202,9 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                         cfgmap_from_fabric['zones'][zone_name])
 
                 zone_map[zone_name] = zone_members
-            else:
-                msg = _("Zoning Policy: %s, not "
-                        "recognized") % zoning_policy
-                LOG.error(msg)
-                raise exception.FCZoneDriverException(msg)
 
-            LOG.info(_LI("Zone map to add: %s"), zone_map)
+            LOG.info(_LI("Zone map to add: %(zonemap)s"),
+                     {'zonemap': zone_map})
 
             if len(zone_map) > 0:
                 try:
@@ -199,10 +218,12 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     msg = _("Failed to add zoning configuration.")
                     LOG.exception(msg)
                     raise exception.FCZoneDriverException(msg)
-            LOG.debug("Zones added successfully: %s", zone_map)
+            LOG.debug("Zones added successfully: %(zonemap)s",
+                      {'zonemap': zone_map})
 
     @lockutils.synchronized('brcd', 'fcfabric-', True)
-    def delete_connection(self, fabric, initiator_target_map):
+    def delete_connection(self, fabric, initiator_target_map, host_name=None,
+                          storage_system=None):
         """Concrete implementation of delete_connection.
 
         Based on zoning policy and state of each I-T pair, list of zones
@@ -212,22 +233,21 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         :param fabric: Fabric name from cinder.conf file
         :param initiator_target_map: Mapping of initiator to list of targets
         """
-        LOG.debug("Delete connection for fabric: %s", fabric)
-        LOG.info(_LI("BrcdFCZoneDriver - Delete connection for I-T map: %s"),
-                 initiator_target_map)
+        LOG.info(_LI("BrcdFCZoneDriver - Delete connection for fabric "
+                 "%(fabric)s for I-T map: %(i_t_map)s"),
+                 {'fabric': fabric,
+                  'i_t_map': initiator_target_map})
         zoning_policy = self.configuration.zoning_policy
         zoning_policy_fab = self.fabric_configs[fabric].safe_get(
             'zoning_policy')
-        if zoning_policy_fab:
-            zoning_policy = zoning_policy_fab
         zone_name_prefix = self.fabric_configs[fabric].safe_get(
             'zone_name_prefix')
-        if not zone_name_prefix:
-            zone_name_prefix = 'openstack'
         zone_activate = self.fabric_configs[fabric].safe_get(
             'zone_activate')
-
-        LOG.info(_LI("Zoning policy for fabric %s"), zoning_policy)
+        if zoning_policy_fab:
+            zoning_policy = zoning_policy_fab
+        LOG.info(_LI("Zoning policy for fabric %(policy)s"),
+                 {'policy': zoning_policy})
         conn = self._get_cli_client(fabric)
         cfgmap_from_fabric = self._get_active_zone_set(conn)
 
@@ -238,7 +258,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         # Based on zoning policy, get zone member list and push changes to
         # fabric. This operation could result in an update for zone config
         # with new member list or deleting zones from active cfg.
-        LOG.debug("zone config from Fabric: %s", cfgmap_from_fabric)
+        LOG.debug("zone config from Fabric: %(cfgmap)s",
+                  {'cfgmap': cfgmap_from_fabric})
         for initiator_key in initiator_target_map.keys():
             initiator = initiator_key.lower()
             formatted_initiator = self.get_formatted_wwn(initiator)
@@ -249,15 +270,20 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                 # In this case, zone needs to be deleted.
                 for t in t_list:
                     target = t.lower()
-                    zone_name = (
-                        zone_name_prefix
-                        + initiator.replace(':', '')
-                        + target.replace(':', ''))
-                    LOG.debug("Zone name to del: %s", zone_name)
+                    zone_name = driver_utils.get_friendly_zone_name(
+                        zoning_policy,
+                        initiator,
+                        target,
+                        host_name,
+                        storage_system,
+                        zone_name_prefix,
+                        SUPPORTED_CHARS)
+                    LOG.debug("Zone name to delete: %(zonename)s",
+                              {'zonename': 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: %(zonename)s",
+                                  {'zonename': zone_name})
                         zones_to_delete.append(zone_name)
 
             elif zoning_policy == 'initiator':
@@ -266,7 +292,14 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     target = t.lower()
                     zone_members.append(self.get_formatted_wwn(target))
 
-                zone_name = zone_name_prefix + initiator.replace(':', '')
+                zone_name = driver_utils.get_friendly_zone_name(
+                    zoning_policy,
+                    initiator,
+                    target,
+                    host_name,
+                    storage_system,
+                    zone_name_prefix,
+                    SUPPORTED_CHARS)
 
                 if (zone_names and (zone_name in zone_names)):
                     filtered_members = filter(
@@ -278,22 +311,25 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     # filtered list and if it is non-empty, add initiator
                     # to it and update zone if filtered list is empty, we
                     # remove that zone.
-                    LOG.debug("Zone delete - I mode: "
-                              "filtered targets: %s", filtered_members)
+                    LOG.debug("Zone delete - initiator mode: "
+                              "filtered targets: %(targets)s",
+                              {'targets': filtered_members})
                     if filtered_members:
                         filtered_members.append(formatted_initiator)
-                        LOG.debug("Filtered zone members to "
-                                  "update: %s", filtered_members)
+                        LOG.debug("Filtered zone members to update: "
+                                  "%(members)s", {'members': filtered_members})
                         zone_map[zone_name] = filtered_members
-                        LOG.debug("Filtered zone Map to "
-                                  "update: %s", zone_map)
+                        LOG.debug("Filtered zone map to update: %(zonemap)s",
+                                  {'zonemap': zone_map})
                     else:
                         zones_to_delete.append(zone_name)
             else:
-                LOG.info(_LI("Zoning Policy: %s, not "
-                             "recognized"), zoning_policy)
-            LOG.debug("Final Zone map to update: %s", zone_map)
-            LOG.debug("Final Zone list to delete: %s", zones_to_delete)
+                LOG.warning(_LW("Zoning policy not recognized: %(policy)s"),
+                            {'policy': zoning_policy})
+            LOG.debug("Final zone map to update: %(zonemap)s",
+                      {'zonemap': zone_map})
+            LOG.debug("Final zone list to delete: %(zones)s",
+                      {'zones': zones_to_delete})
             try:
                 # Update zone membership.
                 if zone_map:
@@ -333,13 +369,14 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         fabric_map = {}
         fc_fabric_names = self.configuration.fc_fabric_names
         fabrics = [x.strip() for x in fc_fabric_names.split(',')]
-        LOG.debug("Fabric List: %s", fabrics)
-        LOG.debug("Target wwn List: %s", target_wwn_list)
+        LOG.debug("Fabric List: %(fabrics)s", {'fabrics': fabrics})
+        LOG.debug("Target WWN list: %(targetwwns)s",
+                  {'targetwwns': target_wwn_list})
         if len(fabrics) > 0:
             for t in target_wwn_list:
                 formatted_target_list.append(self.get_formatted_wwn(t.lower()))
-            LOG.debug("Formatted Target wwn List:"
-                      " %s", formatted_target_list)
+            LOG.debug("Formatted target WWN list: %(targetlist)s",
+                      {'targetlist': formatted_target_list})
             for fabric_name in fabrics:
                 conn = self._get_cli_client(fabric_name)
 
@@ -348,7 +385,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                 nsinfo = None
                 try:
                     nsinfo = conn.get_nameserver_info()
-                    LOG.debug("name server info from fabric: %s", nsinfo)
+                    LOG.debug("Name server info from fabric: %(nsinfo)s",
+                              {'nsinfo': nsinfo})
                     conn.cleanup()
                 except exception.BrocadeZoningCliException:
                     if not conn.is_supported_firmware():
@@ -368,17 +406,19 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     nsinfo)
 
                 if visible_targets:
-                    LOG.info(_LI("Filtered targets for SAN is: %s"),
-                             {fabric_name: visible_targets})
+                    LOG.info(_LI("Filtered targets for SAN is: %(targets)s"),
+                             {'targets': visible_targets})
                     # getting rid of the ':' before returning
                     for idx, elem in enumerate(visible_targets):
                         visible_targets[idx] = str(
                             visible_targets[idx]).replace(':', '')
                     fabric_map[fabric_name] = visible_targets
                 else:
-                    LOG.debug("No targets are in the nameserver for SAN %s",
-                              fabric_name)
-        LOG.debug("Return SAN context output: %s", fabric_map)
+                    LOG.debug("No targets found in the nameserver "
+                              "for fabric: %(fabric)s",
+                              {'fabric': fabric_name})
+        LOG.debug("Return SAN context output: %(fabricmap)s",
+                  {'fabricmap': fabric_map})
         return fabric_map
 
     def _get_active_zone_set(self, conn):
@@ -396,7 +436,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
             msg = (_("Failed to retrieve active zoning configuration %s")
                    % six.text_type(e))
             raise exception.FCZoneDriverException(msg)
-        LOG.debug("Active zone set from fabric: %s", cfgmap)
+        LOG.debug("Active zone set from fabric: %(cfgmap)s",
+                  {'cfgmap': cfgmap})
         return cfgmap
 
     def _get_cli_client(self, fabric):
@@ -408,7 +449,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
         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)
+                LOG.debug("CLI client not found, creating for %(ip)s",
+                          {'ip': fabric_ip})
                 cli_client = importutils.import_object(
                     self.configuration.brcd_sb_connector,
                     ipaddress=fabric_ip,
index 3ef01cde11fe074512d03d8d2f8471ea03939413..1cc2372e58358acb58c98512732c413e045321e8 100644 (file)
@@ -16,7 +16,6 @@
 #    under the License.
 #
 
-
 """
 Common constants used by Brocade FC Zone Driver.
 """
index b94733ede4b6dd28cdb2a730ea9707761f39a9ce..597d66b2b3e78963acebd2ce2f53f0f5e0a5def5 100644 (file)
@@ -33,15 +33,18 @@ from oslo_log import log as logging
 from oslo_utils import excutils
 from oslo_utils import importutils
 import six
+import string
 
 from cinder import exception
 from cinder.i18n import _, _LE, _LI
 from cinder.zonemanager.drivers.cisco import cisco_fabric_opts as fabric_opts
+from cinder.zonemanager.drivers import driver_utils
 from cinder.zonemanager.drivers import fc_zone_driver
 from cinder.zonemanager import utils as zm_utils
 
 LOG = logging.getLogger(__name__)
 
+SUPPORTED_CHARS = string.ascii_letters + string.digits + '$' + '-' + '^' + '_'
 cisco_opts = [
     cfg.StrOpt('cisco_sb_connector',
                default='cinder.zonemanager.drivers.cisco'
@@ -61,9 +64,10 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
 
     Version history:
         1.0 - Initial Cisco FC zone driver
+        1.1 - Added friendly zone name support
     """
 
-    VERSION = "1.0.0"
+    VERSION = "1.1.0"
 
     def __init__(self, **kwargs):
         super(CiscoFCZoneDriver, self).__init__(**kwargs)
@@ -109,7 +113,8 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     fabric_names)
 
     @lockutils.synchronized('cisco', 'fcfabric-', True)
-    def add_connection(self, fabric, initiator_target_map):
+    def add_connection(self, fabric, initiator_target_map, host_name=None,
+                       storage_system=None):
         """Concrete implementation of add_connection.
 
         Based on zoning policy and state of each I-T pair, list of zone
@@ -165,10 +170,15 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                             zone_members = [
                                 zm_utils.get_formatted_wwn(initiator),
                                 zm_utils.get_formatted_wwn(target)]
-                            zone_name = (self.
-                                         configuration.cisco_zone_name_prefix
-                                         + initiator.replace(':', '')
-                                         + target.replace(':', ''))
+                            zone_name = (
+                                driver_utils.get_friendly_zone_name(
+                                    zoning_policy,
+                                    initiator,
+                                    target,
+                                    host_name,
+                                    storage_system,
+                                    self.configuration.cisco_zone_name_prefix,
+                                    SUPPORTED_CHARS))
                             if (len(cfgmap_from_fabric) == 0 or (
                                     zone_name not in zone_names)):
                                 zone_map[zone_name] = zone_members
@@ -185,8 +195,15 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                             zone_members.append(
                                 zm_utils.get_formatted_wwn(target))
 
-                        zone_name = self.configuration.cisco_zone_name_prefix \
-                            + initiator.replace(':', '')
+                        zone_name = (
+                            driver_utils.get_friendly_zone_name(
+                                zoning_policy,
+                                initiator,
+                                target,
+                                host_name,
+                                storage_system,
+                                self.configuration.cisco_zone_name_prefix,
+                                SUPPORTED_CHARS))
 
                         if len(zone_names) > 0 and (zone_name in zone_names):
                             zone_members = zone_members + filter(
@@ -228,7 +245,8 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                 LOG.debug("Zoning session exists VSAN: %s", zoning_vsan)
 
     @lockutils.synchronized('cisco', 'fcfabric-', True)
-    def delete_connection(self, fabric, initiator_target_map):
+    def delete_connection(self, fabric, initiator_target_map, host_name=None,
+                          storage_system=None):
         """Concrete implementation of delete_connection.
 
         Based on zoning policy and state of each I-T pair, list of zones
@@ -288,9 +306,14 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                     for t in t_list:
                         target = t.lower()
                         zone_name = (
-                            self.configuration.cisco_zone_name_prefix
-                            + initiator.replace(':', '')
-                            + target.replace(':', ''))
+                            driver_utils.get_friendly_zone_name(
+                                zoning_policy,
+                                initiator,
+                                target,
+                                host_name,
+                                storage_system,
+                                self.configuration.cisco_zone_name_prefix,
+                                SUPPORTED_CHARS))
                         LOG.debug("Zone name to del: %s", zone_name)
                         if (len(zone_names) > 0 and (zone_name in zone_names)):
                             # delete zone.
@@ -305,8 +328,14 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
                         zone_members.append(
                             zm_utils.get_formatted_wwn(target))
 
-                    zone_name = self.configuration.cisco_zone_name_prefix \
-                        + initiator.replace(':', '')
+                    zone_name = driver_utils.get_friendly_zone_name(
+                        zoning_policy,
+                        initiator,
+                        target,
+                        host_name,
+                        storage_system,
+                        self.configuration.cisco_zone_name_prefix,
+                        SUPPORTED_CHARS)
 
                     if (zone_names and (zone_name in zone_names)):
                         filtered_members = filter(
diff --git a/cinder/zonemanager/drivers/driver_utils.py b/cinder/zonemanager/drivers/driver_utils.py
new file mode 100644 (file)
index 0000000..51ab0b6
--- /dev/null
@@ -0,0 +1,79 @@
+#    (c) Copyright 2014 Brocade Communications Systems Inc.
+#    All Rights Reserved.
+#
+#    Copyright 2014 OpenStack Foundation
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+import re
+
+from oslo_log import log
+
+from cinder.i18n import _LI
+
+LOG = log.getLogger(__name__)
+
+
+def get_friendly_zone_name(zoning_policy, initiator, target,
+                           host_name, storage_system, zone_name_prefix,
+                           supported_chars):
+    """Utility function implementation of _get_friendly_zone_name.
+
+    Get friendly zone name is used to form the zone name
+    based on the details provided by the caller
+
+    :param zoning_policy - determines the zoning policy is either
+    initiator-target or initiator
+    :param initiator - initiator WWN
+    :param target - target WWN
+    :param host_name - Host name returned from Volume Driver
+    :param storage_system - Storage name returned from Volume Driver
+    :param zone_name_prefix - user defined zone prefix configured
+    in cinder.conf
+    :param supported_chars - Supported character set of FC switch vendor.
+    Example: 'abc123_-$'. These are defined in the FC zone drivers.
+    """
+    if host_name is None:
+        host_name = ''
+    if storage_system is None:
+        storage_system = ''
+    if zoning_policy == 'initiator-target':
+        host_name = host_name[:14]
+        storage_system = storage_system[:14]
+        if len(host_name) > 0 and len(storage_system) > 0:
+            zone_name = (host_name + "_"
+                         + initiator.replace(':', '') + "_"
+                         + storage_system + "_"
+                         + target.replace(':', ''))
+        else:
+            zone_name = (zone_name_prefix
+                         + initiator.replace(':', '')
+                         + target.replace(':', ''))
+            LOG.info(_LI("Zone name created using prefix because either "
+                         "host name or storage system is none."))
+    else:
+        host_name = host_name[:47]
+        if len(host_name) > 0:
+            zone_name = (host_name + "_"
+                         + initiator.replace(':', ''))
+        else:
+            zone_name = (zone_name_prefix
+                         + initiator.replace(':', ''))
+            LOG.info(_LI("Zone name created using prefix because host "
+                         "name is none."))
+
+    LOG.info(_LI("Friendly zone name after forming: %(zonename)s"),
+             {'zonename': zone_name})
+    zone_name = re.sub('[^%s]' % supported_chars, '', zone_name)
+    return zone_name
index 8bf7845f8bc1ffed968d532b42444537fb213080..ec8f3e5a06fb83e1bb7a821b65e2f18cec9f24a3 100644 (file)
@@ -43,7 +43,8 @@ class FCZoneDriver(fc_common.FCCommon):
         super(FCZoneDriver, self).__init__(**kwargs)
         LOG.debug("Initializing FCZoneDriver")
 
-    def add_connection(self, fabric, initiator_target_map):
+    def add_connection(self, fabric, initiator_target_map, host_name=None,
+                       storage_system=None):
         """Add connection control.
 
         Abstract method to add connection control.
@@ -60,7 +61,8 @@ class FCZoneDriver(fc_common.FCCommon):
         """
         raise NotImplementedError()
 
-    def delete_connection(self, fabric, initiator_target_map):
+    def delete_connection(self, fabric, initiator_target_map, host_name=None,
+                          storage_system=None):
         """Delete connection control.
 
         Abstract method to remove connection control.
index 2d598b5fc6d4430750f6a87dbd6ecc0cec86d85c..096fd78a64a661a032f2175fa683d4ac2d41600d 100644 (file)
@@ -40,6 +40,8 @@ from cinder import exception
 from cinder.i18n import _, _LI
 from cinder.volume import configuration as config
 from cinder.zonemanager import fc_common
+import cinder.zonemanager.fczm_constants as zone_constant
+
 
 LOG = logging.getLogger(__name__)
 
@@ -59,7 +61,7 @@ zone_manager_opts = [
     cfg.StrOpt('fc_san_lookup_service',
                default='cinder.zonemanager.drivers.brocade'
                '.brcd_fc_san_lookup_service.BrcdFCSanLookupService',
-               help='FC SAN Lookup Service'),
+               help='FC SAN Lookup Service')
 ]
 
 CONF = cfg.CONF
@@ -67,15 +69,17 @@ CONF.register_opts(zone_manager_opts, group='fc-zone-manager')
 
 
 class ZoneManager(fc_common.FCCommon):
+
     """Manages Connection control during attach/detach.
 
        Version History:
            1.0 - Initial version
            1.0.1 - Added __new__ for singleton
+           1.0.2 - Added friendly zone name
 
     """
 
-    VERSION = "1.0.1"
+    VERSION = "1.0.2"
     driver = None
     fabric_names = []
 
@@ -90,17 +94,18 @@ class ZoneManager(fc_common.FCCommon):
 
         self.configuration = config.Configuration(zone_manager_opts,
                                                   'fc-zone-manager')
-
         self._build_driver()
 
     def _build_driver(self):
         zone_driver = self.configuration.zone_driver
-        LOG.debug("Zone Driver from config: {%s}", zone_driver)
+        LOG.debug("Zone driver from config: %(driver)s",
+                  {'driver': zone_driver})
 
+        zm_config = config.Configuration(zone_manager_opts, 'fc-zone-manager')
         # Initialize vendor specific implementation of  FCZoneDriver
         self.driver = importutils.import_object(
             zone_driver,
-            configuration=self.configuration)
+            configuration=zm_config)
 
     def get_zoning_state_ref_count(self, initiator_wwn, target_wwn):
         """Zone management state check.
@@ -113,7 +118,7 @@ class ZoneManager(fc_common.FCCommon):
         # check the state for I-T pair
         return count
 
-    def add_connection(self, initiator_target_map):
+    def add_connection(self, conn_info):
         """Add connection control.
 
         Adds connection control for the given initiator target map.
@@ -125,14 +130,33 @@ class ZoneManager(fc_common.FCCommon):
         }
         """
         connected_fabric = None
+        host_name = None
+        storage_system = None
+
         try:
+            initiator_target_map = (
+                conn_info[zone_constant.DATA][zone_constant.IT_MAP])
+
+            if zone_constant.HOST in conn_info[zone_constant.DATA]:
+                host_name = conn_info[
+                    zone_constant.DATA][
+                    zone_constant.HOST].replace(" ", "_")
+
+            if zone_constant.STORAGE in conn_info[zone_constant.DATA]:
+                storage_system = (
+                    conn_info[
+                        zone_constant.DATA][
+                        zone_constant.STORAGE].replace(" ", "_"))
+
             for initiator in initiator_target_map.keys():
                 target_list = initiator_target_map[initiator]
-                LOG.debug("Target List: %s", target_list)
+                LOG.debug("Target list : %(targets)s",
+                          {'targets': target_list})
 
                 # get SAN context for the target list
                 fabric_map = self.get_san_context(target_list)
-                LOG.debug("Fabric Map after context lookup: %s", fabric_map)
+                LOG.debug("Fabric map after context lookup: %(fabricmap)s",
+                          {'fabricmap': fabric_map})
                 # iterate over each SAN and apply connection control
                 for fabric in fabric_map.keys():
                     connected_fabric = fabric
@@ -141,13 +165,14 @@ class ZoneManager(fc_common.FCCommon):
                     i_t_map = {initiator: t_list}
                     valid_i_t_map = self.get_valid_initiator_target_map(
                         i_t_map, True)
-                    LOG.info(_LI("Final filtered map for fabric: %s"),
-                             valid_i_t_map)
+                    LOG.info(_LI("Final filtered map for fabric: %(i_t_map)s"),
+                             {'i_t_map': valid_i_t_map})
 
                     # Call driver to add connection control
-                    self.driver.add_connection(fabric, valid_i_t_map)
+                    self.driver.add_connection(fabric, valid_i_t_map,
+                                               host_name, storage_system)
 
-            LOG.info(_LI("Add Connection: Finished iterating "
+            LOG.info(_LI("Add connection: finished iterating "
                          "over all target list"))
         except Exception as e:
             msg = _("Failed adding connection for fabric=%(fabric)s: "
@@ -156,7 +181,7 @@ class ZoneManager(fc_common.FCCommon):
             LOG.error(msg)
             raise exception.ZoneManagerException(reason=msg)
 
-    def delete_connection(self, initiator_target_map):
+    def delete_connection(self, conn_info):
         """Delete connection.
 
         Updates/deletes connection control for the given initiator target map.
@@ -168,16 +193,31 @@ class ZoneManager(fc_common.FCCommon):
         }
         """
         connected_fabric = None
+        host_name = None
+        storage_system = None
+
         try:
+            initiator_target_map = (
+                conn_info[zone_constant.DATA][zone_constant.IT_MAP])
+
+            if zone_constant.HOST in conn_info[zone_constant.DATA]:
+                host_name = conn_info[zone_constant.DATA][zone_constant.HOST]
+
+            if zone_constant.STORAGE in conn_info[zone_constant.DATA]:
+                storage_system = (
+                    conn_info[
+                        zone_constant.DATA][
+                        zone_constant.STORAGE].replace(" ", "_"))
+
             for initiator in initiator_target_map.keys():
                 target_list = initiator_target_map[initiator]
-                LOG.info(_LI("Delete connection Target List: %s"),
-                         target_list)
+                LOG.info(_LI("Delete connection target list: %(targets)s"),
+                         {'targets': target_list})
 
                 # get SAN context for the target list
                 fabric_map = self.get_san_context(target_list)
-                LOG.debug("Delete connection Fabric Map from SAN "
-                          "context: %s", fabric_map)
+                LOG.debug("Delete connection fabric map from SAN "
+                          "context: %(fabricmap)s", {'fabricmap': fabric_map})
 
                 # iterate over each SAN and apply connection control
                 for fabric in fabric_map.keys():
@@ -187,14 +227,17 @@ class ZoneManager(fc_common.FCCommon):
                     i_t_map = {initiator: t_list}
                     valid_i_t_map = self.get_valid_initiator_target_map(
                         i_t_map, False)
-                    LOG.info(_LI("Final filtered map for delete "
-                                 "connection: %s"), valid_i_t_map)
+                    LOG.info(_LI("Final filtered map for delete connection: "
+                                 "%(i_t_map)s"), {'i_t_map': valid_i_t_map})
 
                     # Call driver to delete connection control
                     if len(valid_i_t_map) > 0:
-                        self.driver.delete_connection(fabric, valid_i_t_map)
+                        self.driver.delete_connection(fabric,
+                                                      valid_i_t_map,
+                                                      host_name,
+                                                      storage_system)
 
-            LOG.debug("Delete Connection - Finished iterating over all"
+            LOG.debug("Delete connection - finished iterating over all"
                       " target list")
         except Exception as e:
             msg = _("Failed removing connection for fabric=%(fabric)s: "
@@ -210,7 +253,7 @@ class ZoneManager(fc_common.FCCommon):
         to list of target WWNs visible to the fabric.
         """
         fabric_map = self.driver.get_san_context(target_wwn_list)
-        LOG.debug("Got SAN context: %s", fabric_map)
+        LOG.debug("Got SAN context: %(fabricmap)s", {'fabricmap': fabric_map})
         return fabric_map
 
     def get_valid_initiator_target_map(self, initiator_target_map,
@@ -239,5 +282,6 @@ class ZoneManager(fc_common.FCCommon):
                 filtered_i_t_map[initiator] = t_list
             else:
                 LOG.info(_LI("No targets to add or remove connection for "
-                             "I: %s"), initiator)
+                             "initiator: %(init_wwn)s"),
+                         {'init_wwn': initiator})
         return filtered_i_t_map
diff --git a/cinder/zonemanager/fczm_constants.py b/cinder/zonemanager/fczm_constants.py
new file mode 100644 (file)
index 0000000..d1af905
--- /dev/null
@@ -0,0 +1,22 @@
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+"""
+Common constants used by FC Zone Manager.
+"""
+IT_MAP = 'initiator_target_map'
+DATA = 'data'
+HOST = 'host_name'
+STORAGE = 'storage_system'
+SYSTEM = 'system'
index b359b215a64cb29678d9442dc06d8a73443dd32f..9a3c055d633e3bd228642551d2cbae0a10351b1c 100644 (file)
@@ -34,7 +34,7 @@ LOG.logger.setLevel(logging.DEBUG)
 def create_zone_manager():
     """If zoning is enabled, build the Zone Manager."""
     config = configuration.Configuration(manager.volume_manager_opts)
-    LOG.debug("Zoning mode: %s", config.safe_get('zoning_mode'))
+    LOG.debug("Zoning mode: %s.", config.safe_get('zoning_mode'))
     if config.safe_get('zoning_mode') == 'fabric':
         LOG.debug("FC Zone Manager enabled.")
         zm = fc_zone_manager.ZoneManager()
@@ -51,11 +51,11 @@ def create_zone_manager():
 
 def create_lookup_service():
     config = configuration.Configuration(manager.volume_manager_opts)
-    LOG.debug("Zoning mode: %s", config.safe_get('zoning_mode'))
+    LOG.debug("Zoning mode: %s.", config.safe_get('zoning_mode'))
     if config.safe_get('zoning_mode') == 'fabric':
         LOG.debug("FC Lookup Service enabled.")
         lookup = fc_san_lookup_service.FCSanLookupService()
-        LOG.info(_LI("Using FC lookup service %s"), lookup.lookup_service)
+        LOG.info(_LI("Using FC lookup service %s."), lookup.lookup_service)
         return lookup
     else:
         LOG.debug("FC Lookup Service not enabled in cinder.conf.")
@@ -73,6 +73,7 @@ def get_formatted_wwn(wwn_str):
 
 def AddFCZone(initialize_connection):
     """Decorator to add a FC Zone."""
+
     def decorator(self, *args, **kwargs):
         conn_info = initialize_connection(self, *args, **kwargs)
         if not conn_info:
@@ -82,14 +83,12 @@ def AddFCZone(initialize_connection):
 
         vol_type = conn_info.get('driver_volume_type', None)
         if vol_type == 'fibre_channel':
-
             if 'initiator_target_map' in conn_info['data']:
-                init_target_map = conn_info['data']['initiator_target_map']
                 zm = create_zone_manager()
                 if zm:
-                    LOG.debug("Add FC Zone for mapping '%s'.",
-                              init_target_map)
-                    zm.add_connection(init_target_map)
+                    LOG.debug("AddFCZone connection info: %(conninfo)s.",
+                              {'conninfo': conn_info})
+                    zm.add_connection(conn_info)
 
         return conn_info
 
@@ -98,6 +97,7 @@ def AddFCZone(initialize_connection):
 
 def RemoveFCZone(terminate_connection):
     """Decorator for FC drivers to remove zone."""
+
     def decorator(self, *args, **kwargs):
         conn_info = terminate_connection(self, *args, **kwargs)
         if not conn_info:
@@ -107,14 +107,12 @@ def RemoveFCZone(terminate_connection):
 
         vol_type = conn_info.get('driver_volume_type', None)
         if vol_type == 'fibre_channel':
-
             if 'initiator_target_map' in conn_info['data']:
-                init_target_map = conn_info['data']['initiator_target_map']
                 zm = create_zone_manager()
                 if zm:
-                    LOG.debug("Remove FC Zone for mapping '%s'.",
-                              init_target_map)
-                    zm.delete_connection(init_target_map)
+                    LOG.debug("RemoveFCZone connection info: %(conninfo)s.",
+                              {'conninfo': conn_info})
+                    zm.delete_connection(conn_info)
 
         return conn_info
 
diff --git a/releasenotes/notes/friendly-zone-names-d5e131d356040de0.yaml b/releasenotes/notes/friendly-zone-names-d5e131d356040de0.yaml
new file mode 100644 (file)
index 0000000..ffba656
--- /dev/null
@@ -0,0 +1,10 @@
+---
+features:
+  - Cinder FC Zone Manager Friendly Zone Names
+    This feature adds support for Fibre Channel user
+    friendly zone names if implemented by the volume driver.
+    If the volume driver passes the host name and
+    storage system to the Fibre Channel Zone Manager
+    in the conn_info structure, the zone manager
+    will use these names in structuring the zone
+    name to provide a user friendly zone name.