Adds friendly zone name support
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
This commit is contained in:
parent
31141a9ff4
commit
c346612cc7
113
cinder/tests/unit/zonemanager/test_driverutils.py
Normal file
113
cinder/tests/unit/zonemanager/test_driverutils.py
Normal file
@ -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))
|
@ -29,6 +29,17 @@ from cinder.zonemanager import fc_zone_manager
|
|||||||
|
|
||||||
fabric_name = 'BRCD_FAB_3'
|
fabric_name = 'BRCD_FAB_3'
|
||||||
init_target_map = {'10008c7cff523b01': ['20240002ac000a50']}
|
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']}
|
fabric_map = {'BRCD_FAB_3': ['20240002ac000a50']}
|
||||||
target_list = ['20240002ac000a50']
|
target_list = ['20240002ac000a50']
|
||||||
|
|
||||||
@ -60,10 +71,12 @@ class TestFCZoneManager(test.TestCase):
|
|||||||
with mock.patch.object(self.zm.driver, 'add_connection')\
|
with mock.patch.object(self.zm.driver, 'add_connection')\
|
||||||
as add_connection_mock:
|
as add_connection_mock:
|
||||||
self.zm.driver.get_san_context.return_value = fabric_map
|
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)
|
self.zm.driver.get_san_context.assert_called_once_with(target_list)
|
||||||
add_connection_mock.assert_called_once_with(fabric_name,
|
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)
|
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||||
def test_add_connection_error(self, opt_mock):
|
def test_add_connection_error(self, opt_mock):
|
||||||
@ -71,17 +84,19 @@ class TestFCZoneManager(test.TestCase):
|
|||||||
as add_connection_mock:
|
as add_connection_mock:
|
||||||
add_connection_mock.side_effect = exception.FCZoneDriverException
|
add_connection_mock.side_effect = exception.FCZoneDriverException
|
||||||
self.assertRaises(exception.ZoneManagerException,
|
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)
|
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||||
def test_delete_connection(self, opt_mock):
|
def test_delete_connection(self, opt_mock):
|
||||||
with mock.patch.object(self.zm.driver, 'delete_connection')\
|
with mock.patch.object(self.zm.driver, 'delete_connection')\
|
||||||
as delete_connection_mock:
|
as delete_connection_mock:
|
||||||
self.zm.driver.get_san_context.return_value = fabric_map
|
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)
|
self.zm.driver.get_san_context.assert_called_once_with(target_list)
|
||||||
delete_connection_mock.assert_called_once_with(fabric_name,
|
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)
|
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||||
def test_delete_connection_error(self, opt_mock):
|
def test_delete_connection_error(self, opt_mock):
|
||||||
@ -89,4 +104,4 @@ class TestFCZoneManager(test.TestCase):
|
|||||||
as del_connection_mock:
|
as del_connection_mock:
|
||||||
del_connection_mock.side_effect = exception.FCZoneDriverException
|
del_connection_mock.side_effect = exception.FCZoneDriverException
|
||||||
self.assertRaises(exception.ZoneManagerException,
|
self.assertRaises(exception.ZoneManagerException,
|
||||||
self.zm.delete_connection, init_target_map)
|
self.zm.delete_connection, conn_info)
|
||||||
|
@ -53,8 +53,7 @@ class TestVolumeDriver(test.TestCase):
|
|||||||
as mock_safe_get:
|
as mock_safe_get:
|
||||||
mock_safe_get.return_value = 'fabric'
|
mock_safe_get.return_value = 'fabric'
|
||||||
conn_info = self.driver.initialize_connection(None, None)
|
conn_info = self.driver.initialize_connection(None, None)
|
||||||
init_target_map = conn_info['data']['initiator_target_map']
|
add_zone_mock.assert_called_once_with(conn_info)
|
||||||
add_zone_mock.assert_called_once_with(init_target_map)
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'require_driver_initialized')
|
@mock.patch.object(utils, 'require_driver_initialized')
|
||||||
def test_initialize_connection_no_decorator(self, utils_mock):
|
def test_initialize_connection_no_decorator(self, utils_mock):
|
||||||
@ -77,8 +76,7 @@ class TestVolumeDriver(test.TestCase):
|
|||||||
as mock_safe_get:
|
as mock_safe_get:
|
||||||
mock_safe_get.return_value = 'fabric'
|
mock_safe_get.return_value = 'fabric'
|
||||||
conn_info = self.driver.terminate_connection(None, None)
|
conn_info = self.driver.terminate_connection(None, None)
|
||||||
init_target_map = conn_info['data']['initiator_target_map']
|
remove_zone_mock.assert_called_once_with(conn_info)
|
||||||
remove_zone_mock.assert_called_once_with(init_target_map)
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'require_driver_initialized')
|
@mock.patch.object(utils, 'require_driver_initialized')
|
||||||
def test_terminate_connection_no_decorator(self, utils_mock):
|
def test_terminate_connection_no_decorator(self, utils_mock):
|
||||||
|
@ -41,6 +41,7 @@ brcd_zone_opts = [
|
|||||||
default=True,
|
default=True,
|
||||||
help='overridden zoning activation state'),
|
help='overridden zoning activation state'),
|
||||||
cfg.StrOpt('zone_name_prefix',
|
cfg.StrOpt('zone_name_prefix',
|
||||||
|
default='openstack',
|
||||||
help='overridden zone name prefix'),
|
help='overridden zone name prefix'),
|
||||||
cfg.StrOpt('principal_switch_wwn',
|
cfg.StrOpt('principal_switch_wwn',
|
||||||
help='Principal switch WWN of the fabric'),
|
help='Principal switch WWN of the fabric'),
|
||||||
@ -55,7 +56,8 @@ def load_fabric_configurations(fabric_names):
|
|||||||
fabric_configs = {}
|
fabric_configs = {}
|
||||||
for fabric_name in fabric_names:
|
for fabric_name in fabric_names:
|
||||||
config = configuration.Configuration(brcd_zone_opts, fabric_name)
|
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
|
fabric_configs[fabric_name] = config
|
||||||
|
|
||||||
return fabric_configs
|
return fabric_configs
|
||||||
|
@ -36,14 +36,17 @@ from oslo_log import log as logging
|
|||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
import six
|
import six
|
||||||
|
import string
|
||||||
|
|
||||||
from cinder import exception
|
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.brocade import brcd_fabric_opts as fabric_opts
|
||||||
|
from cinder.zonemanager.drivers import driver_utils
|
||||||
from cinder.zonemanager.drivers import fc_zone_driver
|
from cinder.zonemanager.drivers import fc_zone_driver
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SUPPORTED_CHARS = string.ascii_letters + string.digits + '_'
|
||||||
brcd_opts = [
|
brcd_opts = [
|
||||||
cfg.StrOpt('brcd_sb_connector',
|
cfg.StrOpt('brcd_sb_connector',
|
||||||
default='cinder.zonemanager.drivers.brocade'
|
default='cinder.zonemanager.drivers.brocade'
|
||||||
@ -64,9 +67,10 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
Version history:
|
Version history:
|
||||||
1.0 - Initial Brocade FC zone driver
|
1.0 - Initial Brocade FC zone driver
|
||||||
1.1 - Implements performance enhancements
|
1.1 - Implements performance enhancements
|
||||||
|
1.2 - Added support for friendly zone name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "1.1"
|
VERSION = "1.2"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(BrcdFCZoneDriver, self).__init__(**kwargs)
|
super(BrcdFCZoneDriver, self).__init__(**kwargs)
|
||||||
@ -74,8 +78,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
self.configuration = kwargs.get('configuration', None)
|
self.configuration = kwargs.get('configuration', None)
|
||||||
if self.configuration:
|
if self.configuration:
|
||||||
self.configuration.append_config_values(brcd_opts)
|
self.configuration.append_config_values(brcd_opts)
|
||||||
# Adding a hack to hendle parameters from super classes
|
# Adding a hack to handle parameters from super classes
|
||||||
# in case configured with multi backend.
|
# in case configured with multiple back ends.
|
||||||
fabric_names = self.configuration.safe_get('fc_fabric_names')
|
fabric_names = self.configuration.safe_get('fc_fabric_names')
|
||||||
base_san_opts = []
|
base_san_opts = []
|
||||||
if not fabric_names:
|
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)])
|
[wwn_str[i:i + 2] for i in range(0, len(wwn_str), 2)])
|
||||||
|
|
||||||
@lockutils.synchronized('brcd', 'fcfabric-', True)
|
@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.
|
"""Concrete implementation of add_connection.
|
||||||
|
|
||||||
Based on zoning policy and state of each I-T pair, list of zone
|
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 fabric: Fabric name from cinder.conf file
|
||||||
:param initiator_target_map: Mapping of initiator to list of targets
|
: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 fabric "
|
||||||
LOG.info(_LI("BrcdFCZoneDriver - Add connection "
|
"%(fabric)s for I-T map: %(i_t_map)s"),
|
||||||
"for I-T map: %s"), initiator_target_map)
|
{'fabric': fabric,
|
||||||
|
'i_t_map': initiator_target_map})
|
||||||
zoning_policy = self.configuration.zoning_policy
|
zoning_policy = self.configuration.zoning_policy
|
||||||
zoning_policy_fab = self.fabric_configs[fabric].safe_get(
|
zoning_policy_fab = self.fabric_configs[fabric].safe_get(
|
||||||
'zoning_policy')
|
'zoning_policy')
|
||||||
if zoning_policy_fab:
|
|
||||||
zoning_policy = zoning_policy_fab
|
|
||||||
zone_name_prefix = self.fabric_configs[fabric].safe_get(
|
zone_name_prefix = self.fabric_configs[fabric].safe_get(
|
||||||
'zone_name_prefix')
|
'zone_name_prefix')
|
||||||
if not zone_name_prefix:
|
|
||||||
zone_name_prefix = 'openstack'
|
|
||||||
zone_activate = self.fabric_configs[fabric].safe_get(
|
zone_activate = self.fabric_configs[fabric].safe_get(
|
||||||
'zone_activate')
|
'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)
|
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(cli_client)
|
||||||
|
|
||||||
@ -154,24 +164,37 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
target = t.lower()
|
target = t.lower()
|
||||||
zone_members = [self.get_formatted_wwn(initiator),
|
zone_members = [self.get_formatted_wwn(initiator),
|
||||||
self.get_formatted_wwn(target)]
|
self.get_formatted_wwn(target)]
|
||||||
zone_name = (zone_name_prefix
|
zone_name = driver_utils.get_friendly_zone_name(
|
||||||
+ initiator.replace(':', '')
|
zoning_policy,
|
||||||
+ target.replace(':', ''))
|
initiator,
|
||||||
|
target,
|
||||||
|
host_name,
|
||||||
|
storage_system,
|
||||||
|
zone_name_prefix,
|
||||||
|
SUPPORTED_CHARS)
|
||||||
if (
|
if (
|
||||||
len(cfgmap_from_fabric) == 0 or (
|
len(cfgmap_from_fabric) == 0 or (
|
||||||
zone_name not in zone_names)):
|
zone_name not in zone_names)):
|
||||||
zone_map[zone_name] = zone_members
|
zone_map[zone_name] = zone_members
|
||||||
else:
|
else:
|
||||||
# This is I-T zoning, skip if zone already exists.
|
# This is I-T zoning, skip if zone already exists.
|
||||||
LOG.info(_LI("Zone exists in I-T mode. "
|
LOG.info(_LI("Zone exists in I-T mode. Skipping "
|
||||||
"Skipping zone creation %s"), zone_name)
|
"zone creation for %(zonename)s"),
|
||||||
|
{'zonename': zone_name})
|
||||||
elif zoning_policy == 'initiator':
|
elif zoning_policy == 'initiator':
|
||||||
zone_members = [self.get_formatted_wwn(initiator)]
|
zone_members = [self.get_formatted_wwn(initiator)]
|
||||||
for t in t_list:
|
for t in t_list:
|
||||||
target = t.lower()
|
target = t.lower()
|
||||||
zone_members.append(self.get_formatted_wwn(target))
|
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):
|
if len(zone_names) > 0 and (zone_name in zone_names):
|
||||||
zone_members = zone_members + filter(
|
zone_members = zone_members + filter(
|
||||||
@ -179,13 +202,9 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
cfgmap_from_fabric['zones'][zone_name])
|
cfgmap_from_fabric['zones'][zone_name])
|
||||||
|
|
||||||
zone_map[zone_name] = zone_members
|
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:
|
if len(zone_map) > 0:
|
||||||
try:
|
try:
|
||||||
@ -199,10 +218,12 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
msg = _("Failed to add zoning configuration.")
|
msg = _("Failed to add zoning configuration.")
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
raise exception.FCZoneDriverException(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)
|
@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.
|
"""Concrete implementation of delete_connection.
|
||||||
|
|
||||||
Based on zoning policy and state of each I-T pair, list of zones
|
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 fabric: Fabric name from cinder.conf file
|
||||||
:param initiator_target_map: Mapping of initiator to list of targets
|
: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 fabric "
|
||||||
LOG.info(_LI("BrcdFCZoneDriver - Delete connection for I-T map: %s"),
|
"%(fabric)s for I-T map: %(i_t_map)s"),
|
||||||
initiator_target_map)
|
{'fabric': fabric,
|
||||||
|
'i_t_map': initiator_target_map})
|
||||||
zoning_policy = self.configuration.zoning_policy
|
zoning_policy = self.configuration.zoning_policy
|
||||||
zoning_policy_fab = self.fabric_configs[fabric].safe_get(
|
zoning_policy_fab = self.fabric_configs[fabric].safe_get(
|
||||||
'zoning_policy')
|
'zoning_policy')
|
||||||
if zoning_policy_fab:
|
|
||||||
zoning_policy = zoning_policy_fab
|
|
||||||
zone_name_prefix = self.fabric_configs[fabric].safe_get(
|
zone_name_prefix = self.fabric_configs[fabric].safe_get(
|
||||||
'zone_name_prefix')
|
'zone_name_prefix')
|
||||||
if not zone_name_prefix:
|
|
||||||
zone_name_prefix = 'openstack'
|
|
||||||
zone_activate = self.fabric_configs[fabric].safe_get(
|
zone_activate = self.fabric_configs[fabric].safe_get(
|
||||||
'zone_activate')
|
'zone_activate')
|
||||||
|
if zoning_policy_fab:
|
||||||
LOG.info(_LI("Zoning policy for fabric %s"), zoning_policy)
|
zoning_policy = zoning_policy_fab
|
||||||
|
LOG.info(_LI("Zoning policy for fabric %(policy)s"),
|
||||||
|
{'policy': zoning_policy})
|
||||||
conn = self._get_cli_client(fabric)
|
conn = self._get_cli_client(fabric)
|
||||||
cfgmap_from_fabric = self._get_active_zone_set(conn)
|
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
|
# Based on zoning policy, get zone member list and push changes to
|
||||||
# fabric. This operation could result in an update for zone config
|
# fabric. This operation could result in an update for zone config
|
||||||
# with new member list or deleting zones from active cfg.
|
# 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():
|
for initiator_key in initiator_target_map.keys():
|
||||||
initiator = initiator_key.lower()
|
initiator = initiator_key.lower()
|
||||||
formatted_initiator = self.get_formatted_wwn(initiator)
|
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.
|
# In this case, zone needs to be deleted.
|
||||||
for t in t_list:
|
for t in t_list:
|
||||||
target = t.lower()
|
target = t.lower()
|
||||||
zone_name = (
|
zone_name = driver_utils.get_friendly_zone_name(
|
||||||
zone_name_prefix
|
zoning_policy,
|
||||||
+ initiator.replace(':', '')
|
initiator,
|
||||||
+ target.replace(':', ''))
|
target,
|
||||||
LOG.debug("Zone name to del: %s", zone_name)
|
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):
|
if len(zone_names) > 0 and (zone_name in zone_names):
|
||||||
# delete zone.
|
# delete zone.
|
||||||
LOG.debug("Added zone to delete to "
|
LOG.debug("Added zone to delete to list: %(zonename)s",
|
||||||
"list: %s", zone_name)
|
{'zonename': zone_name})
|
||||||
zones_to_delete.append(zone_name)
|
zones_to_delete.append(zone_name)
|
||||||
|
|
||||||
elif zoning_policy == 'initiator':
|
elif zoning_policy == 'initiator':
|
||||||
@ -266,7 +292,14 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
target = t.lower()
|
target = t.lower()
|
||||||
zone_members.append(self.get_formatted_wwn(target))
|
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)):
|
if (zone_names and (zone_name in zone_names)):
|
||||||
filtered_members = filter(
|
filtered_members = filter(
|
||||||
@ -278,22 +311,25 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
# filtered list and if it is non-empty, add initiator
|
# filtered list and if it is non-empty, add initiator
|
||||||
# to it and update zone if filtered list is empty, we
|
# to it and update zone if filtered list is empty, we
|
||||||
# remove that zone.
|
# remove that zone.
|
||||||
LOG.debug("Zone delete - I mode: "
|
LOG.debug("Zone delete - initiator mode: "
|
||||||
"filtered targets: %s", filtered_members)
|
"filtered targets: %(targets)s",
|
||||||
|
{'targets': filtered_members})
|
||||||
if filtered_members:
|
if filtered_members:
|
||||||
filtered_members.append(formatted_initiator)
|
filtered_members.append(formatted_initiator)
|
||||||
LOG.debug("Filtered zone members to "
|
LOG.debug("Filtered zone members to update: "
|
||||||
"update: %s", filtered_members)
|
"%(members)s", {'members': filtered_members})
|
||||||
zone_map[zone_name] = filtered_members
|
zone_map[zone_name] = filtered_members
|
||||||
LOG.debug("Filtered zone Map to "
|
LOG.debug("Filtered zone map to update: %(zonemap)s",
|
||||||
"update: %s", zone_map)
|
{'zonemap': zone_map})
|
||||||
else:
|
else:
|
||||||
zones_to_delete.append(zone_name)
|
zones_to_delete.append(zone_name)
|
||||||
else:
|
else:
|
||||||
LOG.info(_LI("Zoning Policy: %s, not "
|
LOG.warning(_LW("Zoning policy not recognized: %(policy)s"),
|
||||||
"recognized"), zoning_policy)
|
{'policy': zoning_policy})
|
||||||
LOG.debug("Final Zone map to update: %s", zone_map)
|
LOG.debug("Final zone map to update: %(zonemap)s",
|
||||||
LOG.debug("Final Zone list to delete: %s", zones_to_delete)
|
{'zonemap': zone_map})
|
||||||
|
LOG.debug("Final zone list to delete: %(zones)s",
|
||||||
|
{'zones': zones_to_delete})
|
||||||
try:
|
try:
|
||||||
# Update zone membership.
|
# Update zone membership.
|
||||||
if zone_map:
|
if zone_map:
|
||||||
@ -333,13 +369,14 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
fabric_map = {}
|
fabric_map = {}
|
||||||
fc_fabric_names = self.configuration.fc_fabric_names
|
fc_fabric_names = self.configuration.fc_fabric_names
|
||||||
fabrics = [x.strip() for x in fc_fabric_names.split(',')]
|
fabrics = [x.strip() for x in fc_fabric_names.split(',')]
|
||||||
LOG.debug("Fabric List: %s", fabrics)
|
LOG.debug("Fabric List: %(fabrics)s", {'fabrics': fabrics})
|
||||||
LOG.debug("Target wwn List: %s", target_wwn_list)
|
LOG.debug("Target WWN list: %(targetwwns)s",
|
||||||
|
{'targetwwns': target_wwn_list})
|
||||||
if len(fabrics) > 0:
|
if len(fabrics) > 0:
|
||||||
for t in target_wwn_list:
|
for t in target_wwn_list:
|
||||||
formatted_target_list.append(self.get_formatted_wwn(t.lower()))
|
formatted_target_list.append(self.get_formatted_wwn(t.lower()))
|
||||||
LOG.debug("Formatted Target wwn List:"
|
LOG.debug("Formatted target WWN list: %(targetlist)s",
|
||||||
" %s", formatted_target_list)
|
{'targetlist': formatted_target_list})
|
||||||
for fabric_name in fabrics:
|
for fabric_name in fabrics:
|
||||||
conn = self._get_cli_client(fabric_name)
|
conn = self._get_cli_client(fabric_name)
|
||||||
|
|
||||||
@ -348,7 +385,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
nsinfo = None
|
nsinfo = None
|
||||||
try:
|
try:
|
||||||
nsinfo = conn.get_nameserver_info()
|
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()
|
conn.cleanup()
|
||||||
except exception.BrocadeZoningCliException:
|
except exception.BrocadeZoningCliException:
|
||||||
if not conn.is_supported_firmware():
|
if not conn.is_supported_firmware():
|
||||||
@ -368,17 +406,19 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
nsinfo)
|
nsinfo)
|
||||||
|
|
||||||
if visible_targets:
|
if visible_targets:
|
||||||
LOG.info(_LI("Filtered targets for SAN is: %s"),
|
LOG.info(_LI("Filtered targets for SAN is: %(targets)s"),
|
||||||
{fabric_name: visible_targets})
|
{'targets': visible_targets})
|
||||||
# getting rid of the ':' before returning
|
# getting rid of the ':' before returning
|
||||||
for idx, elem in enumerate(visible_targets):
|
for idx, elem in enumerate(visible_targets):
|
||||||
visible_targets[idx] = str(
|
visible_targets[idx] = str(
|
||||||
visible_targets[idx]).replace(':', '')
|
visible_targets[idx]).replace(':', '')
|
||||||
fabric_map[fabric_name] = visible_targets
|
fabric_map[fabric_name] = visible_targets
|
||||||
else:
|
else:
|
||||||
LOG.debug("No targets are in the nameserver for SAN %s",
|
LOG.debug("No targets found in the nameserver "
|
||||||
fabric_name)
|
"for fabric: %(fabric)s",
|
||||||
LOG.debug("Return SAN context output: %s", fabric_map)
|
{'fabric': fabric_name})
|
||||||
|
LOG.debug("Return SAN context output: %(fabricmap)s",
|
||||||
|
{'fabricmap': fabric_map})
|
||||||
return fabric_map
|
return fabric_map
|
||||||
|
|
||||||
def _get_active_zone_set(self, conn):
|
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")
|
msg = (_("Failed to retrieve active zoning configuration %s")
|
||||||
% six.text_type(e))
|
% six.text_type(e))
|
||||||
raise exception.FCZoneDriverException(msg)
|
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
|
return cfgmap
|
||||||
|
|
||||||
def _get_cli_client(self, fabric):
|
def _get_cli_client(self, fabric):
|
||||||
@ -408,7 +449,8 @@ class BrcdFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
try:
|
try:
|
||||||
cli_client = self.sb_conn_map.get(fabric_ip)
|
cli_client = self.sb_conn_map.get(fabric_ip)
|
||||||
if not cli_client:
|
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(
|
cli_client = importutils.import_object(
|
||||||
self.configuration.brcd_sb_connector,
|
self.configuration.brcd_sb_connector,
|
||||||
ipaddress=fabric_ip,
|
ipaddress=fabric_ip,
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Common constants used by Brocade FC Zone Driver.
|
Common constants used by Brocade FC Zone Driver.
|
||||||
"""
|
"""
|
||||||
|
@ -33,15 +33,18 @@ from oslo_log import log as logging
|
|||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
import six
|
import six
|
||||||
|
import string
|
||||||
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _, _LE, _LI
|
from cinder.i18n import _, _LE, _LI
|
||||||
from cinder.zonemanager.drivers.cisco import cisco_fabric_opts as fabric_opts
|
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.drivers import fc_zone_driver
|
||||||
from cinder.zonemanager import utils as zm_utils
|
from cinder.zonemanager import utils as zm_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SUPPORTED_CHARS = string.ascii_letters + string.digits + '$' + '-' + '^' + '_'
|
||||||
cisco_opts = [
|
cisco_opts = [
|
||||||
cfg.StrOpt('cisco_sb_connector',
|
cfg.StrOpt('cisco_sb_connector',
|
||||||
default='cinder.zonemanager.drivers.cisco'
|
default='cinder.zonemanager.drivers.cisco'
|
||||||
@ -61,9 +64,10 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
|
|
||||||
Version history:
|
Version history:
|
||||||
1.0 - Initial Cisco FC zone driver
|
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):
|
def __init__(self, **kwargs):
|
||||||
super(CiscoFCZoneDriver, self).__init__(**kwargs)
|
super(CiscoFCZoneDriver, self).__init__(**kwargs)
|
||||||
@ -109,7 +113,8 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
fabric_names)
|
fabric_names)
|
||||||
|
|
||||||
@lockutils.synchronized('cisco', 'fcfabric-', True)
|
@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.
|
"""Concrete implementation of add_connection.
|
||||||
|
|
||||||
Based on zoning policy and state of each I-T pair, list of zone
|
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 = [
|
zone_members = [
|
||||||
zm_utils.get_formatted_wwn(initiator),
|
zm_utils.get_formatted_wwn(initiator),
|
||||||
zm_utils.get_formatted_wwn(target)]
|
zm_utils.get_formatted_wwn(target)]
|
||||||
zone_name = (self.
|
zone_name = (
|
||||||
configuration.cisco_zone_name_prefix
|
driver_utils.get_friendly_zone_name(
|
||||||
+ initiator.replace(':', '')
|
zoning_policy,
|
||||||
+ target.replace(':', ''))
|
initiator,
|
||||||
|
target,
|
||||||
|
host_name,
|
||||||
|
storage_system,
|
||||||
|
self.configuration.cisco_zone_name_prefix,
|
||||||
|
SUPPORTED_CHARS))
|
||||||
if (len(cfgmap_from_fabric) == 0 or (
|
if (len(cfgmap_from_fabric) == 0 or (
|
||||||
zone_name not in zone_names)):
|
zone_name not in zone_names)):
|
||||||
zone_map[zone_name] = zone_members
|
zone_map[zone_name] = zone_members
|
||||||
@ -185,8 +195,15 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
zone_members.append(
|
zone_members.append(
|
||||||
zm_utils.get_formatted_wwn(target))
|
zm_utils.get_formatted_wwn(target))
|
||||||
|
|
||||||
zone_name = self.configuration.cisco_zone_name_prefix \
|
zone_name = (
|
||||||
+ initiator.replace(':', '')
|
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):
|
if len(zone_names) > 0 and (zone_name in zone_names):
|
||||||
zone_members = zone_members + filter(
|
zone_members = zone_members + filter(
|
||||||
@ -228,7 +245,8 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
LOG.debug("Zoning session exists VSAN: %s", zoning_vsan)
|
LOG.debug("Zoning session exists VSAN: %s", zoning_vsan)
|
||||||
|
|
||||||
@lockutils.synchronized('cisco', 'fcfabric-', True)
|
@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.
|
"""Concrete implementation of delete_connection.
|
||||||
|
|
||||||
Based on zoning policy and state of each I-T pair, list of zones
|
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:
|
for t in t_list:
|
||||||
target = t.lower()
|
target = t.lower()
|
||||||
zone_name = (
|
zone_name = (
|
||||||
self.configuration.cisco_zone_name_prefix
|
driver_utils.get_friendly_zone_name(
|
||||||
+ initiator.replace(':', '')
|
zoning_policy,
|
||||||
+ target.replace(':', ''))
|
initiator,
|
||||||
|
target,
|
||||||
|
host_name,
|
||||||
|
storage_system,
|
||||||
|
self.configuration.cisco_zone_name_prefix,
|
||||||
|
SUPPORTED_CHARS))
|
||||||
LOG.debug("Zone name to del: %s", zone_name)
|
LOG.debug("Zone name to del: %s", zone_name)
|
||||||
if (len(zone_names) > 0 and (zone_name in zone_names)):
|
if (len(zone_names) > 0 and (zone_name in zone_names)):
|
||||||
# delete zone.
|
# delete zone.
|
||||||
@ -305,8 +328,14 @@ class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver):
|
|||||||
zone_members.append(
|
zone_members.append(
|
||||||
zm_utils.get_formatted_wwn(target))
|
zm_utils.get_formatted_wwn(target))
|
||||||
|
|
||||||
zone_name = self.configuration.cisco_zone_name_prefix \
|
zone_name = driver_utils.get_friendly_zone_name(
|
||||||
+ initiator.replace(':', '')
|
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)):
|
if (zone_names and (zone_name in zone_names)):
|
||||||
filtered_members = filter(
|
filtered_members = filter(
|
||||||
|
79
cinder/zonemanager/drivers/driver_utils.py
Normal file
79
cinder/zonemanager/drivers/driver_utils.py
Normal file
@ -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
|
@ -43,7 +43,8 @@ class FCZoneDriver(fc_common.FCCommon):
|
|||||||
super(FCZoneDriver, self).__init__(**kwargs)
|
super(FCZoneDriver, self).__init__(**kwargs)
|
||||||
LOG.debug("Initializing FCZoneDriver")
|
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.
|
"""Add connection control.
|
||||||
|
|
||||||
Abstract method to add connection control.
|
Abstract method to add connection control.
|
||||||
@ -60,7 +61,8 @@ class FCZoneDriver(fc_common.FCCommon):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
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.
|
"""Delete connection control.
|
||||||
|
|
||||||
Abstract method to remove connection control.
|
Abstract method to remove connection control.
|
||||||
|
@ -40,6 +40,8 @@ from cinder import exception
|
|||||||
from cinder.i18n import _, _LI
|
from cinder.i18n import _, _LI
|
||||||
from cinder.volume import configuration as config
|
from cinder.volume import configuration as config
|
||||||
from cinder.zonemanager import fc_common
|
from cinder.zonemanager import fc_common
|
||||||
|
import cinder.zonemanager.fczm_constants as zone_constant
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ zone_manager_opts = [
|
|||||||
cfg.StrOpt('fc_san_lookup_service',
|
cfg.StrOpt('fc_san_lookup_service',
|
||||||
default='cinder.zonemanager.drivers.brocade'
|
default='cinder.zonemanager.drivers.brocade'
|
||||||
'.brcd_fc_san_lookup_service.BrcdFCSanLookupService',
|
'.brcd_fc_san_lookup_service.BrcdFCSanLookupService',
|
||||||
help='FC SAN Lookup Service'),
|
help='FC SAN Lookup Service')
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@ -67,15 +69,17 @@ CONF.register_opts(zone_manager_opts, group='fc-zone-manager')
|
|||||||
|
|
||||||
|
|
||||||
class ZoneManager(fc_common.FCCommon):
|
class ZoneManager(fc_common.FCCommon):
|
||||||
|
|
||||||
"""Manages Connection control during attach/detach.
|
"""Manages Connection control during attach/detach.
|
||||||
|
|
||||||
Version History:
|
Version History:
|
||||||
1.0 - Initial version
|
1.0 - Initial version
|
||||||
1.0.1 - Added __new__ for singleton
|
1.0.1 - Added __new__ for singleton
|
||||||
|
1.0.2 - Added friendly zone name
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "1.0.1"
|
VERSION = "1.0.2"
|
||||||
driver = None
|
driver = None
|
||||||
fabric_names = []
|
fabric_names = []
|
||||||
|
|
||||||
@ -90,17 +94,18 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
|
|
||||||
self.configuration = config.Configuration(zone_manager_opts,
|
self.configuration = config.Configuration(zone_manager_opts,
|
||||||
'fc-zone-manager')
|
'fc-zone-manager')
|
||||||
|
|
||||||
self._build_driver()
|
self._build_driver()
|
||||||
|
|
||||||
def _build_driver(self):
|
def _build_driver(self):
|
||||||
zone_driver = self.configuration.zone_driver
|
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
|
# Initialize vendor specific implementation of FCZoneDriver
|
||||||
self.driver = importutils.import_object(
|
self.driver = importutils.import_object(
|
||||||
zone_driver,
|
zone_driver,
|
||||||
configuration=self.configuration)
|
configuration=zm_config)
|
||||||
|
|
||||||
def get_zoning_state_ref_count(self, initiator_wwn, target_wwn):
|
def get_zoning_state_ref_count(self, initiator_wwn, target_wwn):
|
||||||
"""Zone management state check.
|
"""Zone management state check.
|
||||||
@ -113,7 +118,7 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
# check the state for I-T pair
|
# check the state for I-T pair
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def add_connection(self, initiator_target_map):
|
def add_connection(self, conn_info):
|
||||||
"""Add connection control.
|
"""Add connection control.
|
||||||
|
|
||||||
Adds connection control for the given initiator target map.
|
Adds connection control for the given initiator target map.
|
||||||
@ -125,14 +130,33 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
connected_fabric = None
|
connected_fabric = None
|
||||||
|
host_name = None
|
||||||
|
storage_system = None
|
||||||
|
|
||||||
try:
|
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():
|
for initiator in initiator_target_map.keys():
|
||||||
target_list = initiator_target_map[initiator]
|
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
|
# get SAN context for the target list
|
||||||
fabric_map = self.get_san_context(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
|
# iterate over each SAN and apply connection control
|
||||||
for fabric in fabric_map.keys():
|
for fabric in fabric_map.keys():
|
||||||
connected_fabric = fabric
|
connected_fabric = fabric
|
||||||
@ -141,13 +165,14 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
i_t_map = {initiator: t_list}
|
i_t_map = {initiator: t_list}
|
||||||
valid_i_t_map = self.get_valid_initiator_target_map(
|
valid_i_t_map = self.get_valid_initiator_target_map(
|
||||||
i_t_map, True)
|
i_t_map, True)
|
||||||
LOG.info(_LI("Final filtered map for fabric: %s"),
|
LOG.info(_LI("Final filtered map for fabric: %(i_t_map)s"),
|
||||||
valid_i_t_map)
|
{'i_t_map': valid_i_t_map})
|
||||||
|
|
||||||
# Call driver to add connection control
|
# 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"))
|
"over all target list"))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = _("Failed adding connection for fabric=%(fabric)s: "
|
msg = _("Failed adding connection for fabric=%(fabric)s: "
|
||||||
@ -156,7 +181,7 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.ZoneManagerException(reason=msg)
|
raise exception.ZoneManagerException(reason=msg)
|
||||||
|
|
||||||
def delete_connection(self, initiator_target_map):
|
def delete_connection(self, conn_info):
|
||||||
"""Delete connection.
|
"""Delete connection.
|
||||||
|
|
||||||
Updates/deletes connection control for the given initiator target map.
|
Updates/deletes connection control for the given initiator target map.
|
||||||
@ -168,16 +193,31 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
connected_fabric = None
|
connected_fabric = None
|
||||||
|
host_name = None
|
||||||
|
storage_system = None
|
||||||
|
|
||||||
try:
|
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():
|
for initiator in initiator_target_map.keys():
|
||||||
target_list = initiator_target_map[initiator]
|
target_list = initiator_target_map[initiator]
|
||||||
LOG.info(_LI("Delete connection Target List: %s"),
|
LOG.info(_LI("Delete connection target list: %(targets)s"),
|
||||||
target_list)
|
{'targets': target_list})
|
||||||
|
|
||||||
# get SAN context for the target list
|
# get SAN context for the target list
|
||||||
fabric_map = self.get_san_context(target_list)
|
fabric_map = self.get_san_context(target_list)
|
||||||
LOG.debug("Delete connection Fabric Map from SAN "
|
LOG.debug("Delete connection fabric map from SAN "
|
||||||
"context: %s", fabric_map)
|
"context: %(fabricmap)s", {'fabricmap': fabric_map})
|
||||||
|
|
||||||
# iterate over each SAN and apply connection control
|
# iterate over each SAN and apply connection control
|
||||||
for fabric in fabric_map.keys():
|
for fabric in fabric_map.keys():
|
||||||
@ -187,14 +227,17 @@ class ZoneManager(fc_common.FCCommon):
|
|||||||
i_t_map = {initiator: t_list}
|
i_t_map = {initiator: t_list}
|
||||||
valid_i_t_map = self.get_valid_initiator_target_map(
|
valid_i_t_map = self.get_valid_initiator_target_map(
|
||||||
i_t_map, False)
|
i_t_map, False)
|
||||||
LOG.info(_LI("Final filtered map for delete "
|
LOG.info(_LI("Final filtered map for delete connection: "
|
||||||
"connection: %s"), valid_i_t_map)
|
"%(i_t_map)s"), {'i_t_map': valid_i_t_map})
|
||||||
|
|
||||||
# Call driver to delete connection control
|
# Call driver to delete connection control
|
||||||
if len(valid_i_t_map) > 0:
|
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")
|
" target list")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = _("Failed removing connection for fabric=%(fabric)s: "
|
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.
|
to list of target WWNs visible to the fabric.
|
||||||
"""
|
"""
|
||||||
fabric_map = self.driver.get_san_context(target_wwn_list)
|
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
|
return fabric_map
|
||||||
|
|
||||||
def get_valid_initiator_target_map(self, initiator_target_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
|
filtered_i_t_map[initiator] = t_list
|
||||||
else:
|
else:
|
||||||
LOG.info(_LI("No targets to add or remove connection for "
|
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
|
return filtered_i_t_map
|
||||||
|
22
cinder/zonemanager/fczm_constants.py
Normal file
22
cinder/zonemanager/fczm_constants.py
Normal file
@ -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'
|
@ -34,7 +34,7 @@ LOG.logger.setLevel(logging.DEBUG)
|
|||||||
def create_zone_manager():
|
def create_zone_manager():
|
||||||
"""If zoning is enabled, build the Zone Manager."""
|
"""If zoning is enabled, build the Zone Manager."""
|
||||||
config = configuration.Configuration(manager.volume_manager_opts)
|
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':
|
if config.safe_get('zoning_mode') == 'fabric':
|
||||||
LOG.debug("FC Zone Manager enabled.")
|
LOG.debug("FC Zone Manager enabled.")
|
||||||
zm = fc_zone_manager.ZoneManager()
|
zm = fc_zone_manager.ZoneManager()
|
||||||
@ -51,11 +51,11 @@ def create_zone_manager():
|
|||||||
|
|
||||||
def create_lookup_service():
|
def create_lookup_service():
|
||||||
config = configuration.Configuration(manager.volume_manager_opts)
|
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':
|
if config.safe_get('zoning_mode') == 'fabric':
|
||||||
LOG.debug("FC Lookup Service enabled.")
|
LOG.debug("FC Lookup Service enabled.")
|
||||||
lookup = fc_san_lookup_service.FCSanLookupService()
|
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
|
return lookup
|
||||||
else:
|
else:
|
||||||
LOG.debug("FC Lookup Service not enabled in cinder.conf.")
|
LOG.debug("FC Lookup Service not enabled in cinder.conf.")
|
||||||
@ -73,6 +73,7 @@ def get_formatted_wwn(wwn_str):
|
|||||||
|
|
||||||
def AddFCZone(initialize_connection):
|
def AddFCZone(initialize_connection):
|
||||||
"""Decorator to add a FC Zone."""
|
"""Decorator to add a FC Zone."""
|
||||||
|
|
||||||
def decorator(self, *args, **kwargs):
|
def decorator(self, *args, **kwargs):
|
||||||
conn_info = initialize_connection(self, *args, **kwargs)
|
conn_info = initialize_connection(self, *args, **kwargs)
|
||||||
if not conn_info:
|
if not conn_info:
|
||||||
@ -82,14 +83,12 @@ def AddFCZone(initialize_connection):
|
|||||||
|
|
||||||
vol_type = conn_info.get('driver_volume_type', None)
|
vol_type = conn_info.get('driver_volume_type', None)
|
||||||
if vol_type == 'fibre_channel':
|
if vol_type == 'fibre_channel':
|
||||||
|
|
||||||
if 'initiator_target_map' in conn_info['data']:
|
if 'initiator_target_map' in conn_info['data']:
|
||||||
init_target_map = conn_info['data']['initiator_target_map']
|
|
||||||
zm = create_zone_manager()
|
zm = create_zone_manager()
|
||||||
if zm:
|
if zm:
|
||||||
LOG.debug("Add FC Zone for mapping '%s'.",
|
LOG.debug("AddFCZone connection info: %(conninfo)s.",
|
||||||
init_target_map)
|
{'conninfo': conn_info})
|
||||||
zm.add_connection(init_target_map)
|
zm.add_connection(conn_info)
|
||||||
|
|
||||||
return conn_info
|
return conn_info
|
||||||
|
|
||||||
@ -98,6 +97,7 @@ def AddFCZone(initialize_connection):
|
|||||||
|
|
||||||
def RemoveFCZone(terminate_connection):
|
def RemoveFCZone(terminate_connection):
|
||||||
"""Decorator for FC drivers to remove zone."""
|
"""Decorator for FC drivers to remove zone."""
|
||||||
|
|
||||||
def decorator(self, *args, **kwargs):
|
def decorator(self, *args, **kwargs):
|
||||||
conn_info = terminate_connection(self, *args, **kwargs)
|
conn_info = terminate_connection(self, *args, **kwargs)
|
||||||
if not conn_info:
|
if not conn_info:
|
||||||
@ -107,14 +107,12 @@ def RemoveFCZone(terminate_connection):
|
|||||||
|
|
||||||
vol_type = conn_info.get('driver_volume_type', None)
|
vol_type = conn_info.get('driver_volume_type', None)
|
||||||
if vol_type == 'fibre_channel':
|
if vol_type == 'fibre_channel':
|
||||||
|
|
||||||
if 'initiator_target_map' in conn_info['data']:
|
if 'initiator_target_map' in conn_info['data']:
|
||||||
init_target_map = conn_info['data']['initiator_target_map']
|
|
||||||
zm = create_zone_manager()
|
zm = create_zone_manager()
|
||||||
if zm:
|
if zm:
|
||||||
LOG.debug("Remove FC Zone for mapping '%s'.",
|
LOG.debug("RemoveFCZone connection info: %(conninfo)s.",
|
||||||
init_target_map)
|
{'conninfo': conn_info})
|
||||||
zm.delete_connection(init_target_map)
|
zm.delete_connection(conn_info)
|
||||||
|
|
||||||
return conn_info
|
return conn_info
|
||||||
|
|
||||||
|
10
releasenotes/notes/friendly-zone-names-d5e131d356040de0.yaml
Normal file
10
releasenotes/notes/friendly-zone-names-d5e131d356040de0.yaml
Normal file
@ -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.
|
Loading…
Reference in New Issue
Block a user