Add supported driver checks to Zone Manager
This patch adds the supported driver checks to the Fibre Channel Zone Manager. This is the same mechanism that is in Cinder volume drivers. When a zone manager driver is marked as unsupported, the zone manager won't allow it to work unless the enable_unsupported_driver=True is added to the fc-zone-manager section in cinder.conf Change-Id: If707b9005f60dc28eb99f46929fb700a2de0f755 Implements: blueprint zonemanager-supported-driver
This commit is contained in:
parent
b0c54b672b
commit
a93314b679
@ -1014,6 +1014,10 @@ class FCSanLookupServiceException(CinderException):
|
||||
message = _("Fibre Channel SAN Lookup failure: %(reason)s")
|
||||
|
||||
|
||||
class ZoneManagerNotInitialized(CinderException):
|
||||
message = _("Fibre Channel Zone Manager not initialized")
|
||||
|
||||
|
||||
class BrocadeZoningCliException(CinderException):
|
||||
message = _("Brocade Fibre Channel Zoning CLI error: %(reason)s")
|
||||
|
||||
|
@ -49,11 +49,17 @@ class TestFCZoneManager(test.TestCase):
|
||||
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||
def setUp(self, opt_mock):
|
||||
super(TestFCZoneManager, self).setUp()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestFCZoneManager, self).__init__(*args, **kwargs)
|
||||
|
||||
def setup_fake_driver(self):
|
||||
config = conf.Configuration(None)
|
||||
config.fc_fabric_names = fabric_name
|
||||
|
||||
def fake_build_driver(self):
|
||||
self.driver = mock.Mock(fc_zone_driver.FCZoneDriver)
|
||||
self.set_initialized(True)
|
||||
|
||||
self.mock_object(fc_zone_manager.ZoneManager, '_build_driver',
|
||||
fake_build_driver)
|
||||
@ -61,13 +67,48 @@ class TestFCZoneManager(test.TestCase):
|
||||
self.zm = fc_zone_manager.ZoneManager(configuration=config)
|
||||
self.configuration = conf.Configuration(None)
|
||||
self.configuration.fc_fabric_names = fabric_name
|
||||
self.driver = mock.Mock(fc_zone_driver.FCZoneDriver)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestFCZoneManager, self).__init__(*args, **kwargs)
|
||||
def test_unsupported_driver_disabled(self):
|
||||
config = conf.Configuration(fc_zone_manager.zone_manager_opts,
|
||||
'fc-zone-manager')
|
||||
config.fc_fabric_names = fabric_name
|
||||
config.enable_unsupported_driver = False
|
||||
|
||||
def fake_import(self, *args, **kwargs):
|
||||
fake_driver = mock.Mock(fc_zone_driver.FCZoneDriver)
|
||||
fake_driver.supported = False
|
||||
return fake_driver
|
||||
|
||||
self.patch('oslo_utils.importutils.import_object',
|
||||
fake_import)
|
||||
|
||||
zm = fc_zone_manager.ZoneManager(configuration=config)
|
||||
self.assertFalse(zm.driver.supported)
|
||||
self.assertFalse(zm.initialized)
|
||||
|
||||
def test_unsupported_driver_enabled(self):
|
||||
config = conf.Configuration(None)
|
||||
config.fc_fabric_names = fabric_name
|
||||
|
||||
def fake_import(self, *args, **kwargs):
|
||||
fake_driver = mock.Mock(fc_zone_driver.FCZoneDriver)
|
||||
fake_driver.supported = False
|
||||
return fake_driver
|
||||
|
||||
self.patch('oslo_utils.importutils.import_object',
|
||||
fake_import)
|
||||
|
||||
with mock.patch(
|
||||
'cinder.volume.configuration.Configuration') as mock_config:
|
||||
mock_config.return_value.zone_driver = 'test'
|
||||
mock_config.return_value.enable_unsupported_driver = True
|
||||
zm = fc_zone_manager.ZoneManager(configuration=config)
|
||||
self.assertFalse(zm.driver.supported)
|
||||
self.assertTrue(zm.initialized)
|
||||
|
||||
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||
def test_add_connection(self, opt_mock):
|
||||
self.setup_fake_driver()
|
||||
with mock.patch.object(self.zm.driver, 'add_connection')\
|
||||
as add_connection_mock:
|
||||
self.zm.driver.get_san_context.return_value = fabric_map
|
||||
@ -80,6 +121,7 @@ class TestFCZoneManager(test.TestCase):
|
||||
|
||||
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||
def test_add_connection_error(self, opt_mock):
|
||||
self.setup_fake_driver()
|
||||
with mock.patch.object(self.zm.driver, 'add_connection')\
|
||||
as add_connection_mock:
|
||||
add_connection_mock.side_effect = exception.FCZoneDriverException
|
||||
@ -88,6 +130,7 @@ class TestFCZoneManager(test.TestCase):
|
||||
|
||||
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||
def test_delete_connection(self, opt_mock):
|
||||
self.setup_fake_driver()
|
||||
with mock.patch.object(self.zm.driver, 'delete_connection')\
|
||||
as delete_connection_mock:
|
||||
self.zm.driver.get_san_context.return_value = fabric_map
|
||||
@ -100,6 +143,7 @@ class TestFCZoneManager(test.TestCase):
|
||||
|
||||
@mock.patch('oslo_config.cfg._is_opt_registered', return_value=False)
|
||||
def test_delete_connection_error(self, opt_mock):
|
||||
self.setup_fake_driver()
|
||||
with mock.patch.object(self.zm.driver, 'delete_connection')\
|
||||
as del_connection_mock:
|
||||
del_connection_mock.side_effect = exception.FCZoneDriverException
|
||||
|
@ -44,3 +44,13 @@ class FCZoneDriver(
|
||||
def __init__(self, **kwargs):
|
||||
super(FCZoneDriver, self).__init__(**kwargs)
|
||||
LOG.debug("Initializing FCZoneDriver")
|
||||
|
||||
# If a driver hasn't maintained their CI system, this will get set
|
||||
# to False, which prevents the driver from starting.
|
||||
# Add enable_unsupported_driver = True in cinder.conf to get the
|
||||
# unsupported driver started.
|
||||
self._supported = True
|
||||
|
||||
@property
|
||||
def supported(self):
|
||||
return self._supported
|
||||
|
@ -37,7 +37,7 @@ from oslo_utils import importutils
|
||||
import six
|
||||
|
||||
from cinder import exception
|
||||
from cinder.i18n import _, _LI
|
||||
from cinder.i18n import _, _LE, _LI, _LW
|
||||
from cinder.volume import configuration as config
|
||||
from cinder.zonemanager import fc_common
|
||||
import cinder.zonemanager.fczm_constants as zone_constant
|
||||
@ -61,7 +61,16 @@ zone_manager_opts = [
|
||||
cfg.StrOpt('fc_san_lookup_service',
|
||||
default='cinder.zonemanager.drivers.brocade'
|
||||
'.brcd_fc_san_lookup_service.BrcdFCSanLookupService',
|
||||
help='FC SAN Lookup Service')
|
||||
help='FC SAN Lookup Service'),
|
||||
cfg.BoolOpt('enable_unsupported_driver',
|
||||
default=False,
|
||||
help="Set this to True when you want to allow an unsupported "
|
||||
"zone manager driver to start. Drivers that haven't "
|
||||
"maintained a working CI system and testing are marked "
|
||||
"as unsupported until CI is working again. This also "
|
||||
"marks a driver as deprecated and may be removed in the "
|
||||
"next release."),
|
||||
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -81,6 +90,7 @@ class ZoneManager(fc_common.FCCommon):
|
||||
|
||||
VERSION = "1.0.2"
|
||||
driver = None
|
||||
_initialized = False
|
||||
fabric_names = []
|
||||
|
||||
def __new__(class_, *args, **kwargs):
|
||||
@ -94,6 +104,7 @@ class ZoneManager(fc_common.FCCommon):
|
||||
|
||||
self.configuration = config.Configuration(zone_manager_opts,
|
||||
'fc-zone-manager')
|
||||
self.set_initialized(False)
|
||||
self._build_driver()
|
||||
|
||||
def _build_driver(self):
|
||||
@ -102,11 +113,52 @@ class ZoneManager(fc_common.FCCommon):
|
||||
{'driver': zone_driver})
|
||||
|
||||
zm_config = config.Configuration(zone_manager_opts, 'fc-zone-manager')
|
||||
# Initialize vendor specific implementation of FCZoneDriver
|
||||
# Initialize vendor specific implementation of FCZoneDriver
|
||||
self.driver = importutils.import_object(
|
||||
zone_driver,
|
||||
configuration=zm_config)
|
||||
|
||||
if not self.driver.supported:
|
||||
self._log_unsupported_driver_warning()
|
||||
|
||||
if not self.configuration.enable_unsupported_driver:
|
||||
LOG.error(_LE("Unsupported drivers are disabled."
|
||||
" You can re-enable by adding "
|
||||
"enable_unsupported_driver=True to the "
|
||||
"fc-zone-manager section in cinder.conf"),
|
||||
resource={'type': 'zone_manager',
|
||||
'id': self.__class__.__name__})
|
||||
return
|
||||
|
||||
self.set_initialized(True)
|
||||
|
||||
@property
|
||||
def initialized(self):
|
||||
return self._initialized
|
||||
|
||||
def set_initialized(self, value=True):
|
||||
self._initialized = value
|
||||
|
||||
def _require_initialized(self):
|
||||
"""Verifies that the zone manager has been properly initialized."""
|
||||
if not self.initialized:
|
||||
LOG.error(_LE("Fibre Channel Zone Manager is not initialized."""))
|
||||
raise exception.ZoneManagerNotInitialized()
|
||||
else:
|
||||
self._log_unsupported_driver_warning()
|
||||
|
||||
def _log_unsupported_driver_warning(self):
|
||||
"""Annoy the log about unsupported fczm drivers."""
|
||||
if not self.driver.supported:
|
||||
LOG.warning(_LW("Zone Manager driver (%(driver_name)s %(version)s)"
|
||||
" is currently unsupported and may be removed in "
|
||||
"the next release of OpenStack. Use at your own "
|
||||
"risk."),
|
||||
{'driver_name': self.driver.__class__.__name__,
|
||||
'version': self.driver.get_version()},
|
||||
resource={'type': 'zone_manager',
|
||||
'id': self.driver.__class__.__name__})
|
||||
|
||||
def get_zoning_state_ref_count(self, initiator_wwn, target_wwn):
|
||||
"""Zone management state check.
|
||||
|
||||
@ -136,6 +188,17 @@ class ZoneManager(fc_common.FCCommon):
|
||||
host_name = None
|
||||
storage_system = None
|
||||
|
||||
try:
|
||||
# Make sure the driver is loaded and we are initialized
|
||||
self._log_unsupported_driver_warning()
|
||||
self._require_initialized()
|
||||
except exception.ZoneManagerNotInitialized:
|
||||
LOG.error(_LE("Cannot add Fibre Channel Zone because the "
|
||||
"Zone Manager is not initialized properly."),
|
||||
resource={'type': 'zone_manager',
|
||||
'id': self.__class__.__name__})
|
||||
return
|
||||
|
||||
try:
|
||||
initiator_target_map = (
|
||||
conn_info[zone_constant.DATA][zone_constant.IT_MAP])
|
||||
@ -202,6 +265,17 @@ class ZoneManager(fc_common.FCCommon):
|
||||
host_name = None
|
||||
storage_system = None
|
||||
|
||||
try:
|
||||
# Make sure the driver is loaded and we are initialized
|
||||
self._log_unsupported_driver_warning()
|
||||
self._require_initialized()
|
||||
except exception.ZoneManagerNotInitialized:
|
||||
LOG.error(_LE("Cannot delete fibre channel zone because the "
|
||||
"Zone Manager is not initialized properly."),
|
||||
resource={'type': 'zone_manager',
|
||||
'id': self.__class__.__name__})
|
||||
return
|
||||
|
||||
try:
|
||||
initiator_target_map = (
|
||||
conn_info[zone_constant.DATA][zone_constant.IT_MAP])
|
||||
|
@ -35,12 +35,18 @@ def create_zone_manager():
|
||||
if config.safe_get('zoning_mode') == 'fabric':
|
||||
LOG.debug("FC Zone Manager enabled.")
|
||||
zm = fc_zone_manager.ZoneManager()
|
||||
LOG.info(_LI("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
|
||||
if zm.initialized:
|
||||
LOG.info(_LI("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 %(zm_version)s disabled",
|
||||
{"zm_version": zm.get_version()})
|
||||
return None
|
||||
|
||||
else:
|
||||
LOG.debug("FC Zone Manager not enabled in cinder.conf.")
|
||||
return None
|
||||
|
Loading…
x
Reference in New Issue
Block a user