neutron的插件加载机制
看neutron代码的时候见识到了neutron是如何加载插件的,其实就是看下stevedore的功能。
废话不多说,先上代码:
def __init__(self, **local_config):
mapper = routes_mapper.Mapper()
plugin = manager.NeutronManager.get_plugin()
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
主要分析一下plugin = manager.NeutronManager.get_plugin()的实现。简化后的代码如下:
def __init__(self, options=None, config_file=None):
if not options:
options = {}
plugin_provider = cfg.CONF.core_plugin
self.plugin = self._get_plugin_instance(CORE_PLUGINS_NAMESPACE,plugin_provider)
再贴一下self._get_plugin_instance的实现:
def _get_plugin_instance(self, namespace, plugin_provider):
plugin_class = self.load_class_for_provider(namespace, plugin_provider)
return plugin_class()
继续跟,找到load_class_for_provider的实现:
def load_class_for_provider(namespace, plugin_provider):
return utils.load_class_by_alias_or_classname(namespace,plugin_provider)
继续,找到load_class_by_alias_or_classname的实现(省略了异常处理):
def load_class_by_alias_or_classname(namespace, name):
if not name:
LOG.error(_LE("Alias or class name is not set"))
raise ImportError(_("Class not found."))
# Try to resolve class by alias
mgr = driver.DriverManager(namespace, name)
class_to_load = mgr.driver
return class_to_load
终于到重点了,mgr = driver.DriverManager(namespace, name)这个就是使用stevedore的实现,如下:
class DriverManager(NamedExtensionManager):
def __init__(self, namespace, name,
invoke_on_load=False, invoke_args=(),
invoke_kwds={},
on_load_failure_callback=None,
verify_requirements=False):
on_load_failure_callback = on_load_failure_callback \
or self._default_on_load_failure
super(DriverManager, self).__init__(
namespace=namespace,
names=[name],
invoke_on_load=invoke_on_load,
invoke_args=invoke_args,
invoke_kwds=invoke_kwds,
on_load_failure_callback=on_load_failure_callback,
verify_requirements=verify_requirements,
)
@property
def driver(self):
ext = self.extensions[0]
return ext.obj if ext.obj else ext.plugin