Merge "Add supported driver checks to Zone Manager"

This commit is contained in:
Jenkins 2016-09-02 02:42:58 +00:00 committed by Gerrit Code Review
commit 29e00a3c63
5 changed files with 150 additions and 12 deletions

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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])

View File

@ -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