Ocata Neutron代码分析(四)——api-paste.ini分析

在Neutron API启动过程分析中,曾分析到加载wsgi app是通过load_paste_app函数首先实例化oslo_service.wsgi.py中的Loader类,返回一个loader对象。然后再调用loader对象的load_app函数来实现的。

def load_paste_app(app_name):
    """Builds and returns a WSGI app from a paste config file.

    :param app_name: Name of the application to load
    """
    loader = wsgi.Loader(cfg.CONF)
    app = loader.load_app(app_name)
    return app
class Loader(object):

    def load_app(self, name):
        """Return the paste URLMap wrapped WSGI application.

        :param name: Name of the application to load.
        :returns: Paste URLMap object wrapping the requested application.
        :raises: PasteAppNotFound

        """
        try:
            LOG.debug("Loading app %(name)s from %(path)s",
                      {'name': name, 'path': self.config_path})
            return deploy.loadapp("config:%s" % self.config_path, name=name)    # 调用第三方库paste.deploy的loadapp函数来加载wsgi_app并返回
        except LookupError:
            LOG.exception("Couldn't lookup app: %s", name)
            raise PasteAppNotFound(name=name, path=self.config_path)

下面分析一下paste.deploy的配置文件(即self.config_path),该配置文件默认为api-paste.ini。

[composite:neutron]
use = egg:Paste#urlmap
/: neutronversions_composite
/v2.0: neutronapi_v2_0

[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi request_id catch_errors extensions neutronapiapp_v2_0
keystone = cors http_proxy_to_wsgi request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0

[composite:neutronversions_composite]
use = call:neutron.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi neutronversions
keystone = cors http_proxy_to_wsgi neutronversions

[filter:request_id]
paste.filter_factory = oslo_middleware:RequestId.factory

[filter:catch_errors]
paste.filter_factory = oslo_middleware:CatchErrors.factory

[filter:cors]
paste.filter_factory = oslo_middleware.cors:filter_factory
oslo_config_project = neutron

[filter:http_proxy_to_wsgi]
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory

[filter:keystonecontext]
paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory

[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory

[filter:extensions]
paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory

[app:neutronversions]
paste.app_factory = neutron.api.versions:Versions.factory

[app:neutronapiapp_v2_0]
paste.app_factory = neutron.api.v2.router:APIRouter.factory

[filter:osprofiler]
paste.filter_factory = osprofiler.web:WsgiMiddleware.factory
这里只分析api-paste.ini的处理流程,具体paste配置文件的语法请参考其他文档。
app_name为该配置文件的入口,在NeutronApiService.create函数中传入了app_name为neutron。这里neutron的composite用Paste.urlmap来构造wsgi app:
  • url为'/':由neutronversions_composite处理;
  • url为'/v2.0':由neutronapi_v2_0处理。
neutronversions_composite的处理很简单,在response的body中返回Neutron API版本的相关信息。
下面重点分析neutronapi_v2_0。
[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = cors http_proxy_to_wsgi request_id catch_errors extensions neutronapiapp_v2_0
keystone = cors http_proxy_to_wsgi request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0

 use指定要调用的函数为/neutron/auth.py的pipeline_factory。noauth和keystone作为参数local_conf(dict)传入该函数。

def pipeline_factory(loader, global_conf, **local_conf):
    """Create a paste pipeline based on the 'auth_strategy' config option."""
    pipeline = local_conf[cfg.CONF.auth_strategy]           # 配置文件中auth_strategy设置是否需要验证token(口令)
    pipeline = pipeline.split()                             # pipeline:str -> list
    filters = [loader.get_filter(n) for n in pipeline[:-1]] # 获取所有的filters(排除最后一个neutronapiapp_v2_0,因为它是app),形成list
    app = loader.get_app(pipeline[-1])                      # neutronapiapp_v2_0中调用的类(APIRouter)在这一步被初始化,下一节分析
    filters.reverse()                                       # 反向filters列表,最靠近APIRouter的filter最先执行,即第一个执行的是extensions filter
    for filter in filters:
        app = filter(app)                                   # 将app作为参数依次传入每个filter
    return app

配置文件中的auth_strategy默认为keystone,即默认需要对token进行验证。下面重点分析一下app:neutronapiapp_v2_0和filter:extensions。

1.neutronapiapp_v2_0

[app:neutronapiapp_v2_0]
paste.app_factory = neutron.api.v2.router:APIRouter.factory

直接调用/neutron/api/v2/router.py中APIRouter的factory方法:

class APIRouter(base_wsgi.Router):

    @classmethod
    def factory(cls, global_config, **local_config):
        return cls(**local_config)

    def __init__(self, **local_config):
        ......

APIRouter的factory方法是一个classmethod,直接调用APIRouter的构造函数,对APIRouter进行初始化,这部分下一节分析。

2.extensions

[filter:extensions]
paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory

extensions filter直接调用/neutron/api/extensions.py中的plugin_aware_extension_middleware_factory方法:

def plugin_aware_extension_middleware_factory(global_config, **local_config):
    """Paste factory."""
    def _factory(app):
        ext_mgr = PluginAwareExtensionManager.get_instance()
        return ExtensionMiddleware(app, ext_mgr=ext_mgr)
    return _factory
该函数中只包含一个_factory函数,函数中首先获取了PluginAwareExtensionManager的实例,该类是一个单例模式的实现,在APIRouter初始化时初始化,在下一节进行分析。
接着,将ext_mgr作为参数初始化ExtensionMiddleware,ExtensionMiddleware的构造函数主要是将extensions中的resource进行map,而顶级的resource(network、subnet和port)将在APIRouter的构造函数中进行map,也将在下一节进行分析。

转载于:https://www.cnblogs.com/Luka-Modric/p/8117162.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值