OpenStack J版 Neutron-server服务加载与启动源码分析(二)
2014-11-04 12:25
701 查看
声明:本博客欢迎转载,但请保留原作者信息!作者:林凯团队:华为杭州OpenStack团队 本文是在学习Openstack的过程中整理和总结,由于时间和个人能力有限,错误之处在所难免,欢迎指正!在上一篇博客Neutron-server服务加载与启动源码分析(一)通过对api-paste.ini中配置信息的解析,最终就调用了WSGIApplicationapiv2的实现,具体就是neutron.api.v2.router:APIRouter.factory,这个WSGI Application的具体功能就是实现模块功能的扩展和加载过程。现在就深入了解该模块是如何实现模块功能的扩展和加载。首先来看下neutron.api.v2.router.py
classAPIRouter(wsgi.Router): @classmethod deffactory(cls, global_config,**local_config): return cls(**local_config) def__init__(self,**local_config): #路由映射 mapper = routes_mapper.Mapper() #获取插件 plugin = manager.NeutronManager.get_plugin() ext_mgr =extensions.PluginAwareExtensionManager.get_instance() #(1) ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP) col_kwargs = dict(collection_actions=COLLECTION_ACTIONS, member_actions=MEMBER_ACTIONS) def_map_resource(collection, resource, params, parent=None): #(2) allow_bulk = cfg.CONF.allow_bulk allow_pagination = cfg.CONF.allow_pagination allow_sorting = cfg.CONF.allow_sorting controller = base.create_resource( collection, resource, plugin, params, allow_bulk=allow_bulk, parent=parent, allow_pagination=allow_pagination, allow_sorting=allow_sorting) path_prefix =None if parent: path_prefix ="/%s/{%s_id}/%s"%(parent['collection_name'], parent['member_name'], collection) mapper_kwargs = dict(controller=controller, requirements=REQUIREMENTS, path_prefix=path_prefix, **col_kwargs) return mapper.collection(collection, resource, **mapper_kwargs) mapper.connect('index','/', controller=Index(RESOURCES)) #遍历建立对应资源的Controller for resource in RESOURCES: _map_resource(RESOURCES[resource], resource, attributes.RESOURCE_ATTRIBUTE_MAP.get( RESOURCES[resource], dict())) for resource in SUB_RESOURCES: _map_resource(SUB_RESOURCES[resource]['collection_name'], resource, attributes.RESOURCE_ATTRIBUTE_MAP.get( SUB_RESOURCES[resource]['collection_name'], dict()), SUB_RESOURCES[resource]['parent']) super(APIRouter, self).__init__(mapper)这里面有两个重要的函数(1)和(2)首先来看(1)函数:ext_mgr = extensions.PluginAwareExtensionManager.get_instance()最先执行的是PluginAwareExtensionManager的初始化中
classPluginAwareExtensionManager(ExtensionManager): _instance =None def__init__(self, path, plugins): self.plugins = plugins super(PluginAwareExtensionManager, self).__init__(path) self.check_if_plugin_extensions_loaded()调用父类的初始化,这边的path为/usr/lib/python2.7/dist-packages/neutron/extensions,根据注释可知是配置的extension路径。
classExtensionManager(object): def__init__(self, path): LOG.info(_('Initializing extension manager.')) self.path = path self.extensions ={} self._load_all_extensions() policy.reset()在_load_all_extensions()中
for path in self.path.split(':'): if os.path.exists(path): self._load_all_extensions_from_path(path) else: LOG.error(_("Extension path '%s' doesn't exist!"), path)在_load_all_extensions_from_path(path)中将/usr/lib/python2.7/dist-packages/neutron/extensions路径下的所有为“.py“的文件按照sorted排序顺序分别加载
def_load_all_extensions_from_path(self, path): # 对文件进行排序取出并加载 for f in sorted(os.listdir(path)): try: LOG.debug(_('Loading extension file: %s'), f) mod_name, file_ext = os.path.splitext(os.path.split(f)[-1]) ext_path = os.path.join(path, f) if file_ext.lower()=='.py'andnot mod_name.startswith('_'): mod = imp.load_source(mod_name, ext_path) ext_name = mod_name[0].upper()+ mod_name[1:] new_ext_class = getattr(mod, ext_name,None) ifnot new_ext_class: LOG.warn(_('Did not find expected name ' '"%(ext_name)s" in %(file)s'), {'ext_name': ext_name, 'file': ext_path}) continue new_ext = new_ext_class() self.add_extension(new_ext) except Exception as exception: LOG.warn(_("Extension file %(f)s wasn't loaded due to " "%(exception)s"),{'f': f,'exception': exception})其中加载的文件包括external_net.py,agent.py等文件回到(1)函数,初始化完成,就调用
defget_instance(cls): if cls._instance isNone: cls._instance = cls(get_extensions_path(), manager.NeutronManager.get_service_plugins()) returncls._instanceget_instance(cls)函数,在这个函数中,获取路径下的所有文件的paths和服务的插件,来构建cls并且返回。再来看第二个重要的(2)函数:def_map_resource(collection, resource, params, parent=None):这个函数是函数中内置的函数,下面被遍历调用。
def _map_resource(collection, resource, params, parent=None): #读取配置文件中关于分块、分页、排序的设置 allow_bulk = cfg.CONF.allow_bulk allow_pagination = cfg.CONF.allow_pagination allow_sorting = cfg.CONF.allow_sorting # create_resource中主要是根据资源信息建立Controller,这个Controller就是用以之后api请求到来之后真正去处理这些请求 #这个Controller是在neutron.api.v2.base中 #之后wsgi_resource.Resource中根据collection、resource以及对应的RESOURCE_ATTRIBUTE_MAP的信息 #创建一个xml和json的序列化和反序列化的对象 #序列化指:对xml或json语句进行解析,确定要引用的动作 #反序列化指:进行xml或json的封装 controller = base.create_resource( collection, resource, plugin, params, allow_bulk=allow_bulk, parent=parent, allow_pagination=allow_pagination, allow_sorting=allow_sorting) path_prefix = None if parent: path_prefix = "/%s/{%s_id}/%s" % (parent['collection_name'], parent['member_name'], collection) #根据之前创建的controller、REQUIREMENTS和path_prefix建立字典 mapper_kwargs = dict(controller=controller, requirements=REQUIREMENTS, path_prefix=path_prefix, **col_kwargs) #最后根据字典,建立neutron api的顶级资源集合体 return mapper.collection(collection, resource, **mapper_kwargs)_map_resource函数从字面的意思我们就可以看出他是对资源进行映射,这边的资源是什么?他对应的就是得到的URL,所以这个函数可以简单的理解为,得到了URL,通过这里实现的映射关系,进行格式匹配,具体定位到所要调用的方法上。这边就将URL的请求信息对应地放置在顶级资源集合体之中,为调用做好准备。至此,模块功能的扩展和加载就搞定了。
相关文章推荐
- OpenStack J版 Neutron-server服务加载与启动源码分析(一)
- Openstack学习笔记之——Neutron-server服务加载与启动源码分析(三)
- Openstack本学习笔记——Neutron-server服务加载和启动源代码分析(三)
- dataserver 源码分析(二) 启动服务
- Tomcat源码分析(一)--服务启动
- SystemServer进程启动过程源码分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- SystemServer进程启动过程源码分析
- [android源码分析]sdp Server的启动分析
- Android服务启动之StartService源码分析
- Android SurfaceFlinger服务启动过程源码分析
- System Server进程启动过程源码分析
- [android源码分析]sdp Server的启动分析
- Android服务启动之StartService源码分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- openstack 源码分析之swift proxy 服务启动 1
- spring启动component-scan类扫描加载过程---源码分析
- openstack 源码分析之swift proxy 服务启动 2
- OpenStack Swift源码分析(3)----swift服务启动源码分析之三