def get_provisioning_manager(): """ Gets a stevedore provisioning manager which controls access to all the possible drivers. Manager is used to call a method on one or more of the drivers. """ from stevedore import dispatch config = get_config() if config.get('PLUGIN_WHITELIST', ''): plugin_whitelist = config.get('PLUGIN_WHITELIST').split() mgr = dispatch.NameDispatchExtensionManager( namespace='pebbles.drivers.provisioning', check_func=lambda x: x.name in plugin_whitelist, invoke_on_load=True, invoke_args=(logger, get_config()), ) else: # ahem, load all plugins if string is empty or not available? # is this wise? -jyrsa 2016-11-28 mgr = dispatch.NameDispatchExtensionManager( namespace='pebbles.drivers.provisioning', check_func=lambda x: True, invoke_on_load=True, invoke_args=(logger, get_config()), ) logger.debug('provisioning manager loaded, extensions: %s ' % mgr.names()) return mgr
def mock_the_extension_manager(driver="fake", namespace="ironic.drivers"): """Get a fake stevedore NameDispatchExtensionManager instance. :param namespace: A string representing the namespace over which to search for entrypoints. :returns mock_ext_mgr: A DriverFactory instance that has been faked. :returns mock_ext: A real plugin loaded by mock_ext_mgr in the specified namespace. """ entry_point = None for ep in list(pkg_resources.iter_entry_points(namespace)): s = "%s" % ep if driver == s[:s.index(' =')]: entry_point = ep break # NOTE(lucasagomes): Initialize the _extension_manager before # instantiaing a DriverFactory class to avoid # a real NameDispatchExtensionManager to be created # with the real namespace. driver_factory.DriverFactory._extension_manager = ( dispatch.NameDispatchExtensionManager('ironic.no-such-namespace', lambda x: True)) mock_ext_mgr = driver_factory.DriverFactory() mock_ext = mock_ext_mgr._extension_manager._load_one_plugin( entry_point, True, [], {}, False) mock_ext_mgr._extension_manager.extensions = [mock_ext] mock_ext_mgr._extension_manager.by_name = dict( (e.name, e) for e in [mock_ext]) return (mock_ext_mgr, mock_ext)
def _init_extension_manager(cls): # NOTE(deva): In case multiple greenthreads queue up on this lock # before _extension_manager is initialized, prevent # creation of multiple NameDispatchExtensionManagers. if cls._extension_manager: return # NOTE(deva): Drivers raise "DriverLoadError" if they are unable to be # loaded, eg. due to missing external dependencies. # We capture that exception, and, only if it is for an # enabled driver, raise it from here. If enabled driver # raises other exception type, it is wrapped in # "DriverLoadError", providing the name of the driver that # caused it, and raised. If the exception is for a # non-enabled driver, we suppress it. def _catch_driver_not_found(mgr, ep, exc): # NOTE(deva): stevedore loads plugins *before* evaluating # _check_func, so we need to check here, too. if ep.name in CONF.enabled_drivers: if not isinstance(exc, exception.DriverLoadError): raise exception.DriverLoadError(driver=ep.name, reason=exc) raise exc def _check_func(ext): return ext.name in CONF.enabled_drivers cls._extension_manager = (dispatch.NameDispatchExtensionManager( 'ironic.drivers', _check_func, invoke_on_load=True, on_load_failure_callback=_catch_driver_not_found)) LOG.info(_LI("Loaded the following drivers: %s"), cls._extension_manager.names())
def _init_driver_factory(cls): # NOTE(deva): In case multiple greenthreads queue up on this lock # before _driver_factory is initialized, prevent creation # of multiple NameDispatchExtensionManagers. if not cls._driver_factory: cls._driver_factory = dispatch.NameDispatchExtensionManager( namespace='ironic.drivers', check_func=lambda x: True, invoke_on_load=True)
def _init_extension_manager(cls): # NOTE(deva): In case multiple greenthreads queue up on this lock # before _extension_manager is initialized, prevent # creation of multiple NameDispatchExtensionManagers. if not cls._extension_manager: cls._extension_manager = \ dispatch.NameDispatchExtensionManager('ironic.drivers', lambda x: True, invoke_on_load=True)
def _init_extension_manager(cls): # NOTE(deva): In case multiple greenthreads queue up on this lock # before _extension_manager is initialized, prevent # creation of multiple NameDispatchExtensionManagers. if cls._extension_manager: return # Check for duplicated driver entries and warn the operator # about them counter = collections.Counter(CONF.enabled_drivers).items() duplicated_drivers = list(dup for (dup, i) in counter if i > 1) if duplicated_drivers: LOG.warning( _LW('The driver(s) "%s" is/are duplicated in the ' 'list of enabled_drivers. Please check your ' 'configuration file.'), ', '.join(duplicated_drivers)) enabled_drivers = set(CONF.enabled_drivers) # NOTE(deva): Drivers raise "DriverLoadError" if they are unable to be # loaded, eg. due to missing external dependencies. # We capture that exception, and, only if it is for an # enabled driver, raise it from here. If enabled driver # raises other exception type, it is wrapped in # "DriverLoadError", providing the name of the driver that # caused it, and raised. If the exception is for a # non-enabled driver, we suppress it. def _catch_driver_not_found(mgr, ep, exc): # NOTE(deva): stevedore loads plugins *before* evaluating # _check_func, so we need to check here, too. if ep.name in enabled_drivers: if not isinstance(exc, exception.DriverLoadError): raise exception.DriverLoadError(driver=ep.name, reason=exc) raise exc def _check_func(ext): return ext.name in enabled_drivers cls._extension_manager = (dispatch.NameDispatchExtensionManager( 'ironic.drivers', _check_func, invoke_on_load=True, on_load_failure_callback=_catch_driver_not_found)) # NOTE(deva): if we were unable to load any configured driver, perhaps # because it is not present on the system, raise an error. if (sorted(enabled_drivers) != sorted(cls._extension_manager.names())): found = cls._extension_manager.names() names = [n for n in enabled_drivers if n not in found] # just in case more than one could not be found ... names = ', '.join(names) raise exception.DriverNotFound(driver_name=names) LOG.info(_LI("Loaded the following drivers: %s"), cls._extension_manager.names())
def test_name_dispatch_map_method(self): em = dispatch.NameDispatchExtensionManager( 'stevedore.test.extension', lambda *args, **kwds: True, invoke_on_load=True, invoke_args=('a',), invoke_kwds={'b': 'B'}, ) results = em.map_method(['t3', 't1'], 'get_args_and_data', 'first') self.assertEqual(results, [(('a',), {'b': 'B'}, 'first')])
def get_provisioning_manager(): from stevedore import dispatch config = get_config() if config.get('PLUGIN_WHITELIST', ''): plugin_whitelist = config.get('PLUGIN_WHITELIST').split() mgr = dispatch.NameDispatchExtensionManager( namespace='pouta_blueprints.drivers.provisioning', check_func=lambda x: x.name in plugin_whitelist, invoke_on_load=True, invoke_args=(logger, get_config()), ) else: mgr = dispatch.NameDispatchExtensionManager( namespace='pouta_blueprints.drivers.provisioning', check_func=lambda x: True, invoke_on_load=True, invoke_args=(logger, get_config()), ) logger.debug('provisioning manager loaded, extensions: %s ' % mgr.names()) return mgr
def test_name_dispatch_ignore_missing(self): def invoke(ep, *args, **kwds): return (ep.name, args, kwds) em = dispatch.NameDispatchExtensionManager( 'stevedore.test.extension', lambda *args, **kwds: True, invoke_on_load=True, invoke_args=('a',), invoke_kwds={'b': 'B'}, ) results = em.map(['t3', 't1'], invoke, 'first', named='named value',) expected = [('t1', ('first',), {'named': 'named value'})] self.assertEqual(results, expected)
def test_name_dispatch(): def invoke(ep, *args, **kwds): return (ep.name, args, kwds) em = dispatch.NameDispatchExtensionManager( 'stevedore.test.extension', lambda *args, **kwds: True, invoke_on_load=True, invoke_args=('a', ), invoke_kwds={'b': 'B'}, ) assert len(em.extensions) == 2 assert set(em.names()) == set(['t1', 't2']) results = em.map( ['t2'], invoke, 'first', named='named value', ) expected = [('t2', ('first', ), {'named': 'named value'})] assert results == expected
def get_mockable_extension_manager(driver, namespace): """Get a fake stevedore NameDispatchExtensionManager instance. :param namespace: A string representing the namespace over which to search for entrypoints. :returns mock_ext_mgr: A NameDispatchExtensionManager that has been faked. :returns mock_ext: A real plugin loaded by mock_ext_mgr in the specified namespace. """ entry_point = None for ep in list(pkg_resources.iter_entry_points(namespace)): s = "%s" % ep if driver == s[:s.index(' =')]: entry_point = ep break mock_ext_mgr = dispatch.NameDispatchExtensionManager( 'ironic.no-such-namespace', lambda x: True) mock_ext = mock_ext_mgr._load_one_plugin(entry_point, True, [], {}) mock_ext_mgr.extensions = [mock_ext] mock_ext_mgr.by_name = dict((e.name, e) for e in [mock_ext]) return (mock_ext_mgr, mock_ext)
def _init_extension_manager(cls): # NOTE(deva): In case multiple greenthreads queue up on this lock # before _extension_manager is initialized, prevent # creation of multiple NameDispatchExtensionManagers. if cls._extension_manager: return enabled_drivers = getattr(CONF, cls._enabled_driver_list_config_option, []) # Check for duplicated driver entries and warn the operator # about them counter = collections.Counter(enabled_drivers).items() duplicated_drivers = [] cls._enabled_driver_list = [] for item, cnt in counter: if not item: LOG.warning( _LW('An empty driver was specified in the "%s" ' 'configuration option and will be ignored. Please ' 'fix your ironic.conf file to avoid this warning ' 'message.'), cls._enabled_driver_list_config_option) continue if cnt > 1: duplicated_drivers.append(item) cls._enabled_driver_list.append(item) if duplicated_drivers: LOG.warning( _LW('The driver(s) "%s" is/are duplicated in the ' 'list of enabled_drivers. Please check your ' 'configuration file.'), ', '.join(duplicated_drivers)) # NOTE(deva): Drivers raise "DriverLoadError" if they are unable to be # loaded, eg. due to missing external dependencies. # We capture that exception, and, only if it is for an # enabled driver, raise it from here. If enabled driver # raises other exception type, it is wrapped in # "DriverLoadError", providing the name of the driver that # caused it, and raised. If the exception is for a # non-enabled driver, we suppress it. def _catch_driver_not_found(mgr, ep, exc): # NOTE(deva): stevedore loads plugins *before* evaluating # _check_func, so we need to check here, too. if ep.name in cls._enabled_driver_list: if not isinstance(exc, exception.DriverLoadError): raise exception.DriverLoadError(driver=ep.name, reason=exc) raise exc def _check_func(ext): return ext.name in cls._enabled_driver_list cls._extension_manager = (dispatch.NameDispatchExtensionManager( cls._entrypoint_name, _check_func, invoke_on_load=True, on_load_failure_callback=_catch_driver_not_found, propagate_map_exceptions=True)) # NOTE(deva): if we were unable to load any configured driver, perhaps # because it is not present on the system, raise an error. if (sorted(cls._enabled_driver_list) != sorted( cls._extension_manager.names())): found = cls._extension_manager.names() names = [n for n in cls._enabled_driver_list if n not in found] # just in case more than one could not be found ... names = ', '.join(names) raise exception.DriverNotFoundInEntrypoint( names=names, entrypoint=cls._entrypoint_name) # warn for any untested/unsupported/deprecated drivers or interfaces cls._extension_manager.map(cls._extension_manager.names(), _warn_if_unsupported) LOG.info(cls._logging_template, cls._extension_manager.names())