您的位置:首页 > 运维架构

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._instance
get_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的请求信息对应地放置在顶级资源集合体之中,为调用做好准备。至此,模块功能的扩展和加载就搞定了。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: