diff --git a/cinder/opts.py b/cinder/opts.py index 0e210d695e0..969bccdac37 100644 --- a/cinder/opts.py +++ b/cinder/opts.py @@ -168,10 +168,6 @@ from cinder.zonemanager.drivers.brocade import brcd_fabric_opts as \ cinder_zonemanager_drivers_brocade_brcdfabricopts from cinder.zonemanager.drivers.brocade import brcd_fc_zone_driver as \ cinder_zonemanager_drivers_brocade_brcdfczonedriver -from cinder.zonemanager.drivers.cisco import cisco_fabric_opts as \ - cinder_zonemanager_drivers_cisco_ciscofabricopts -from cinder.zonemanager.drivers.cisco import cisco_fc_zone_driver as \ - cinder_zonemanager_drivers_cisco_ciscofczonedriver from cinder.zonemanager import fc_zone_manager as \ cinder_zonemanager_fczonemanager @@ -182,7 +178,6 @@ def list_opts(): itertools.chain( cinder_zonemanager_fczonemanager.zone_manager_opts, cinder_zonemanager_drivers_brocade_brcdfczonedriver.brcd_opts, - cinder_zonemanager_drivers_cisco_ciscofczonedriver.cisco_opts, )), ('KEYMGR', itertools.chain( @@ -342,11 +337,6 @@ def list_opts(): itertools.chain( cinder_service.profiler_opts, )), - ('CISCO_FABRIC_EXAMPLE', - itertools.chain( - cinder_zonemanager_drivers_cisco_ciscofabricopts. - cisco_zone_opts, - )), ('BRCD_FABRIC_EXAMPLE', itertools.chain( cinder_zonemanager_drivers_brocade_brcdfabricopts. diff --git a/cinder/tests/unit/zonemanager/test_cisco_fc_san_lookup_service.py b/cinder/tests/unit/zonemanager/test_cisco_fc_san_lookup_service.py deleted file mode 100644 index 1542853266d..00000000000 --- a/cinder/tests/unit/zonemanager/test_cisco_fc_san_lookup_service.py +++ /dev/null @@ -1,149 +0,0 @@ -# (c) Copyright 2014 Cisco 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 Cisco fc san lookup service.""" - -import mock -from oslo_config import cfg - -from cinder import exception -from cinder import test -from cinder.volume import configuration as conf -import cinder.zonemanager.drivers.cisco.cisco_fc_san_lookup_service \ - as cisco_lookup -import cinder.zonemanager.drivers.cisco.fc_zone_constants as ZoneConstant -from cinder.zonemanager import utils as zm_utils - -nsshow = '20:1a:00:05:1e:e8:e3:29' -switch_data = ['VSAN 304\n', - '------------------------------------------------------\n', - 'FCID TYPE PWWN (VENDOR) \n', - '------------------------------------------------------\n', - '0x030001 N 20:1a:00:05:1e:e8:e3:29 (Cisco) ipfc\n', - '0x030101 NL 10:00:00:00:77:99:60:2c (Interphase)\n', - '0x030200 N 10:00:00:49:c9:28:c7:01\n'] - -nsshow_data = ['10:00:8c:7c:ff:52:3b:01', '20:24:00:02:ac:00:0a:50'] - -_device_map_to_verify = { - '304': { - 'initiator_port_wwn_list': ['10008c7cff523b01'], - 'target_port_wwn_list': ['20240002ac000a50']}} - - -class TestCiscoFCSanLookupService(cisco_lookup.CiscoFCSanLookupService, - test.TestCase): - - def setUp(self): - super(TestCiscoFCSanLookupService, self).setUp() - self.configuration = conf.Configuration(None) - self.configuration.set_default('fc_fabric_names', 'CISCO_FAB_2', - 'fc-zone-manager') - self.configuration.fc_fabric_names = 'CISCO_FAB_2' - self.create_configuration() - self.fabric_vsan = '304' - - # override some of the functions - def __init__(self, *args, **kwargs): - test.TestCase.__init__(self, *args, **kwargs) - - def create_configuration(self): - fc_fabric_opts = [] - fc_fabric_opts.append(cfg.StrOpt('cisco_fc_fabric_address', - default='172.24.173.142', help='')) - fc_fabric_opts.append(cfg.StrOpt('cisco_fc_fabric_user', - default='admin', help='')) - fc_fabric_opts.append(cfg.StrOpt('cisco_fc_fabric_password', - default='admin1234', help='', - secret=True)) - fc_fabric_opts.append(cfg.PortOpt('cisco_fc_fabric_port', - default=22, help='')) - fc_fabric_opts.append(cfg.StrOpt('cisco_zoning_vsan', - default='304', help='')) - config = conf.Configuration(fc_fabric_opts, 'CISCO_FAB_2') - self.fabric_configs = {'CISCO_FAB_2': config} - - @mock.patch.object(cisco_lookup.CiscoFCSanLookupService, - 'get_nameserver_info') - def test_get_device_mapping_from_network(self, get_nameserver_info_mock): - initiator_list = ['10008c7cff523b01'] - target_list = ['20240002ac000a50', '20240002ac000a40'] - get_nameserver_info_mock.return_value = (nsshow_data) - device_map = self.get_device_mapping_from_network( - initiator_list, target_list) - self.assertDictMatch(_device_map_to_verify, device_map) - - @mock.patch.object(cisco_lookup.CiscoFCSanLookupService, - '_get_switch_info') - def test_get_nameserver_info(self, get_switch_data_mock): - ns_info_list = [] - ns_info_list_expected = ['20:1a:00:05:1e:e8:e3:29', - '10:00:00:49:c9:28:c7:01'] - get_switch_data_mock.return_value = (switch_data) - ns_info_list = self.get_nameserver_info('304') - self.assertEqual(ns_info_list_expected, ns_info_list) - - def test_parse_ns_output(self): - invalid_switch_data = [' N 011a00;20:1a:00:05:1e:e8:e3:29'] - return_wwn_list = [] - expected_wwn_list = ['20:1a:00:05:1e:e8:e3:29', - '10:00:00:49:c9:28:c7:01'] - return_wwn_list = self._parse_ns_output(switch_data) - self.assertEqual(expected_wwn_list, return_wwn_list) - self.assertRaises(exception.InvalidParameterValue, - self._parse_ns_output, invalid_switch_data) - - def test_get_formatted_wwn(self): - wwn_list = ['10008c7cff523b01'] - return_wwn_list = [] - expected_wwn_list = ['10:00:8c:7c:ff:52:3b:01'] - return_wwn_list.append(zm_utils.get_formatted_wwn(wwn_list[0])) - self.assertEqual(expected_wwn_list, return_wwn_list) - - @mock.patch.object(cisco_lookup.CiscoFCSanLookupService, - '_run_ssh') - def test__get_switch_info(self, run_ssh_mock): - cmd_list = [ZoneConstant.FCNS_SHOW, self.fabric_vsan, - ' | no-more'] - nsshow_list = [nsshow] - run_ssh_mock.return_value = (Stream(nsshow), Stream()) - switch_data = self._get_switch_info(cmd_list) - self.assertEqual(nsshow_list, switch_data) - run_ssh_mock.assert_called_once_with(cmd_list, True, 1) - - -class Channel(object): - def recv_exit_status(self): - return 0 - - -class Stream(object): - def __init__(self, buffer=''): - self.buffer = buffer - self.channel = Channel() - - def readlines(self): - return self.buffer - - def splitlines(self): - return self.buffer.splitlines() - - def close(self): - pass - - def flush(self): - self.buffer = '' diff --git a/cinder/tests/unit/zonemanager/test_cisco_fc_zone_client_cli.py b/cinder/tests/unit/zonemanager/test_cisco_fc_zone_client_cli.py deleted file mode 100644 index b3e155ed53f..00000000000 --- a/cinder/tests/unit/zonemanager/test_cisco_fc_zone_client_cli.py +++ /dev/null @@ -1,303 +0,0 @@ -# (c) Copyright 2014 Cisco 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 Cisco fc zone client cli.""" - -import time - -import mock -from oslo_concurrency import processutils -from six.moves import range - -from cinder import exception -from cinder import test -from cinder.zonemanager.drivers.cisco \ - import cisco_fc_zone_client_cli as cli -import cinder.zonemanager.drivers.cisco.fc_zone_constants as ZoneConstant - -nsshow = '20:1a:00:05:1e:e8:e3:29' -switch_data = ['VSAN 303\n', - '----------------------------------------------------------\n', - 'FCID TYPE PWWN (VENDOR) FC4-TYPE:FEATURE\n', - '----------------------------------------------------------\n', - '0x030001 N 20:1a:00:05:1e:e8:e3:29 (Cisco) ipfc\n', - '0x030101 NL 10:00:00:00:77:99:60:2c (Interphase)\n', - '0x030200 NL 10:00:00:49:c9:28:c7:01\n'] - -cfgactv = ['zoneset name OpenStack_Cfg vsan 303\n', - 'zone name openstack50060b0000c26604201900051ee8e329 vsan 303\n', - 'pwwn 50:06:0b:00:00:c2:66:04\n', - 'pwwn 20:19:00:05:1e:e8:e3:29\n'] - -active_zoneset = { - 'zones': { - 'openstack50060b0000c26604201900051ee8e329': - ['50:06:0b:00:00:c2:66:04', '20:19:00:05:1e:e8:e3:29']}, - 'active_zone_config': 'OpenStack_Cfg'} - -zoning_status_data_basic = [ - 'VSAN: 303 default-zone: deny distribute: active only Interop: default\n', - ' mode: basic merge-control: allow\n', - ' session: none\n', - ' hard-zoning: enabled broadcast: unsupported\n', - ' smart-zoning: disabled\n', - ' rscn-format: fabric-address\n', - 'Default zone:\n', - ' qos: none broadcast: unsupported ronly: unsupported\n', - 'Full Zoning Database :\n', - ' DB size: 220 bytes\n', - ' Zonesets:2 Zones:2 Aliases: 0\n', - 'Active Zoning Database :\n', - ' DB size: 80 bytes\n', - ' Name: test-zs-test Zonesets:1 Zones:1\n', - 'Status:\n'] - -zoning_status_basic = {'mode': 'basic', 'session': 'none'} - -zoning_status_data_enhanced_nosess = [ - 'VSAN: 303 default-zone: deny distribute: active only Interop: default\n', - ' mode: enhanced merge-control: allow\n', - ' session: none\n', - ' hard-zoning: enabled broadcast: unsupported\n', - ' smart-zoning: disabled\n', - ' rscn-format: fabric-address\n', - 'Default zone:\n', - ' qos: none broadcast: unsupported ronly: unsupported\n', - 'Full Zoning Database :\n', - ' DB size: 220 bytes\n', - ' Zonesets:2 Zones:2 Aliases: 0\n', - 'Active Zoning Database :\n', - ' DB size: 80 bytes\n', - ' Name: test-zs-test Zonesets:1 Zones:1\n', - 'Status:\n'] - -zoning_status_enhanced_nosess = {'mode': 'enhanced', 'session': 'none'} - -zoning_status_data_enhanced_sess = [ - 'VSAN: 303 default-zone: deny distribute: active only Interop: default\n', - ' mode: enhanced merge-control: allow\n', - ' session: otherthannone\n', - ' hard-zoning: enabled broadcast: unsupported\n', - ' smart-zoning: disabled\n', - ' rscn-format: fabric-address\n', - 'Default zone:\n', - ' qos: none broadcast: unsupported ronly: unsupported\n', - 'Full Zoning Database :\n', - ' DB size: 220 bytes\n', - ' Zonesets:2 Zones:2 Aliases: 0\n', - 'Active Zoning Database :\n', - ' DB size: 80 bytes\n', - ' Name: test-zs-test Zonesets:1 Zones:1\n', - 'Status:\n'] - -zoning_status_enhanced_sess = {'mode': 'enhanced', 'session': 'otherthannone'} - -active_zoneset_multiple_zones = { - 'zones': { - 'openstack50060b0000c26604201900051ee8e329': - ['50:06:0b:00:00:c2:66:04', '20:19:00:05:1e:e8:e3:29'], - 'openstack10000012345678902001009876543210': - ['50:06:0b:00:00:c2:66:02', '20:19:00:05:1e:e8:e3:27']}, - 'active_zone_config': 'OpenStack_Cfg'} - -new_zone = {'openstack10000012345678902001009876543210': - ['10:00:00:12:34:56:78:90', '20:01:00:98:76:54:32:10']} - -new_zones = {'openstack10000012345678902001009876543210': - ['10:00:00:12:34:56:78:90', '20:01:00:98:76:54:32:10'], - 'openstack10000011111111112001001111111111': - ['10:00:00:11:11:11:11:11', '20:01:00:11:11:11:11:11']} - -zone_names_to_delete = 'openstack50060b0000c26604201900051ee8e329' - - -class TestCiscoFCZoneClientCLI(cli.CiscoFCZoneClientCLI, test.TestCase): - - def setUp(self): - super(TestCiscoFCZoneClientCLI, self).setUp() - self.fabric_vsan = '303' - - # override some of the functions - def __init__(self, *args, **kwargs): - test.TestCase.__init__(self, *args, **kwargs) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_get_switch_info') - def test_get_active_zone_set(self, get_switch_info_mock): - cmd_list = [ZoneConstant.GET_ACTIVE_ZONE_CFG, self.fabric_vsan, - ' | no-more'] - get_switch_info_mock.return_value = cfgactv - active_zoneset_returned = self.get_active_zone_set() - get_switch_info_mock.assert_called_once_with(cmd_list) - self.assertDictMatch(active_zoneset, active_zoneset_returned) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - def test_get_active_zone_set_ssh_error(self, run_ssh_mock): - run_ssh_mock.side_effect = processutils.ProcessExecutionError - self.assertRaises(exception.CiscoZoningCliException, - self.get_active_zone_set) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_get_switch_info') - def test_get_zoning_status_basic(self, get_zoning_status_mock): - cmd_list = [ZoneConstant.GET_ZONE_STATUS, self.fabric_vsan] - get_zoning_status_mock.return_value = zoning_status_data_basic - zoning_status_returned = self.get_zoning_status() - get_zoning_status_mock.assert_called_once_with(cmd_list) - self.assertDictMatch(zoning_status_basic, zoning_status_returned) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_get_switch_info') - def test_get_zoning_status_enhanced_nosess(self, get_zoning_status_mock): - cmd_list = [ZoneConstant.GET_ZONE_STATUS, self.fabric_vsan] - get_zoning_status_mock.return_value =\ - zoning_status_data_enhanced_nosess - zoning_status_returned = self.get_zoning_status() - get_zoning_status_mock.assert_called_once_with(cmd_list) - self.assertDictMatch(zoning_status_enhanced_nosess, - zoning_status_returned) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_get_switch_info') - def test_get_zoning_status_enhanced_sess(self, get_zoning_status_mock): - cmd_list = [ZoneConstant.GET_ZONE_STATUS, self.fabric_vsan] - get_zoning_status_mock.return_value = zoning_status_data_enhanced_sess - zoning_status_returned = self.get_zoning_status() - get_zoning_status_mock.assert_called_once_with(cmd_list) - self.assertDictMatch(zoning_status_enhanced_sess, - zoning_status_returned) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_get_switch_info') - def test_get_nameserver_info(self, get_switch_info_mock): - ns_info_list = [] - ns_info_list_expected = ['20:1a:00:05:1e:e8:e3:29'] - get_switch_info_mock.return_value = (switch_data) - ns_info_list = self.get_nameserver_info() - self.assertEqual(ns_info_list_expected, ns_info_list) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - def test_get_nameserver_info_ssh_error(self, run_ssh_mock): - run_ssh_mock.side_effect = processutils.ProcessExecutionError - self.assertRaises(exception.CiscoZoningCliException, - self.get_nameserver_info) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - def test__cfg_save(self, run_ssh_mock): - cmd_list = ['copy', 'running-config', 'startup-config'] - self._cfg_save() - run_ssh_mock.assert_called_once_with(cmd_list, True) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - @mock.patch.object(time, 'sleep') - def test__cfg_save_with_retry(self, mock_sleep, run_ssh_mock): - cmd_list = ['copy', 'running-config', 'startup-config'] - run_ssh_mock.side_effect = [ - processutils.ProcessExecutionError, - ('', None) - ] - - self._cfg_save() - - self.assertEqual(2, run_ssh_mock.call_count) - run_ssh_mock.assert_has_calls([ - mock.call(cmd_list, True), - mock.call(cmd_list, True) - ]) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - @mock.patch.object(time, 'sleep') - def test__cfg_save_with_error(self, mock_sleep, run_ssh_mock): - cmd_list = ['copy', 'running-config', 'startup-config'] - run_ssh_mock.side_effect = processutils.ProcessExecutionError - - self.assertRaises(processutils.ProcessExecutionError, self._cfg_save) - - expected_num_calls = 5 - expected_calls = [] - for i in range(expected_num_calls): - expected_calls.append(mock.call(cmd_list, True)) - - self.assertEqual(expected_num_calls, run_ssh_mock.call_count) - run_ssh_mock.assert_has_calls(expected_calls) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_run_ssh') - def test__get_switch_info(self, run_ssh_mock): - cmd_list = [ZoneConstant.FCNS_SHOW, self.fabric_vsan] - nsshow_list = [nsshow] - run_ssh_mock.return_value = (Stream(nsshow), Stream()) - switch_data = self._get_switch_info(cmd_list) - self.assertEqual(nsshow_list, switch_data) - run_ssh_mock.assert_called_once_with(cmd_list, True) - - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_ssh_execute') - @mock.patch.object(cli.CiscoFCZoneClientCLI, '_cfg_save') - def test__add_zones_with_update(self, ssh_execute_mock, cfg_save_mock): - self.add_zones(new_zone, False, self.fabric_vsan, - active_zoneset_multiple_zones, - zoning_status_basic) - self.assertEqual(2, ssh_execute_mock.call_count) - self.assertEqual(2, cfg_save_mock.call_count) - - def test__parse_ns_output(self): - return_wwn_list = [] - expected_wwn_list = ['20:1a:00:05:1e:e8:e3:29'] - return_wwn_list = self._parse_ns_output(switch_data) - self.assertEqual(expected_wwn_list, return_wwn_list) - - -class TestCiscoFCZoneClientCLISSH(test.TestCase): - - def setUp(self): - super(TestCiscoFCZoneClientCLISSH, self).setUp() - self.client = cli.CiscoFCZoneClientCLI(None, None, None, None, None) - self.client.sshpool = mock.MagicMock() - self.mock_ssh = self.client.sshpool.item().__enter__() - - @mock.patch('oslo_concurrency.processutils.ssh_execute') - def test__run_ssh(self, mock_execute): - mock_execute.return_value = 'ssh output' - ret = self.client._run_ssh(['cat', 'foo']) - self.assertEqual('ssh output', ret) - mock_execute.assert_called_once_with(self.mock_ssh, - 'cat foo', - check_exit_code=True) - - @mock.patch('oslo_concurrency.processutils.ssh_execute') - def test__run_ssh_with_error(self, mock_execute): - mock_execute.side_effect = processutils.ProcessExecutionError() - self.assertRaises(processutils.ProcessExecutionError, - self.client._run_ssh, - ['cat', 'foo']) - - -class Channel(object): - def recv_exit_status(self): - return 0 - - -class Stream(object): - def __init__(self, buffer=''): - self.buffer = buffer - self.channel = Channel() - - def readlines(self): - return self.buffer - - def splitlines(self): - return self.buffer.splitlines() - - def close(self): - pass - - def flush(self): - self.buffer = '' diff --git a/cinder/tests/unit/zonemanager/test_cisco_fc_zone_driver.py b/cinder/tests/unit/zonemanager/test_cisco_fc_zone_driver.py deleted file mode 100644 index 42e5c555cfd..00000000000 --- a/cinder/tests/unit/zonemanager/test_cisco_fc_zone_driver.py +++ /dev/null @@ -1,208 +0,0 @@ -# (c) Copyright 2014 Cisco 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 Cisco FC zone driver.""" - -from oslo_concurrency import processutils -from oslo_config import cfg -from oslo_utils import importutils - -from cinder import exception -from cinder import test -from cinder.volume import configuration as conf - -_active_cfg_before_add = {} -_active_cfg_before_delete = { - 'zones': { - 'openstack10008c7cff523b0120240002ac000a50': ( - ['10:00:8c:7c:ff:52:3b:01', - '20:24:00:02:ac:00:0a:50'])}, - 'active_zone_config': 'cfg1'} -_activate = True -_zone_name = 'openstack10008c7cff523b0120240002ac000a50' -_target_ns_map = {'100000051e55a100': ['20240002ac000a50']} -_zoning_status = {'mode': 'basis', 'session': 'none'} -_initiator_ns_map = {'100000051e55a100': ['10008c7cff523b01']} -_zone_map_to_add = {'openstack10008c7cff523b0120240002ac000a50': ( - ['10:00:8c:7c:ff:52:3b:01', '20:24:00:02:ac:00:0a:50'])} - -_initiator_target_map = {'10008c7cff523b01': ['20240002ac000a50']} -_device_map_to_verify = { - '304': { - 'initiator_port_wwn_list': [ - '10008c7cff523b01'], 'target_port_wwn_list': ['20240002ac000a50']}} -_fabric_wwn = '304' - - -class CiscoFcZoneDriverBaseTest(object): - - def setup_config(self, is_normal, mode): - fc_test_opts = [ - cfg.StrOpt('fc_fabric_address_CISCO_FAB_1', default='10.24.48.213', - help='FC Fabric names'), - ] - configuration = conf.Configuration(fc_test_opts) - # fill up config - configuration.zoning_mode = 'fabric' - configuration.zone_driver = ('cinder.tests.unit.zonemanager.' - 'test_cisco_fc_zone_driver.' - 'FakeCiscoFCZoneDriver') - configuration.cisco_sb_connector = ('cinder.tests.unit.zonemanager.' - 'test_cisco_fc_zone_driver' - '.FakeCiscoFCZoneClientCLI') - configuration.zoning_policy = 'initiator-target' - configuration.zone_activate = True - configuration.zone_name_prefix = 'openstack' - configuration.fc_san_lookup_service = ('cinder.tests.unit.zonemanager.' - 'test_cisco_fc_zone_driver.' - 'FakeCiscoFCSanLookupService') - - configuration.fc_fabric_names = 'CISCO_FAB_1' - configuration.fc_fabric_address_CISCO_FAB_1 = '172.21.60.220' - if (is_normal): - configuration.fc_fabric_user_CISCO_FAB_1 = 'admin' - else: - configuration.fc_fabric_user_CISCO_FAB_1 = 'invaliduser' - configuration.fc_fabric_password_CISCO_FAB_1 = 'admin1234' - - if (mode == 1): - configuration.zoning_policy_CISCO_FAB_1 = 'initiator-target' - elif (mode == 2): - configuration.zoning_policy_CISCO_FAB_1 = 'initiator' - else: - configuration.zoning_policy_CISCO_FAB_1 = 'initiator-target' - configuration.zone_activate_CISCO_FAB_1 = True - configuration.zone_name_prefix_CISCO_FAB_1 = 'openstack' - configuration.zoning_vsan_CISCO_FAB_1 = '304' - return configuration - - -class TestCiscoFcZoneDriver(CiscoFcZoneDriverBaseTest, test.TestCase): - - def setUp(self): - super(TestCiscoFcZoneDriver, self).setUp() - # setup config for normal flow - self.setup_driver(self.setup_config(True, 1)) - GlobalVars._zone_state = [] - - def setup_driver(self, config): - self.driver = importutils.import_object( - 'cinder.zonemanager.drivers.cisco.cisco_fc_zone_driver' - '.CiscoFCZoneDriver', configuration=config) - - def fake_get_active_zone_set(self, fabric_ip, fabric_user, fabric_pwd, - zoning_vsan): - return GlobalVars._active_cfg - - def fake_get_san_context(self, target_wwn_list): - fabric_map = {} - return fabric_map - - def test_delete_connection(self): - GlobalVars._is_normal_test = True - GlobalVars._active_cfg = _active_cfg_before_delete - self.driver.delete_connection( - 'CISCO_FAB_1', _initiator_target_map) - self.assertFalse(_zone_name in GlobalVars._zone_state) - - def test_delete_connection_for_initiator_mode(self): - GlobalVars._is_normal_test = True - GlobalVars._active_cfg = _active_cfg_before_delete - self.setup_driver(self.setup_config(True, 2)) - self.driver.delete_connection( - 'CISCO_FAB_1', _initiator_target_map) - self.assertFalse(_zone_name in GlobalVars._zone_state) - - def test_add_connection_for_invalid_fabric(self): - """Test abnormal flows.""" - GlobalVars._is_normal_test = True - GlobalVars._active_cfg = _active_cfg_before_add - GlobalVars._is_normal_test = False - self.setup_driver(self.setup_config(False, 1)) - self.assertRaises(exception.FCZoneDriverException, - self.driver.add_connection, - 'CISCO_FAB_1', - _initiator_target_map) - - def test_delete_connection_for_invalid_fabric(self): - GlobalVars._active_cfg = _active_cfg_before_delete - GlobalVars._is_normal_test = False - self.setup_driver(self.setup_config(False, 1)) - self.assertRaises(exception.FCZoneDriverException, - self.driver.delete_connection, - 'CISCO_FAB_1', - _initiator_target_map) - - -class FakeCiscoFCZoneClientCLI(object): - def __init__(self, ipaddress, username, password, port, vsan): - if not GlobalVars._is_normal_test: - raise processutils.ProcessExecutionError( - "Unable to connect to fabric") - - def get_active_zone_set(self): - return GlobalVars._active_cfg - - def add_zones(self, zones, isActivate): - GlobalVars._zone_state.extend(zones.keys()) - - def delete_zones(self, zone_names, isActivate): - zone_list = zone_names.split(';') - GlobalVars._zone_state = [ - x for x in GlobalVars._zone_state if x not in zone_list] - - def get_nameserver_info(self): - return _target_ns_map - - def get_zoning_status(self): - return _zoning_status - - def close_connection(self): - pass - - def cleanup(self): - pass - - -class FakeCiscoFCSanLookupService(object): - def get_device_mapping_from_network(self, - initiator_wwn_list, - target_wwn_list): - device_map = {} - initiators = [] - targets = [] - for i in initiator_wwn_list: - if (i in _initiator_ns_map[_fabric_wwn]): - initiators.append(i) - for t in target_wwn_list: - if (t in _target_ns_map[_fabric_wwn]): - targets.append(t) - device_map[_fabric_wwn] = { - 'initiator_port_wwn_list': initiators, - 'target_port_wwn_list': targets} - return device_map - - -class GlobalVars(object): - global _active_cfg - _active_cfg = {} - global _zone_state - _zone_state = list() - global _is_normal_test - _is_normal_test = True - global _zoning_status - _zoning_status = {} diff --git a/cinder/tests/unit/zonemanager/test_cisco_lookup_service.py b/cinder/tests/unit/zonemanager/test_cisco_lookup_service.py deleted file mode 100644 index 678fd83da2b..00000000000 --- a/cinder/tests/unit/zonemanager/test_cisco_lookup_service.py +++ /dev/null @@ -1,96 +0,0 @@ -# (c) Copyright 2014 Cisco 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 Cisco FC san lookup service.""" - -from cinder import exception -from cinder import test -from cinder.volume import configuration as conf -from cinder.zonemanager import fc_san_lookup_service as san_service - -_target_ns_map = {'100000051e55a100': ['20240002ac000a50']} -_initiator_ns_map = {'100000051e55a100': ['10008c7cff523b01']} -_device_map_to_verify = { - '100000051e55a100': { - 'initiator_port_wwn_list': [ - '10008c7cff523b01'], 'target_port_wwn_list': ['20240002ac000a50']}} -_fabric_wwn = '100000051e55a100' - - -class TestFCSanLookupService(san_service.FCSanLookupService, test.TestCase): - - def setUp(self): - super(TestFCSanLookupService, self).setUp() - self.configuration = self.setup_config() - - # override some of the functions - def __init__(self, *args, **kwargs): - test.TestCase.__init__(self, *args, **kwargs) - - def setup_config(self): - configuration = conf.Configuration(None) - # fill up config - configuration.fc_san_lookup_service = ('cinder.tests.unit.zonemanager' - '.test_cisco_lookup_service' - '.FakeCiscoFCSanLookupService') - return configuration - - def test_get_device_mapping_from_network(self): - GlobalParams._is_normal_test = True - initiator_list = ['10008c7cff523b01'] - target_list = ['20240002ac000a50', '20240002ac000a40'] - device_map = self.get_device_mapping_from_network( - initiator_list, target_list) - self.assertDictMatch(_device_map_to_verify, device_map) - - def test_get_device_mapping_from_network_for_invalid_config(self): - GlobalParams._is_normal_test = False - initiator_list = ['10008c7cff523b01'] - target_list = ['20240002ac000a50', '20240002ac000a40'] - self.assertRaises(exception.FCSanLookupServiceException, - self.get_device_mapping_from_network, - initiator_list, target_list) - - -class FakeCiscoFCSanLookupService(object): - - def __init__(self, **kwargs): - pass - - def get_device_mapping_from_network(self, - initiator_wwn_list, - target_wwn_list): - if not GlobalParams._is_normal_test: - raise exception.FCSanLookupServiceException("Error") - device_map = {} - initiators = [] - targets = [] - for i in initiator_wwn_list: - if (i in _initiator_ns_map[_fabric_wwn]): - initiators.append(i) - for t in target_wwn_list: - if (t in _target_ns_map[_fabric_wwn]): - targets.append(t) - device_map[_fabric_wwn] = { - 'initiator_port_wwn_list': initiators, - 'target_port_wwn_list': targets} - return device_map - - -class GlobalParams(object): - global _is_normal_test - _is_normal_test = True diff --git a/cinder/zonemanager/drivers/cisco/__init__.py b/cinder/zonemanager/drivers/cisco/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/cinder/zonemanager/drivers/cisco/cisco_fabric_opts.py b/cinder/zonemanager/drivers/cisco/cisco_fabric_opts.py deleted file mode 100644 index 524dcc1e9a6..00000000000 --- a/cinder/zonemanager/drivers/cisco/cisco_fabric_opts.py +++ /dev/null @@ -1,56 +0,0 @@ -# (c) Copyright 2014 Cisco 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. -# -from oslo_config import cfg - -from cinder.volume import configuration - -cisco_zone_opts = [ - cfg.StrOpt('cisco_fc_fabric_address', - default='', - help='Management IP of fabric'), - cfg.StrOpt('cisco_fc_fabric_user', - default='', - help='Fabric user ID'), - cfg.StrOpt('cisco_fc_fabric_password', - default='', - help='Password for user', - secret=True), - cfg.PortOpt('cisco_fc_fabric_port', - default=22, - help='Connecting port'), - cfg.StrOpt('cisco_zoning_policy', - default='initiator-target', - help='overridden zoning policy'), - cfg.BoolOpt('cisco_zone_activate', - default=True, - help='overridden zoning activation state'), - cfg.StrOpt('cisco_zone_name_prefix', - help='overridden zone name prefix'), - cfg.StrOpt('cisco_zoning_vsan', - help='VSAN of the Fabric'), -] - -CONF = cfg.CONF -CONF.register_opts(cisco_zone_opts, group='CISCO_FABRIC_EXAMPLE') - - -def load_fabric_configurations(fabric_names): - fabric_configs = {} - for fabric_name in fabric_names: - config = configuration.Configuration(cisco_zone_opts, fabric_name) - fabric_configs[fabric_name] = config - - return fabric_configs diff --git a/cinder/zonemanager/drivers/cisco/cisco_fc_san_lookup_service.py b/cinder/zonemanager/drivers/cisco/cisco_fc_san_lookup_service.py deleted file mode 100644 index 77aaaa90bff..00000000000 --- a/cinder/zonemanager/drivers/cisco/cisco_fc_san_lookup_service.py +++ /dev/null @@ -1,355 +0,0 @@ -# (c) Copyright 2014 Cisco 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. -# - - -import random - -from eventlet import greenthread -from oslo_concurrency import processutils -from oslo_log import log as logging -from oslo_utils import excutils -import six - -from cinder import exception -from cinder.i18n import _, _LE -from cinder import ssh_utils -from cinder import utils -from cinder.zonemanager.drivers.cisco import cisco_fabric_opts as fabric_opts -import cinder.zonemanager.drivers.cisco.fc_zone_constants as zone_constant -from cinder.zonemanager import fc_san_lookup_service as fc_service -from cinder.zonemanager import utils as zm_utils - -LOG = logging.getLogger(__name__) - - -class CiscoFCSanLookupService(fc_service.FCSanLookupService): - """The SAN lookup service that talks to Cisco switches. - - Version History: - 1.0.0 - Initial version - - """ - - VERSION = "1.0.0" - - def __init__(self, **kwargs): - """Initializing the client.""" - super(CiscoFCSanLookupService, self).__init__(**kwargs) - self.configuration = kwargs.get('configuration', None) - self.create_configuration() - - self.switch_user = "" - self.switch_port = "" - self.switch_pwd = "" - self.switch_ip = "" - self.sshpool = None - - def create_configuration(self): - """Configuration specific to SAN context values.""" - config = self.configuration - - fabric_names = [x.strip() for x in config.fc_fabric_names.split(',')] - LOG.debug('Fabric Names: %s', fabric_names) - - # There can be more than one SAN in the network and we need to - # get credentials for each for SAN context lookup later. - # Cisco Zonesets require VSANs - if fabric_names: - self.fabric_configs = fabric_opts.load_fabric_configurations( - fabric_names) - - def get_device_mapping_from_network(self, - initiator_wwn_list, - target_wwn_list): - """Provides the initiator/target map for available SAN contexts. - - Looks up fcns database of each fc SAN configured to find logged in - devices and returns a map of initiator and target port WWNs for each - fabric. - - :param initiator_wwn_list: List of initiator port WWN - :param target_wwn_list: List of target port WWN - :returns: List -- device wwn map in following format - { - : { - 'initiator_port_wwn_list': - ('200000051e55a100', '200000051e55a121'..) - 'target_port_wwn_list': - ('100000051e55a100', '100000051e55a121'..) - } - } - :raises: Exception when connection to fabric is failed - """ - device_map = {} - formatted_target_list = [] - formatted_initiator_list = [] - fabric_map = {} - fabric_names = self.configuration.fc_fabric_names - - if not fabric_names: - raise exception.InvalidParameterValue( - err=_("Missing Fibre Channel SAN configuration " - "param - fc_fabric_names")) - - fabrics = [x.strip() for x in fabric_names.split(',')] - - LOG.debug("FC Fabric List: %s", fabrics) - if fabrics: - for t in target_wwn_list: - formatted_target_list.append(zm_utils.get_formatted_wwn(t)) - - for i in initiator_wwn_list: - formatted_initiator_list.append(zm_utils.get_formatted_wwn(i)) - - for fabric_name in fabrics: - self.switch_ip = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_address') - self.switch_user = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_user') - self.switch_pwd = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_password') - self.switch_port = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_port') - zoning_vsan = self.fabric_configs[fabric_name].safe_get( - 'cisco_zoning_vsan') - - # Get name server data from fabric and find the targets - # logged in - nsinfo = '' - LOG.debug("show fcns database for vsan %s", zoning_vsan) - nsinfo = self.get_nameserver_info(zoning_vsan) - - LOG.debug("Lookup service:fcnsdatabase-%s", nsinfo) - LOG.debug("Lookup service:initiator list from caller-%s", - formatted_initiator_list) - LOG.debug("Lookup service:target list from caller-%s", - formatted_target_list) - visible_targets = [x for x in nsinfo - if x in formatted_target_list] - visible_initiators = [x for x in nsinfo - if x in formatted_initiator_list] - - if visible_targets: - LOG.debug("Filtered targets is: %s", visible_targets) - # getting rid of the : before returning - for idx, elem in enumerate(visible_targets): - elem = str(elem).replace(':', '') - visible_targets[idx] = elem - else: - LOG.debug("No targets are in the fcns database" - " for vsan %s", zoning_vsan) - - if visible_initiators: - # getting rid of the : before returning ~sk - for idx, elem in enumerate(visible_initiators): - elem = str(elem).replace(':', '') - visible_initiators[idx] = elem - else: - LOG.debug("No initiators are in the fcns database" - " for vsan %s", zoning_vsan) - - fabric_map = {'initiator_port_wwn_list': visible_initiators, - 'target_port_wwn_list': visible_targets - } - device_map[zoning_vsan] = fabric_map - LOG.debug("Device map for SAN context: %s", device_map) - return device_map - - def get_nameserver_info(self, fabric_vsan): - """Get fcns database info from fabric. - - This method will return the connected node port wwn list(local - and remote) for the given switch fabric - """ - cli_output = None - nsinfo_list = [] - try: - cmd = ([zone_constant.FCNS_SHOW, fabric_vsan, ' | no-more']) - cli_output = self._get_switch_info(cmd) - except exception.FCSanLookupServiceException: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed collecting show fcns database for" - " fabric")) - if cli_output: - nsinfo_list = self._parse_ns_output(cli_output) - - LOG.debug("Connector returning fcns info-%s", nsinfo_list) - return nsinfo_list - - def _get_switch_info(self, cmd_list): - stdout, stderr, sw_data = None, None, None - try: - stdout, stderr = self._run_ssh(cmd_list, True, 1) - LOG.debug("CLI output from ssh - output: %s", stdout) - if (stdout): - sw_data = stdout.splitlines() - return sw_data - except processutils.ProcessExecutionError as e: - msg = _("Error while getting data via ssh: (command=%(cmd)s " - "error=%(err)s).") % {'cmd': cmd_list, - 'err': six.text_type(e)} - LOG.error(msg) - raise exception.CiscoZoningCliException(reason=msg) - - def _parse_ns_output(self, switch_data): - """Parses name server data. - - Parses nameserver raw data and adds the device port wwns to the list - - :returns: list of device port wwn from ns info - """ - nsinfo_list = [] - for line in switch_data: - if not(" N " in line): - continue - linesplit = line.split() - if len(linesplit) > 2: - node_port_wwn = linesplit[2] - nsinfo_list.append(node_port_wwn) - else: - msg = _("Malformed fcns output string: %s") % line - LOG.error(msg) - raise exception.InvalidParameterValue(err=msg) - return nsinfo_list - - def _run_ssh(self, cmd_list, check_exit_code=True, attempts=1): - - command = ' '.join(cmd_list) - - if not self.sshpool: - self.sshpool = ssh_utils.SSHPool(self.switch_ip, - self.switch_port, - None, - self.switch_user, - self.switch_pwd, - min_size=1, - max_size=5) - last_exception = None - try: - with self.sshpool.item() as ssh: - while attempts > 0: - attempts -= 1 - try: - return processutils.ssh_execute( - ssh, - command, - check_exit_code=check_exit_code) - except Exception as e: - msg = _("Exception: %s") % six.text_type(e) - LOG.error(msg) - last_exception = e - greenthread.sleep(random.randint(20, 500) / 100.0) - try: - raise processutils.ProcessExecutionError( - exit_code=last_exception.exit_code, - stdout=last_exception.stdout, - stderr=last_exception.stderr, - cmd=last_exception.cmd) - except AttributeError: - raise processutils.ProcessExecutionError( - exit_code=-1, - stdout="", - stderr="Error running SSH command", - cmd=command) - except Exception: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Error running SSH command: %s"), command) - - def _ssh_execute(self, cmd_list, check_exit_code=True, attempts=1): - """Execute cli with status update. - - Executes CLI commands where status return is expected. - - cmd_list is a list of commands, where each command is itself - a list of parameters. We use utils.check_ssh_injection to check each - command, but then join then with " ; " to form a single command. - """ - - # Check that each command is secure - for cmd in cmd_list: - utils.check_ssh_injection(cmd) - - # Combine into a single command. - command = ' ; '.join(map(lambda x: ' '.join(x), cmd_list)) - - if not self.sshpool: - self.sshpool = ssh_utils.SSHPool(self.switch_ip, - self.switch_port, - None, - self.switch_user, - self.switch_pwd, - min_size=1, - max_size=5) - stdin, stdout, stderr = None, None, None - LOG.debug("Executing command via ssh: %s", command) - last_exception = None - try: - with self.sshpool.item() as ssh: - while attempts > 0: - attempts -= 1 - try: - stdin, stdout, stderr = ssh.exec_command(command) - greenthread.sleep(random.randint(20, 500) / 100.0) - channel = stdout.channel - exit_status = channel.recv_exit_status() - LOG.debug("Exit Status from ssh:%s", exit_status) - # exit_status == -1 if no exit code was returned - if exit_status != -1: - LOG.debug('Result was %s', exit_status) - if check_exit_code and exit_status != 0: - raise processutils.ProcessExecutionError( - exit_code=exit_status, - stdout=stdout, - stderr=stderr, - cmd=command) - else: - return True - else: - return True - except Exception as e: - msg = _("Exception: %s") % six.text_type(e) - LOG.error(msg) - last_exception = e - greenthread.sleep(random.randint(20, 500) / 100.0) - LOG.debug("Handling error case after SSH:%s", last_exception) - try: - raise processutils.ProcessExecutionError( - exit_code=last_exception.exit_code, - stdout=last_exception.stdout, - stderr=last_exception.stderr, - cmd=last_exception.cmd) - except AttributeError: - raise processutils.ProcessExecutionError( - exit_code=-1, - stdout="", - stderr="Error running SSH command", - cmd=command) - except Exception as e: - with excutils.save_and_reraise_exception(): - msg = (_("Error executing command via ssh: %s") % - six.text_type(e)) - LOG.error(msg) - finally: - if stdin: - stdin.flush() - stdin.close() - if stdout: - stdout.close() - if stderr: - stderr.close() - - def cleanup(self): - self.sshpool = None diff --git a/cinder/zonemanager/drivers/cisco/cisco_fc_zone_client_cli.py b/cinder/zonemanager/drivers/cisco/cisco_fc_zone_client_cli.py deleted file mode 100644 index 924dbe35592..00000000000 --- a/cinder/zonemanager/drivers/cisco/cisco_fc_zone_client_cli.py +++ /dev/null @@ -1,460 +0,0 @@ -# (c) Copyright 2014 Cisco 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. -# - - -""" -Script to push the zone configuration to Cisco SAN switches. -""" -import random -import re - -from eventlet import greenthread -from oslo_concurrency import processutils -from oslo_log import log as logging -from oslo_utils import excutils -import six - -from cinder import exception -from cinder.i18n import _, _LE, _LI, _LW -from cinder import ssh_utils -from cinder import utils -import cinder.zonemanager.drivers.cisco.fc_zone_constants as ZoneConstant - -LOG = logging.getLogger(__name__) - - -class CiscoFCZoneClientCLI(object): - """Cisco FC zone client cli implementation. - - OpenStack Fibre Channel zone client cli connector - to manage FC zoning in Cisco SAN fabrics. - - Version history: - 1.0 - Initial Cisco FC zone client cli - """ - - switch_ip = None - switch_port = '22' - switch_user = 'admin' - switch_pwd = 'none' - - def __init__(self, ipaddress, username, password, port, vsan): - """initializing the client.""" - self.switch_ip = ipaddress - self.switch_port = port - self.switch_user = username - self.switch_pwd = password - self.fabric_vsan = vsan - self.sshpool = None - - def get_active_zone_set(self): - """Return the active zone configuration. - - Return active zoneset from fabric. When none of the configurations - are active then it will return empty map. - - :returns: Map -- active zone set map in the following format - { - 'zones': - {'openstack50060b0000c26604201900051ee8e329': - ['50060b0000c26604', '201900051ee8e329'] - }, - 'active_zone_config': 'OpenStack_Cfg' - } - """ - zone_set = {} - zone = {} - zone_member = None - zone_name = None - switch_data = None - zone_set_name = None - try: - switch_data = self._get_switch_info( - [ZoneConstant.GET_ACTIVE_ZONE_CFG, self.fabric_vsan, - ' | no-more']) - except exception.CiscoZoningCliException: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed getting active zone set " - "from fabric %s"), self.switch_ip) - try: - for line in switch_data: - # Split on non-word characters, - line_split = re.split('[\s\[\]]+', line) - if ZoneConstant.CFG_ZONESET in line_split: - # zoneset name [name] vsan [vsan] - zone_set_name = \ - line_split[line_split.index(ZoneConstant.CFG_ZONESET) - + 2] - continue - if ZoneConstant.CFG_ZONE in line_split: - # zone name [name] vsan [vsan] - zone_name = \ - line_split[line_split.index(ZoneConstant.CFG_ZONE) + 2] - zone[zone_name] = list() - continue - if ZoneConstant.CFG_ZONE_MEMBER in line_split: - # Examples: - # pwwn c0:50:76:05:15:9f:00:12 - # * fcid 0x1e01c0 [pwwn 50:05:07:68:02:20:48:04] [V7K_N1P2] - zone_member = \ - line_split[ - line_split.index(ZoneConstant.CFG_ZONE_MEMBER) + 1] - zone_member_list = zone.get(zone_name) - zone_member_list.append(zone_member) - - zone_set[ZoneConstant.CFG_ZONES] = zone - zone_set[ZoneConstant.ACTIVE_ZONE_CONFIG] = zone_set_name - except Exception as ex: - # In case of parsing error here, it should be malformed cli output. - msg = _("Malformed zone configuration: (switch=%(switch)s " - "zone_config=%(zone_config)s)." - ) % {'switch': self.switch_ip, - 'zone_config': switch_data} - LOG.error(msg) - exc_msg = _("Exception: %s") % six.text_type(ex) - LOG.error(exc_msg) - raise exception.FCZoneDriverException(reason=msg) - - return zone_set - - def add_zones(self, zones, activate, fabric_vsan, active_zone_set, - zone_status): - """Add zone configuration. - - This method will add the zone configuration passed by user. - input params: - zones - zone names mapped to members and VSANs. - zone members are colon separated but case-insensitive - { zonename1:[zonememeber1,zonemember2,...], - zonename2:[zonemember1, zonemember2,...]...} - e.g: {'openstack50060b0000c26604201900051ee8e329': - ['50:06:0b:00:00:c2:66:04', '20:19:00:05:1e:e8:e3:29'] - } - activate - True/False - """ - LOG.debug("Add Zones - Zones passed: %s", zones) - - LOG.debug("Active zone set: %s", active_zone_set) - zone_list = active_zone_set[ZoneConstant.CFG_ZONES] - LOG.debug("zone list: %s", zone_list) - LOG.debug("zone status: %s", zone_status) - - cfg_name = active_zone_set[ZoneConstant.ACTIVE_ZONE_CONFIG] - - zone_cmds = [['conf'], - ['zoneset', 'name', cfg_name, 'vsan', fabric_vsan]] - - for zone in zones.keys(): - # if zone exists, its an update. Delete & insert - LOG.debug("Update call") - if zone in zone_list: - # Response from get_active_zone_set strips colons from WWPNs - current_zone = set(zone_list[zone]) - new_wwpns = map(lambda x: x.lower().replace(':', ''), - zones[zone]) - new_zone = set(new_wwpns) - - if current_zone != new_zone: - try: - self.delete_zones(zone, activate, fabric_vsan, - active_zone_set, zone_status) - except exception.CiscoZoningCliException: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Deleting zone failed %s"), zone) - LOG.debug("Deleted Zone before insert : %s", zone) - - zone_cmds.append(['zone', 'name', zone]) - - for member in zones[zone]: - zone_cmds.append(['member', 'pwwn', member]) - - zone_cmds.append(['end']) - - try: - LOG.debug("Add zones: Config cmd to run: %s", zone_cmds) - self._ssh_execute(zone_cmds, True, 1) - - if activate: - self.activate_zoneset(cfg_name, fabric_vsan, zone_status) - self._cfg_save() - except Exception as e: - - msg = _("Creating and activating zone set failed: " - "(Zone set=%(zoneset)s error=%(err)s)." - ) % {'zoneset': cfg_name, 'err': six.text_type(e)} - LOG.error(msg) - raise exception.CiscoZoningCliException(reason=msg) - - def activate_zoneset(self, cfgname, fabric_vsan, zone_status): - """Method to Activate the zone config. Param cfgname - ZonesetName.""" - - LOG.debug("zone status: %s", zone_status) - - cmd_list = [['conf'], - ['zoneset', 'activate', 'name', cfgname, 'vsan', - self.fabric_vsan]] - if zone_status['mode'] == 'enhanced': - cmd_list.append(['zone', 'commit', 'vsan', fabric_vsan]) - - cmd_list.append(['end']) - - return self._ssh_execute(cmd_list, True, 1) - - def get_zoning_status(self): - """Return the zoning mode and session for a zoneset.""" - zone_status = {} - - try: - switch_data = self._get_switch_info( - [ZoneConstant.GET_ZONE_STATUS, self.fabric_vsan]) - except exception.CiscoZoningCliException: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed getting zone status " - "from fabric %s"), self.switch_ip) - try: - for line in switch_data: - # Split on non-word characters, - line_split = re.split('[\s\[\]]+', line) - if 'mode:' in line_split: - # mode: - zone_status['mode'] = line_split[line_split.index('mode:') - + 1] - continue - if 'session:' in line_split: - # session: - zone_status['session'] = \ - line_split[line_split.index('session:') + 1] - continue - except Exception as ex: - # In case of parsing error here, it should be malformed cli output. - msg = _("Malformed zone status: (switch=%(switch)s " - "zone_config=%(zone_config)s)." - ) % {'switch': self.switch_ip, - 'zone_status': switch_data} - LOG.error(msg) - exc_msg = _("Exception: %s") % six.text_type(ex) - LOG.error(exc_msg) - raise exception.FCZoneDriverException(reason=msg) - - return zone_status - - def delete_zones(self, zone_names, activate, fabric_vsan, active_zone_set, - zone_status): - """Delete zones from fabric. - - Method to delete the active zone config zones - - params zone_names: zoneNames separated by semicolon - params activate: True/False - """ - - LOG.debug("zone_names %s", zone_names) - active_zoneset_name = active_zone_set[ZoneConstant.ACTIVE_ZONE_CONFIG] - - cmds = [['conf'], - ['zoneset', 'name', active_zoneset_name, 'vsan', - fabric_vsan]] - - try: - for zone in set(zone_names.split(';')): - cmds.append(['no', 'zone', 'name', zone]) - - cmds.append(['end']) - - LOG.debug("Delete zones: Config cmd to run: %s", cmds) - self._ssh_execute(cmds, True, 1) - - if activate: - self.activate_zoneset(active_zoneset_name, fabric_vsan, - zone_status) - self._cfg_save() - - except Exception as e: - msg = _("Deleting zones failed: (command=%(cmd)s error=%(err)s)." - ) % {'cmd': cmds, 'err': six.text_type(e)} - LOG.error(msg) - raise exception.CiscoZoningCliException(reason=msg) - - def get_nameserver_info(self): - """Get name server data from fabric. - - This method will return the connected node port wwn list(local - and remote) for the given switch fabric - - show fcns database - """ - cli_output = None - return_list = [] - try: - cli_output = self._get_switch_info([ZoneConstant.FCNS_SHOW, - self.fabric_vsan]) - except exception.CiscoZoningCliException: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed collecting fcns database " - "info for fabric %s"), self.switch_ip) - - if (cli_output): - return_list = self._parse_ns_output(cli_output) - - LOG.info(_LI("Connector returning fcnsinfo-%s"), return_list) - - return return_list - - @utils.retry(processutils.ProcessExecutionError, retries=5) - def _cfg_save(self): - cmd = ['copy', 'running-config', 'startup-config'] - self._run_ssh(cmd, True) - - def _get_switch_info(self, cmd_list): - stdout, stderr, sw_data = None, None, None - try: - stdout, stderr = self._run_ssh(cmd_list, True) - LOG.debug("CLI output from ssh - output: %s", stdout) - if (stdout): - sw_data = stdout.splitlines() - return sw_data - except processutils.ProcessExecutionError as e: - msg = _("Error while getting data via ssh: (command=%(cmd)s " - "error=%(err)s).") % {'cmd': cmd_list, - 'err': six.text_type(e)} - LOG.error(msg) - raise exception.CiscoZoningCliException(reason=msg) - - def _parse_ns_output(self, switch_data): - """Parses name server data. - - Parses nameserver raw data and adds the device port wwns to the list - - :returns: List -- list of device port wwn from ns info - """ - return_list = [] - for line in switch_data: - if not(" N " in line): - continue - linesplit = line.split() - if len(linesplit) > 2: - node_port_wwn = linesplit[2] - return_list.append(node_port_wwn) - else: - msg = _("Malformed show fcns database string: %s") % line - LOG.error(msg) - raise exception.InvalidParameterValue(err=msg) - return return_list - - def _run_ssh(self, cmd_list, check_exit_code=True): - - command = ' '.join(cmd_list) - - if not self.sshpool: - self.sshpool = ssh_utils.SSHPool(self.switch_ip, - self.switch_port, - None, - self.switch_user, - self.switch_pwd, - min_size=1, - max_size=5) - try: - with self.sshpool.item() as ssh: - return processutils.ssh_execute( - ssh, - command, - check_exit_code=check_exit_code) - - except Exception: - with excutils.save_and_reraise_exception(): - LOG.warning(_LW("Error running SSH command: %s"), command) - - def _ssh_execute(self, cmd_list, check_exit_code=True, attempts=1): - """Execute cli with status update. - - Executes CLI commands where status return is expected. - - cmd_list is a list of commands, where each command is itself - a list of parameters. We use utils.check_ssh_injection to check each - command, but then join then with " ; " to form a single command. - """ - - # Check that each command is secure - for cmd in cmd_list: - utils.check_ssh_injection(cmd) - - # Combine into a single command. - command = ' ; '.join(map(lambda x: ' '.join(x), cmd_list)) - - if not self.sshpool: - self.sshpool = ssh_utils.SSHPool(self.switch_ip, - self.switch_port, - None, - self.switch_user, - self.switch_pwd, - min_size=1, - max_size=5) - stdin, stdout, stderr = None, None, None - LOG.debug("Executing command via ssh: %s", command) - last_exception = None - try: - with self.sshpool.item() as ssh: - while attempts > 0: - attempts -= 1 - try: - stdin, stdout, stderr = ssh.exec_command(command) - channel = stdout.channel - exit_status = channel.recv_exit_status() - LOG.debug("Exit Status from ssh: %s", exit_status) - # exit_status == -1 if no exit code was returned - if exit_status != -1: - LOG.debug('Result was %s', exit_status) - if check_exit_code and exit_status != 0: - raise processutils.ProcessExecutionError( - exit_code=exit_status, - stdout=stdout, - stderr=stderr, - cmd=command) - else: - return True - else: - return True - except Exception as e: - LOG.exception(_LE('Error executing SSH command.')) - last_exception = e - greenthread.sleep(random.randint(20, 500) / 100.0) - LOG.debug("Handling error case after SSH: %s", last_exception) - try: - raise processutils.ProcessExecutionError( - exit_code=last_exception.exit_code, - stdout=last_exception.stdout, - stderr=last_exception.stderr, - cmd=last_exception.cmd) - except AttributeError: - raise processutils.ProcessExecutionError( - exit_code=-1, - stdout="", - stderr="Error running SSH command", - cmd=command) - except Exception: - with excutils.save_and_reraise_exception(): - LOG.exception(_LE("Error executing command via ssh.")) - finally: - if stdin: - stdin.flush() - stdin.close() - if stdout: - stdout.close() - if stderr: - stderr.close() - - def cleanup(self): - self.sshpool = None diff --git a/cinder/zonemanager/drivers/cisco/cisco_fc_zone_driver.py b/cinder/zonemanager/drivers/cisco/cisco_fc_zone_driver.py deleted file mode 100644 index 597d66b2b3e..00000000000 --- a/cinder/zonemanager/drivers/cisco/cisco_fc_zone_driver.py +++ /dev/null @@ -1,518 +0,0 @@ -# (c) Copyright 2014 Cisco 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. -# - - -""" -Cisco Zone Driver is responsible to manage access control using FC zoning -for Cisco FC fabrics. -This is a concrete implementation of FCZoneDriver interface implementing -add_connection and delete_connection interfaces. - -**Related Flags** - -:zone_activate: Used by: class: 'FCZoneDriver'. Defaults to True -:zone_name_prefix: Used by: class: 'FCZoneDriver'. Defaults to 'openstack' -""" - -from oslo_concurrency import lockutils -from oslo_config import cfg -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' - '.cisco_fc_zone_client_cli.CiscoFCZoneClientCLI', - help='Southbound connector for zoning operation'), -] - -CONF = cfg.CONF -CONF.register_opts(cisco_opts, group='fc-zone-manager') - - -class CiscoFCZoneDriver(fc_zone_driver.FCZoneDriver): - """Cisco FC zone driver implementation. - - OpenStack Fibre Channel zone driver to manage FC zoning in - Cisco SAN fabrics. - - Version history: - 1.0 - Initial Cisco FC zone driver - 1.1 - Added friendly zone name support - """ - - VERSION = "1.1.0" - - def __init__(self, **kwargs): - super(CiscoFCZoneDriver, self).__init__(**kwargs) - self.configuration = kwargs.get('configuration', None) - if self.configuration: - self.configuration.append_config_values(cisco_opts) - - # Adding a hack to handle parameters from super classes - # in case configured with multi backends. - fabric_names = self.configuration.safe_get('fc_fabric_names') - activate = self.configuration.safe_get('cisco_zone_activate') - prefix = self.configuration.safe_get('cisco_zone_name_prefix') - base_san_opts = [] - if not fabric_names: - base_san_opts.append( - cfg.StrOpt('fc_fabric_names', - help='Comma separated list of fibre channel ' - 'fabric names. This list of names is used to' - ' retrieve other SAN credentials for connecting' - ' to each SAN fabric' - )) - if not activate: - base_san_opts.append( - cfg.BoolOpt('cisco_zone_activate', - default=True, - help='Indicates whether zone should ' - 'be activated or not')) - if not prefix: - base_san_opts.append( - cfg.StrOpt('cisco_zone_name_prefix', - default="openstack", - help="A prefix to be used when naming zone")) - if len(base_san_opts) > 0: - CONF.register_opts(base_san_opts) - self.configuration.append_config_values(base_san_opts) - fabric_names = [x.strip() for x in self. - configuration.fc_fabric_names.split(',')] - - # There can be more than one SAN in the network and we need to - # get credentials for each SAN. - if fabric_names: - self.fabric_configs = fabric_opts.load_fabric_configurations( - fabric_names) - - @lockutils.synchronized('cisco', 'fcfabric-', True) - 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 - members are created and pushed to the fabric to add zones. The - new zones created or zones updated are activated based on isActivate - flag set in cinder.conf returned by volume driver after attach - operation. - - :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("CiscoFCZoneDriver - Add connection " - "for I-T map: %s"), initiator_target_map) - fabric_ip = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_address') - fabric_user = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_user') - fabric_pwd = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_password') - fabric_port = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_port') - zoning_policy = self.configuration.zoning_policy - zoning_policy_fab = self.fabric_configs[fabric].safe_get( - 'cisco_zoning_policy') - if zoning_policy_fab: - zoning_policy = zoning_policy_fab - - zoning_vsan = self.fabric_configs[fabric].safe_get('cisco_zoning_vsan') - - LOG.info(_LI("Zoning policy for Fabric %s"), zoning_policy) - - statusmap_from_fabric = self.get_zoning_status( - fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan) - - if statusmap_from_fabric.get('session') == 'none': - - cfgmap_from_fabric = self.get_active_zone_set( - fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan) - zone_names = [] - if cfgmap_from_fabric.get('zones'): - zone_names = cfgmap_from_fabric['zones'].keys() - # based on zoning policy, create zone member list and - # push changes to fabric. - for initiator_key in initiator_target_map.keys(): - zone_map = {} - initiator = initiator_key.lower() - t_list = initiator_target_map[initiator_key] - if zoning_policy == 'initiator-target': - for t in t_list: - target = t.lower() - zone_members = [ - zm_utils.get_formatted_wwn(initiator), - zm_utils.get_formatted_wwn(target)] - 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 - else: - # This is I-T zoning, skip if zone exists. - LOG.info(_LI("Zone exists in I-T mode. " - "Skipping zone creation %s"), - zone_name) - elif zoning_policy == 'initiator': - zone_members = [ - zm_utils.get_formatted_wwn(initiator)] - for t in t_list: - target = t.lower() - zone_members.append( - zm_utils.get_formatted_wwn(target)) - - 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( - lambda x: x not in zone_members, - 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) - - if len(zone_map) > 0: - conn = None - try: - conn = importutils.import_object( - self.configuration.cisco_sb_connector, - ipaddress=fabric_ip, - username=fabric_user, - password=fabric_pwd, - port=fabric_port, - vsan=zoning_vsan) - conn.add_zones( - zone_map, self.configuration.cisco_zone_activate, - zoning_vsan, cfgmap_from_fabric, - statusmap_from_fabric) - conn.cleanup() - except exception.CiscoZoningCliException as cisco_ex: - msg = _("Exception: %s") % six.text_type(cisco_ex) - raise exception.FCZoneDriverException(msg) - except Exception: - msg = _("Failed to add zoning configuration.") - LOG.exception(msg) - raise exception.FCZoneDriverException(msg) - LOG.debug("Zones added successfully: %s", zone_map) - else: - LOG.debug("Zoning session exists VSAN: %s", zoning_vsan) - - @lockutils.synchronized('cisco', 'fcfabric-', True) - 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 - are created for deletion. The zones are either updated deleted based - on the policy and attach/detach state of each I-T pair. - - :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("CiscoFCZoneDriver - Delete connection for I-T map: %s"), - initiator_target_map) - fabric_ip = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_address') - fabric_user = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_user') - fabric_pwd = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_password') - fabric_port = self.fabric_configs[fabric].safe_get( - 'cisco_fc_fabric_port') - zoning_policy = self.configuration.zoning_policy - zoning_policy_fab = self.fabric_configs[fabric].safe_get( - 'cisco_zoning_policy') - - if zoning_policy_fab: - zoning_policy = zoning_policy_fab - - zoning_vsan = self.fabric_configs[fabric].safe_get('cisco_zoning_vsan') - - LOG.info(_LI("Zoning policy for fabric %s"), zoning_policy) - - statusmap_from_fabric = self.get_zoning_status( - fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan) - - if statusmap_from_fabric.get('session') == 'none': - cfgmap_from_fabric = self.get_active_zone_set( - fabric_ip, fabric_user, fabric_pwd, fabric_port, zoning_vsan) - - zone_names = [] - if cfgmap_from_fabric.get('zones'): - zone_names = cfgmap_from_fabric['zones'].keys() - - # 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) - for initiator_key in initiator_target_map.keys(): - initiator = initiator_key.lower() - formatted_initiator = zm_utils.get_formatted_wwn(initiator) - zone_map = {} - zones_to_delete = [] - t_list = initiator_target_map[initiator_key] - if zoning_policy == 'initiator-target': - # In this case, zone needs to be deleted. - for t in t_list: - target = t.lower() - zone_name = ( - 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. - LOG.debug("Added zone to delete to list: %s", - zone_name) - zones_to_delete.append(zone_name) - - elif zoning_policy == 'initiator': - zone_members = [formatted_initiator] - for t in t_list: - target = t.lower() - zone_members.append( - zm_utils.get_formatted_wwn(target)) - - 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( - lambda x: x not in zone_members, - cfgmap_from_fabric['zones'][zone_name]) - - # The assumption here is that initiator is always - # there in the zone as it is 'initiator' policy. - # We find the 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) - if filtered_members: - filtered_members.append(formatted_initiator) - LOG.debug("Filtered zone members to update: %s", - filtered_members) - zone_map[zone_name] = filtered_members - LOG.debug("Filtered zone Map to update: %s", - 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) - conn = None - try: - conn = importutils.import_object( - self.configuration.cisco_sb_connector, - ipaddress=fabric_ip, - username=fabric_user, - password=fabric_pwd, - port=fabric_port, - vsan=zoning_vsan) - # Update zone membership. - if zone_map: - conn.add_zones( - zone_map, self.configuration.cisco_zone_activate, - zoning_vsan, cfgmap_from_fabric, - statusmap_from_fabric) - # Delete zones ~sk. - if zones_to_delete: - zone_name_string = '' - num_zones = len(zones_to_delete) - for i in range(0, num_zones): - if i == 0: - zone_name_string = ('%s%s' % ( - zone_name_string, - zones_to_delete[i])) - else: - zone_name_string = ('%s%s%s' % ( - zone_name_string, ';', - zones_to_delete[i])) - - conn.delete_zones(zone_name_string, - self.configuration. - cisco_zone_activate, - zoning_vsan, cfgmap_from_fabric, - statusmap_from_fabric) - conn.cleanup() - except Exception: - msg = _("Failed to update or delete zoning configuration") - LOG.exception(msg) - raise exception.FCZoneDriverException(msg) - LOG.debug("Zones deleted successfully: %s", zone_map) - else: - LOG.debug("Zoning session exists VSAN: %s", zoning_vsan) - - def get_san_context(self, target_wwn_list): - """Lookup SAN context for visible end devices. - - Look up each SAN configured and return a map of SAN (fabric IP) to - list of target WWNs visible to the fabric. - """ - formatted_target_list = [] - fabric_map = {} - fabrics = [x.strip() for x in self. - configuration.fc_fabric_names.split(',')] - LOG.debug("Fabric List: %s", fabrics) - LOG.debug("Target wwn List: %s", target_wwn_list) - if len(fabrics) > 0: - for t in target_wwn_list: - formatted_target_list.append( - zm_utils.get_formatted_wwn(t.lower())) - LOG.debug("Formatted Target wwn List: %s", formatted_target_list) - for fabric_name in fabrics: - fabric_ip = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_address') - fabric_user = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_user') - fabric_pwd = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_password') - fabric_port = self.fabric_configs[fabric_name].safe_get( - 'cisco_fc_fabric_port') - zoning_vsan = self.fabric_configs[fabric_name].safe_get( - 'cisco_zoning_vsan') - - # Get name server data from fabric and get the targets - # logged in. - nsinfo = None - try: - conn = importutils.import_object( - self.configuration.cisco_sb_connector, - ipaddress=fabric_ip, - username=fabric_user, - password=fabric_pwd, port=fabric_port, - vsan=zoning_vsan) - nsinfo = conn.get_nameserver_info() - LOG.debug("show fcns database info from fabric: %s", - nsinfo) - conn.cleanup() - except exception.CiscoZoningCliException: - with excutils.save_and_reraise_exception(): - LOG.exception(_LE("Error getting show fcns database " - "info.")) - except Exception: - msg = _("Failed to get show fcns database info.") - LOG.exception(msg) - raise exception.FCZoneDriverException(msg) - visible_targets = filter( - lambda x: x in formatted_target_list, nsinfo) - - if visible_targets: - LOG.info(_LI("Filtered targets for SAN is: %s"), - {fabric_name: visible_targets}) - # getting rid of the ':' before returning - for idx, elem in enumerate(visible_targets): - visible_targets[idx] = six.text_type( - visible_targets[idx]).replace(':', '') - fabric_map[fabric_name] = visible_targets - else: - LOG.debug("No targets are in the fcns info for SAN %s", - fabric_name) - LOG.debug("Return SAN context output: %s", fabric_map) - return fabric_map - - def get_active_zone_set(self, fabric_ip, - fabric_user, fabric_pwd, fabric_port, - zoning_vsan): - """Gets active zoneset config for vsan.""" - cfgmap = {} - conn = None - try: - LOG.debug("Southbound connector: %s", - self.configuration.cisco_sb_connector) - conn = importutils.import_object( - self.configuration.cisco_sb_connector, - ipaddress=fabric_ip, username=fabric_user, - password=fabric_pwd, port=fabric_port, vsan=zoning_vsan) - cfgmap = conn.get_active_zone_set() - conn.cleanup() - except Exception: - msg = _("Failed to access active zoning configuration.") - LOG.exception(msg) - raise exception.FCZoneDriverException(msg) - LOG.debug("Active zone set from fabric: %s", cfgmap) - return cfgmap - - def get_zoning_status(self, fabric_ip, fabric_user, fabric_pwd, - fabric_port, zoning_vsan): - """Gets zoneset status and mode.""" - statusmap = {} - conn = None - try: - LOG.debug("Southbound connector: %s", - self.configuration.cisco_sb_connector) - conn = importutils.import_object( - self.configuration.cisco_sb_connector, - ipaddress=fabric_ip, username=fabric_user, - password=fabric_pwd, port=fabric_port, vsan=zoning_vsan) - statusmap = conn.get_zoning_status() - conn.cleanup() - except Exception: - msg = _("Failed to access zoneset status:%s") - LOG.exception(msg) - raise exception.FCZoneDriverException(msg) - LOG.debug("Zoneset status from fabric: %s", statusmap) - return statusmap diff --git a/cinder/zonemanager/drivers/cisco/fc_zone_constants.py b/cinder/zonemanager/drivers/cisco/fc_zone_constants.py deleted file mode 100644 index 6e1a8755c02..00000000000 --- a/cinder/zonemanager/drivers/cisco/fc_zone_constants.py +++ /dev/null @@ -1,32 +0,0 @@ -# (c) Copyright 2014 Cisco 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. -# - - -""" -Common constants used by Cisco FC Zone Driver. -""" -ACTIVE_ZONE_CONFIG = 'active_zone_config' -CFG_ZONESET = 'zoneset' -CFG_ZONE = 'zone' -CFG_ZONE_MEMBER = 'pwwn' -CFG_ZONES = 'zones' - -""" -CLI Commands for FC zoning operations. -""" -GET_ACTIVE_ZONE_CFG = 'show zoneset active vsan ' -FCNS_SHOW = 'show fcns database vsan ' -GET_ZONE_STATUS = 'show zone status vsan ' diff --git a/releasenotes/notes/cisco-fczm-removed-502dfcba51acd1b4.yaml b/releasenotes/notes/cisco-fczm-removed-502dfcba51acd1b4.yaml new file mode 100644 index 00000000000..29949a5e5c1 --- /dev/null +++ b/releasenotes/notes/cisco-fczm-removed-502dfcba51acd1b4.yaml @@ -0,0 +1,4 @@ +--- +upgrade: + - The Cisco FC Zone Manager driver is no longer supported + and not included in-tree.