Paste Deploy
neutron的api-paste.ini:
[composite:neutron]
use = egg:Paste#urlmap
/: neutronversions
/v2.0: neutronapi_v2_0
[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = request_id catch_errors extensions neutronapiapp_v2_0
keystone = request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0
[filter:request_id]
paste.filter_factory = oslo.middleware:RequestId.factory
[filter:catch_errors]
paste.filter_factory = oslo.middleware:CatchErrors.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
0. Introduction
简单说吧,这玩意就是为了优化WSGI配置的,弄的很灵活,但是看着有点复杂。
1. section:
- 每对中括号是一个section,中括号里语法:type:name
- type 分为composite,app*,filter,具体含义看下面结合实例解释
2. composite:neutron
[composite:neutron]
use = egg:Paste#urlmap
/: neutronversions
/v2.0: neutronapi_v2_0
- neutron这个section是composite类型。composite原意是组合,这里是说这个section会把请求分发到别的section来完成,也就是说多个section组合在一起,实现neutron要做的事情
- use = egg:Paste#urlmap 表示使用Paste包的urlmap。urlmap把url路径和应用关联起来。也就是说下面两行把/ 关联到neutronversions, /v2.0 关联到neutronapi_v2_0。如果REST请求后面没跟版本的话,我们就用neutronversions这个app,跟了「v2.0」的话,就用neutronapi_v2_0。
3. app:neutronversions
paste.app_factory = neutron.api.versions:Versions.factory
- Paste Deploy支持几种工厂模式的应用,包括paste.app_factory, paste.composite_factory, paste.filter_factory, and lastly paste.server_factory
- paste.app_factory指定一个app工厂函数,返回一个wsgi的app。这是比较简单常用的一种方式
4. composite:neutronapi_v2_0
[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = request_id catch_errors extensions neutronapiapp_v2_0
keystone = request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0
- use = call:neutron.auth:pipeline_factory: call 表示直接调用类,neutron.auth 模块里的 pipeline_factory
- noauth 和 keystone : 这里和neutron.conf里auth_strategy 的配置有关,如果配置的是keystone, 那就使用keystone对应的值,其实那个值是个pipeline。
- 代码:
def pipeline_factory(loader, global_conf, **local_conf):
“”“Create a paste pipeline based on the ‘auth_strategy’ config option.”“”
#cfg.CONF.auth_strategy 是noauth或者keystone,local_conf就是一个字典,key,value就是api-paste.ini里noauth和keystone那两行
pipeline = local_conf[cfg.CONF.auth_strategy]
pipeline = pipeline.split()
filters = [loader.get_filter(n) for n in pipeline[:-1]]
#最后一个是app: neutronapiapp_v2_0
app = loader.get_app(pipeline[-1])
filters.reverse()
for filter in filters:
#把所有filter一层一层的套在app外面了, 类似与装饰器功能
app = filter(app)
return app
5. filter:request_id
[filter:request_id]
paste.filter_factory = oslo.middleware:RequestId.factory
filter的工厂,看一下oslo.middleware:RequestId.factory的代码,这个RequestId的filter主要是更新以下req,其它的filter还有检查错误的,应该是类似一个装饰器的作用
class RequestIdMiddleware(base.Middleware):
@webob.dec.wsgify
def __call__(self, req):
req_id = context.generate_request_id()
req.environ[ENV_REQUEST_ID] = req_id
response = req.get_response(self.application)
if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)
return response
6. Reference
http://pythonpaste.org/deploy/
http://www.choudan.net/2013/07/28/OpenStack-paste-deploy介绍.html