from cinder.tests.brick.fake_lvm import FakeBrickLVM
from cinder.volume import driver
from cinder.volume.drivers import lvm
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
return (None, None)
+class FakeFibreChannelDriver(driver.FibreChannelDriver):
+
+ @fczm_utils.AddFCZone
+ def initialize_connection(self, volume, connector):
+ return {
+ 'driver_volume_type': 'fibre_channel',
+ 'data': {
+ 'initiator_target_map': {'fake_wwn': ['fake_wwn2']},
+ }}
+
+ @fczm_utils.AddFCZone
+ def no_zone_initialize_connection(self, volume, connector):
+ """This shouldn't call the ZM."""
+ return {
+ 'driver_volume_type': 'bogus',
+ 'data': {
+ 'initiator_target_map': {'fake_wwn': ['fake_wwn2']},
+ }}
+
+ @fczm_utils.RemoveFCZone
+ def terminate_connection(self, volume, connector, **kwargs):
+ return {
+ 'driver_volume_type': 'fibre_channel',
+ 'data': {
+ 'initiator_target_map': {'fake_wwn': ['fake_wwn2']},
+ }}
+
+ @fczm_utils.RemoveFCZone
+ def no_zone_terminate_connection(self, volume, connector, **kwargs):
+ return {
+ 'driver_volume_type': 'bogus',
+ 'data': {
+ 'initiator_target_map': {'fake_wwn': ['fake_wwn2']},
+ }}
+
+
class LoggingVolumeDriver(driver.VolumeDriver):
"""Logs and records calls, for unit tests."""
"""Test Case for FibreChannelDriver."""
driver_name = "cinder.volume.driver.FibreChannelDriver"
- def setUp(self):
- super(FibreChannelTestCase, self).setUp()
- self.driver = driver.FibreChannelDriver()
- self.driver.do_setup(None)
-
def test_initialize_connection(self):
self.assertRaises(NotImplementedError,
- self.driver.initialize_connection, {}, {})
+ self.volume.driver.initialize_connection, {}, {})
def test_validate_connector(self):
"""validate_connector() successful use case.
"""
connector = {'wwpns': ["not empty"],
'wwnns': ["not empty"]}
- self.driver.validate_connector(connector)
+ self.volume.driver.validate_connector(connector)
def test_validate_connector_no_wwpns(self):
"""validate_connector() throws exception when it has no wwpns."""
connector = {'wwnns': ["not empty"]}
self.assertRaises(exception.VolumeDriverException,
- self.driver.validate_connector, connector)
+ self.volume.driver.validate_connector, connector)
def test_validate_connector_empty_wwpns(self):
"""validate_connector() throws exception when it has empty wwpns."""
connector = {'wwpns': [],
'wwnns': ["not empty"]}
self.assertRaises(exception.VolumeDriverException,
- self.driver.validate_connector, connector)
+ self.volume.driver.validate_connector, connector)
def test_validate_connector_no_wwnns(self):
"""validate_connector() throws exception when it has no wwnns."""
connector = {'wwpns': ["not empty"]}
self.assertRaises(exception.VolumeDriverException,
- self.driver.validate_connector, connector)
+ self.volume.driver.validate_connector, connector)
def test_validate_connector_empty_wwnns(self):
"""validate_connector() throws exception when it has empty wwnns."""
connector = {'wwnns': [],
'wwpns': ["not empty"]}
self.assertRaises(exception.VolumeDriverException,
- self.driver.validate_connector, connector)
+ self.volume.driver.validate_connector, connector)
class VolumePolicyTestCase(test.TestCase):
from cinder import test
from cinder.volume import configuration as conf
from cinder.zonemanager.drivers.fc_zone_driver import FCZoneDriver
-from cinder.zonemanager.fc_zone_manager import ZoneManager
+from cinder.zonemanager import fc_zone_manager
from mock import Mock
fabric_name = 'BRCD_FAB_3'
target_list = ['20240002ac000a50']
-class TestFCZoneManager(ZoneManager, test.TestCase):
+class TestFCZoneManager(test.TestCase):
def setUp(self):
super(TestFCZoneManager, self).setUp()
- self.configuration = conf.Configuration(None)
- self.configuration.set_default('fc_fabric_names', fabric_name)
- self.driver = Mock(FCZoneDriver)
+ config = conf.Configuration(None)
+ config.fc_fabric_names = fabric_name
+
+ def fake_build_driver(self):
+ self.driver = Mock(FCZoneDriver)
+
+ self.stubs.Set(fc_zone_manager.ZoneManager, '_build_driver',
+ fake_build_driver)
+
+ self.zm = fc_zone_manager.ZoneManager(configuration=config)
def __init__(self, *args, **kwargs):
test.TestCase.__init__(self, *args, **kwargs)
def test_add_connection(self):
- with mock.patch.object(self.driver, 'add_connection')\
+ with mock.patch.object(self.zm.driver, 'add_connection')\
as add_connection_mock:
- self.driver.get_san_context.return_value = fabric_map
- self.add_connection(init_target_map)
- self.driver.get_san_context.assert_called_once(target_list)
+ self.zm.driver.get_san_context.return_value = fabric_map
+ self.zm.add_connection(init_target_map)
+ self.zm.driver.get_san_context.assert_called_once(target_list)
add_connection_mock.assert_called_once_with(fabric_name,
init_target_map)
def test_add_connection_error(self):
- with mock.patch.object(self.driver, 'add_connection')\
+ with mock.patch.object(self.zm.driver, 'add_connection')\
as add_connection_mock:
add_connection_mock.side_effect = exception.FCZoneDriverException
self.assertRaises(exception.ZoneManagerException,
- self.add_connection, init_target_map)
+ self.zm.add_connection, init_target_map)
def test_delete_connection(self):
- with mock.patch.object(self.driver, 'delete_connection')\
+ with mock.patch.object(self.zm.driver, 'delete_connection')\
as delete_connection_mock:
- self.driver.get_san_context.return_value = fabric_map
- self.delete_connection(init_target_map)
- self.driver.get_san_context.assert_called_once_with(target_list)
+ self.zm.driver.get_san_context.return_value = fabric_map
+ self.zm.delete_connection(init_target_map)
+ self.zm.driver.get_san_context.assert_called_once_with(target_list)
delete_connection_mock.assert_called_once_with(fabric_name,
init_target_map)
def test_delete_connection_error(self):
- with mock.patch.object(self.driver, 'delete_connection')\
+ with mock.patch.object(self.zm.driver, 'delete_connection')\
as del_connection_mock:
del_connection_mock.side_effect = exception.FCZoneDriverException
self.assertRaises(exception.ZoneManagerException,
- self.delete_connection, init_target_map)
+ self.zm.delete_connection, init_target_map)
--- /dev/null
+# (c) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
+# 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.
+#
+
+
+"""Unit tests for Volume Manager."""
+
+import mock
+
+from cinder import test
+from cinder.tests import fake_driver
+from cinder import utils
+from cinder.volume import configuration as conf
+from cinder.zonemanager.drivers.brocade import brcd_fc_zone_driver
+from cinder.zonemanager import fc_zone_manager
+
+
+class TestVolumeDriver(test.TestCase):
+
+ def setUp(self):
+ super(TestVolumeDriver, self).setUp()
+ self.driver = fake_driver.FakeFibreChannelDriver()
+ brcd_fc_zone_driver.BrcdFCZoneDriver = mock.Mock()
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.driver = None
+
+ def __init__(self, *args, **kwargs):
+ test.TestCase.__init__(self, *args, **kwargs)
+
+ @mock.patch.object(utils, 'require_driver_initialized')
+ def test_initialize_connection_with_decorator(self, utils_mock):
+ utils_mock.return_value = True
+ with mock.patch.object(fc_zone_manager.ZoneManager, 'add_connection')\
+ as add_zone_mock:
+ with mock.patch.object(conf.Configuration, 'safe_get')\
+ as mock_safe_get:
+ mock_safe_get.return_value = 'fabric'
+ conn_info = self.driver.initialize_connection(None, None)
+ init_target_map = conn_info['data']['initiator_target_map']
+ add_zone_mock.assert_called_once_with(init_target_map)
+
+ @mock.patch.object(utils, 'require_driver_initialized')
+ def test_initialize_connection_no_decorator(self, utils_mock):
+ utils_mock.return_value = True
+ with mock.patch.object(fc_zone_manager.ZoneManager, 'add_connection')\
+ as add_zone_mock:
+ with mock.patch.object(conf.Configuration, 'safe_get')\
+ as mock_safe_get:
+ mock_safe_get.return_value = 'fabric'
+ self.driver.no_zone_initialize_connection(None, None)
+ assert not add_zone_mock.called
+
+ @mock.patch.object(utils, 'require_driver_initialized')
+ def test_terminate_connection_with_decorator(self, utils_mock):
+ utils_mock.return_value = True
+ with mock.patch.object(fc_zone_manager.ZoneManager,
+ 'delete_connection') as remove_zone_mock:
+ with mock.patch.object(conf.Configuration, 'safe_get')\
+ as mock_safe_get:
+ mock_safe_get.return_value = 'fabric'
+ conn_info = self.driver.terminate_connection(None, None)
+ init_target_map = conn_info['data']['initiator_target_map']
+ remove_zone_mock.assert_called_once_with(init_target_map)
+
+ @mock.patch.object(utils, 'require_driver_initialized')
+ def test_terminate_connection_no_decorator(self, utils_mock):
+ utils_mock.return_value = True
+ with mock.patch.object(fc_zone_manager.ZoneManager,
+ 'delete_connection') as remove_zone_mock:
+ with mock.patch.object(conf.Configuration, 'safe_get')\
+ as mock_safe_get:
+ mock_safe_get.return_value = 'fabric'
+ self.driver.no_zone_terminate_connection(None, None)
+ assert not remove_zone_mock.called
+++ /dev/null
-# (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.
-#
-
-
-"""Unit tests for Volume Manager."""
-
-import mock
-
-from cinder import exception
-from cinder import test
-from cinder import utils
-from cinder.volume import configuration as conf
-from cinder.volume import driver
-from cinder.volume import manager
-from cinder.zonemanager import fc_zone_manager
-
-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']
- }
- }
-}
-conn_info_no_init_target_map = {
- 'driver_volume_type': 'fibre_channel',
- 'data': {
- 'target_discovered': True,
- 'target_lun': 1,
- 'target_wwn': '20240002ac000a50',
- }
-}
-
-
-class TestVolumeManager(manager.VolumeManager, test.TestCase):
-
- def setUp(self):
- super(TestVolumeManager, self).setUp()
- self.configuration = conf.Configuration(None)
- self.configuration.set_default('fc_fabric_names', 'BRCD_FAB_4',
- 'fc-zone-manager')
- self.configuration.zoning_mode = 'fabric'
- self.driver = mock.Mock(driver.VolumeDriver)
- self.driver.initialize_connection.return_value = conn_info
- self.driver.terminate_connection.return_value = conn_info
- self.driver.create_export.return_value = None
- self.db = mock.Mock()
- self.db.volume_get.return_value = {'volume_type_id': None}
- self.db.volume_admin_metadata_get.return_value = {}
- self.context_mock = mock.Mock()
- self.context_mock.elevated.return_value = None
- self.zonemanager = fc_zone_manager.ZoneManager(
- configuration=self.configuration)
-
- def tearDown(self):
- super(TestVolumeManager, self).tearDown()
- self.configuration = None
- self.db = None
- self.driver = None
- self.zonemanager = None
-
- def __init__(self, *args, **kwargs):
- test.TestCase.__init__(self, *args, **kwargs)
-
- @mock.patch.object(utils, 'require_driver_initialized')
- def test_initialize_connection_voltype_fc_mode_fabric(self,
- utils_mock):
- utils_mock.return_value = True
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- self.initialize_connection(self.context_mock, None, None)
- add_del_conn_mock.assert_called_once_with(conn_info, 1)
-
- @mock.patch.object(utils, 'require_driver_initialized')
- def test_initialize_connection_voltype_fc_mode_none(self,
- utils_mock):
- utils_mock.return_value = True
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- self.configuration.zoning_mode = 'none'
- self.zonemanager = None
- self.initialize_connection(self.context_mock, None, None)
- assert not add_del_conn_mock.called
-
- def test_terminate_connection_exception(self):
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- add_del_conn_mock.side_effect = exception.ZoneManagerException
- self.assertRaises(exception.VolumeBackendAPIException,
- self.terminate_connection, None, None, None,
- False)
-
- @mock.patch.object(utils, 'require_driver_initialized')
- def test_terminate_connection_voltype_fc_mode_fabric(self,
- utils_mock):
- utils_mock.return_value = True
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- self.terminate_connection(self.context_mock, None, None, False)
- add_del_conn_mock.assert_called_once_with(conn_info, 0)
-
- @mock.patch.object(utils, 'require_driver_initialized')
- def test_terminate_connection_mode_none(self,
- utils_mock):
- utils_mock.return_value = True
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- self.configuration.zoning_mode = 'none'
- self.zonemanager = None
- self.terminate_connection(self.context_mock, None, None, False)
- assert not add_del_conn_mock.called
-
- @mock.patch.object(utils, 'require_driver_initialized')
- def test_terminate_connection_conn_info_none(self,
- utils_mock):
- utils_mock.return_value = True
- self.driver.terminate_connection.return_value = None
- with mock.patch.object(manager.VolumeManager,
- '_add_or_delete_fc_connection')\
- as add_del_conn_mock:
- self.terminate_connection(self.context_mock, None, None, False)
- assert not add_del_conn_mock.called
-
- @mock.patch.object(fc_zone_manager.ZoneManager, 'add_connection')
- def test__add_or_delete_connection_add(self,
- add_connection_mock):
- self._add_or_delete_fc_connection(conn_info, 1)
- add_connection_mock.assert_called_once_with(init_target_map)
-
- @mock.patch.object(fc_zone_manager.ZoneManager, 'delete_connection')
- def test__add_or_delete_connection_delete(self,
- delete_connection_mock):
- self._add_or_delete_fc_connection(conn_info, 0)
- delete_connection_mock.assert_called_once_with(init_target_map)
-
- @mock.patch.object(fc_zone_manager.ZoneManager, 'delete_connection')
- def test__add_or_delete_connection_no_init_target_map(self,
- del_conn_mock):
- self._add_or_delete_fc_connection(conn_info_no_init_target_map, 0)
- assert not del_conn_mock.called
from cinder.openstack.common import log as logging
from cinder.volume import driver
from cinder.volume.drivers.emc import emc_smis_common
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
"""Make sure volume is exported."""
pass
+ @fczm_utils.AddFCZone
def initialize_connection(self, volume, connector):
"""Initializes the connection and returns connection info.
return data
+ @fczm_utils.RemoveFCZone
def terminate_connection(self, volume, connector, **kwargs):
"""Disallow connection from connector."""
self.common.terminate_connection(volume, connector)
from cinder.volume import driver
from cinder.volume.drivers.huawei.rest_common import HVSCommon
+from cinder.zonemanager import utils as fczm_utils
class HuaweiHVSISCSIDriver(driver.ISCSIDriver):
data['driver_version'] = self.VERSION
return data
+ @fczm_utils.AddFCZone
def initialize_connection(self, volume, connector):
"""Map a volume to a host."""
return self.common.initialize_connection_fc(volume, connector)
+ @fczm_utils.RemoveFCZone
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate the map."""
self.common.terminate_connection(volume, connector, **kwargs)
from cinder.volume import driver
from cinder.volume.drivers.huawei import huawei_utils
from cinder.volume.drivers.huawei import ssh_common
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
LOG.error(err_msg)
raise exception.VolumeBackendAPIException(data=err_msg)
+ @fczm_utils.AddFCZone
def initialize_connection(self, volume, connector):
"""Create FC connection between a volume and a host."""
LOG.debug('initialize_connection: volume name: %(vol)s, '
def _get_fc_port_ctr(self, port_details):
return port_details['ControllerID']
+ @fczm_utils.RemoveFCZone
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate the map."""
LOG.debug('terminate_connection: volume: %(vol)s, host: %(host)s, '
from cinder.volume.drivers.ibm.storwize_svc import helpers as storwize_helpers
from cinder.volume.drivers.san import san
from cinder.volume import volume_types
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
return self._helpers.get_vdisk_params(self.configuration, self._state,
type_id, volume_type=volume_type)
+ @fczm_utils.AddFCZone
@utils.synchronized('storwize-host', external=True)
def initialize_connection(self, volume, connector):
"""Perform the necessary work so that an iSCSI/FC connection can
return i_t_map
+ @fczm_utils.RemoveFCZone
@utils.synchronized('storwize-host', external=True)
def terminate_connection(self, volume, connector, **kwargs):
"""Cleanup after an iSCSI connection has been terminated.
import cinder.volume.driver
from cinder.volume.drivers.san.hp import hp_3par_common as hpcommon
from cinder.volume.drivers.san import san
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
finally:
self.common.client_logout()
+ @fczm_utils.AddFCZone
@utils.synchronized('3par', external=True)
def initialize_connection(self, volume, connector):
"""Assigns the volume to a server.
finally:
self.common.client_logout()
+ @fczm_utils.RemoveFCZone
@utils.synchronized('3par', external=True)
def terminate_connection(self, volume, connector, **kwargs):
"""Driver entry point to unattach a volume from an instance."""
import cinder.volume.driver
from cinder.volume.drivers.san.hp import hp_msa_common as hpcommon
from cinder.volume.drivers.san import san
+from cinder.zonemanager import utils as fczm_utils
LOG = logging.getLogger(__name__)
finally:
self.common.client_logout()
+ @fczm_utils.AddFCZone
@utils.synchronized('msa', external=True)
def initialize_connection(self, volume, connector):
self.common.client_login()
finally:
self.common.client_logout()
+ @fczm_utils.RemoveFCZone
@utils.synchronized('msa', external=True)
def terminate_connection(self, volume, connector, **kwargs):
self.common.client_login()
from cinder.volume import rpcapi as volume_rpcapi
from cinder.volume import utils as volume_utils
from cinder.volume import volume_types
-from cinder.zonemanager.fc_zone_manager import ZoneManager
from eventlet.greenpool import GreenPool
db=self.db,
host=self.host)
- self.zonemanager = None
try:
self.extra_capabilities = jsonutils.loads(
self.driver.configuration.extra_capabilities)
"""
ctxt = context.get_admin_context()
- if self.configuration.safe_get('zoning_mode') == 'fabric':
- self.zonemanager = ZoneManager(configuration=self.configuration)
- LOG.info(_("Starting FC Zone Manager %(zm_version)s,"
- " Driver %(drv_name)s %(drv_version)s") %
- {'zm_version': self.zonemanager.get_version(),
- 'drv_name': self.zonemanager.driver.__class__.__name__,
- 'drv_version': self.zonemanager.driver.get_version()})
-
LOG.info(_("Starting volume driver %(driver_name)s (%(version)s)") %
{'driver_name': self.driver.__class__.__name__,
'version': self.driver.get_version()})
if volume_metadata.get('readonly') == 'True'
else 'rw')
conn_info['data']['access_mode'] = access_mode
- # NOTE(skolathur): If volume_type is fibre_channel, invoke
- # FCZoneManager to add access control via FC zoning.
- vol_type = conn_info.get('driver_volume_type', None)
- mode = self.configuration.zoning_mode
- LOG.debug("Zoning Mode: %s", mode)
- if vol_type == 'fibre_channel' and self.zonemanager:
- self._add_or_delete_fc_connection(conn_info, 1)
+
return conn_info
def terminate_connection(self, context, volume_id, connector, force=False):
volume_ref = self.db.volume_get(context, volume_id)
try:
- conn_info = self.driver.terminate_connection(volume_ref,
- connector,
- force=force)
- # NOTE(skolathur): If volume_type is fibre_channel, invoke
- # FCZoneManager to remove access control via FC zoning.
- if conn_info:
- vol_type = conn_info.get('driver_volume_type', None)
- mode = self.configuration.zoning_mode
- LOG.debug("Zoning Mode: %s", mode)
- if vol_type == 'fibre_channel' and self.zonemanager:
- self._add_or_delete_fc_connection(conn_info, 0)
+ self.driver.terminate_connection(volume_ref, connector,
+ force=force)
except Exception as err:
err_msg = (_('Unable to terminate volume connection: %(err)s')
% {'err': err})
# Update volume stats
self.stats['allocated_capacity_gb'] += volume_ref['size']
return volume_ref['id']
-
- def _add_or_delete_fc_connection(self, conn_info, zone_op):
- """Add or delete connection control to fibre channel network.
-
- In case of fibre channel, when zoning mode is set as fabric
- ZoneManager is invoked to apply FC zoning configuration to the network
- using initiator and target WWNs used for attach/detach.
-
- params conn_info: connector passed by volume driver after
- initialize_connection or terminate_connection.
- params zone_op: Indicates if it is a zone add or delete operation
- zone_op=0 for delete connection and 1 for add connection
- """
- _initiator_target_map = None
- if 'initiator_target_map' in conn_info['data']:
- _initiator_target_map = conn_info['data']['initiator_target_map']
- LOG.debug("Initiator Target map:%s", _initiator_target_map)
- # NOTE(skolathur): Invoke Zonemanager to handle automated FC zone
- # management when vol_type is fibre_channel and zoning_mode is fabric
- # Initiator_target map associating each initiator WWN to one or more
- # target WWN is passed to ZoneManager to add or update zone config.
- LOG.debug("Zoning op: %s", zone_op)
- if _initiator_target_map is not None:
- try:
- if zone_op == 1:
- self.zonemanager.add_connection(_initiator_target_map)
- elif zone_op == 0:
- self.zonemanager.delete_connection(_initiator_target_map)
- except exception.ZoneManagerException as e:
- with excutils.save_and_reraise_exception():
- LOG.error(e)
class ZoneManager(fc_common.FCCommon):
- """Manages Connection control during attach/detach."""
+ """Manages Connection control during attach/detach.
- VERSION = "1.0"
+ Version History:
+ 1.0 - Initial version
+ 1.0.1 - Added __new__ for singleton
+
+ """
+
+ VERSION = "1.0.1"
driver = None
fabric_names = []
+ def __new__(class_, *args, **kwargs):
+ if not hasattr(class_, "_instance"):
+ class_._instance = object.__new__(class_, *args, **kwargs)
+ return class_._instance
+
def __init__(self, **kwargs):
"""Load the driver from the one specified in args, or from flags."""
super(ZoneManager, self).__init__(**kwargs)
if self.configuration:
self.configuration.append_config_values(zone_manager_opts)
+ self._build_driver()
+
+ def _build_driver(self):
zone_driver = self.configuration.zone_driver
LOG.debug("Zone Driver from config: {%s}", zone_driver)
--- /dev/null
+# (c) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
+# 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.
+#
+"""
+Utility functions related to the Zone Manager.
+
+"""
+import logging
+
+from cinder.openstack.common import log
+from cinder.volume.configuration import Configuration
+from cinder.volume import manager
+from cinder.zonemanager import fc_zone_manager
+
+LOG = log.getLogger(__name__)
+LOG.logger.setLevel(logging.DEBUG)
+
+
+def create_zone_manager():
+ """If zoning is enabled, build the Zone Manager."""
+ config = Configuration(manager.volume_manager_opts)
+ LOG.debug("zoning mode %s" % config.safe_get('zoning_mode'))
+ if config.safe_get('zoning_mode') == 'fabric':
+ LOG.debug("FC Zone Manager enabled.")
+ zm = fc_zone_manager.ZoneManager(configuration=config)
+ LOG.info(_("Using FC Zone Manager %(zm_version)s,"
+ " Driver %(drv_name)s %(drv_version)s.") %
+ {'zm_version': zm.get_version(),
+ 'drv_name': zm.driver.__class__.__name__,
+ 'drv_version': zm.driver.get_version()})
+ return zm
+ else:
+ LOG.debug("FC Zone Manager not enabled in cinder.conf.")
+ return None
+
+
+def AddFCZone(initialize_connection):
+ """Decorator to add a FC Zone."""
+ def decorator(self, *args, **kwargs):
+ conn_info = initialize_connection(self, *args, **kwargs)
+ if not conn_info:
+ LOG.warn(_("Driver didn't return connection info, "
+ "can't add zone."))
+ return None
+
+ vol_type = conn_info.get('driver_volume_type', None)
+ if vol_type == 'fibre_channel':
+
+ if 'initiator_target_map' in conn_info['data']:
+ init_target_map = conn_info['data']['initiator_target_map']
+ zm = create_zone_manager()
+ if zm:
+ LOG.debug("Add FC Zone for mapping '%s'." %
+ init_target_map)
+ zm.add_connection(init_target_map)
+
+ return conn_info
+
+ return decorator
+
+
+def RemoveFCZone(terminate_connection):
+ """Decorator for FC drivers to remove zone."""
+ def decorator(self, *args, **kwargs):
+ conn_info = terminate_connection(self, *args, **kwargs)
+ if not conn_info:
+ LOG.warn(_("Driver didn't return connection info from "
+ "terminate_connection call."))
+ return None
+
+ vol_type = conn_info.get('driver_volume_type', None)
+ if vol_type == 'fibre_channel':
+
+ if 'initiator_target_map' in conn_info['data']:
+ init_target_map = conn_info['data']['initiator_target_map']
+ zm = create_zone_manager()
+ if zm:
+ LOG.debug("Remove FC Zone for mapping '%s'." %
+ init_target_map)
+ zm.delete_connection(init_target_map)
+
+ return conn_info
+
+ return decorator