主要说一下initialize_application中的application_factory

     def loadapp():
app = application.application_factory(name)
return app

源码如下

 @fail_gracefully
def application_factory(name='public'):
if name not in ('admin', 'public'):
raise RuntimeError('Application name (for base_url lookup) must be '
'either `admin` or `public`.') # NOTE(morgan): The Flask App actually dispatches nothing until we migrate
# some routers to Flask-Blueprints, it is simply a placeholder.
app = flask.Flask(name)
app.after_request(_add_vary_x_auth_token_header) # NOTE(morgan): Configure the Flask Environment for our needs.
app.config.update(
# We want to bubble up Flask Exceptions (for now)
PROPAGATE_EXCEPTIONS=True) # TODO(morgan): Convert Subsystems over to Flask-Native, for now, we simply
# dispatch to another "application" [e.g "keystone"]
# NOTE(morgan): as each router is converted to flask-native blueprint,
# remove from this list. WARNING ORDER MATTERS; ordered dict used to
# ensure sane ordering of the routers in the legacy-dispatch model.
dispatch_map = collections.OrderedDict() # Load in Healthcheck and map it to /healthcheck
hc_app = healthcheck.Healthcheck.app_factory(
{}, oslo_config_project='keystone')
dispatch_map['/healthcheck'] = hc_app # More legacy code to instantiate all the magic for the dispatchers.
# The move to blueprints (FLASK) will allow this to be eliminated.
_routers = []
sub_routers = []
mapper = routes.Mapper()
for api_routers in ALL_API_ROUTERS:
moved_found = [pfx for
pfx in getattr(api_routers, '_path_prefixes', [])
if pfx in _MOVED_API_PREFIXES]
if moved_found:
raise RuntimeError('An API Router is trying to register path '
'prefix(s) `%(pfx)s` that is handled by the '
'native Flask app. Keystone cannot '
'start.' %
{'pfx': ', '.join([p for p in moved_found])}) routers_instance = api_routers.Routers()
_routers.append(routers_instance)
routers_instance.append_v3_routers(mapper, sub_routers)
# TODO(morgan): Remove "API version registration". For now this is kept
# for ease of conversion (minimal changes)
keystone.api.discovery.register_version('v3') # NOTE(morgan): We add in all the keystone.api blueprints here, this
# replaces (as they are implemented) the legacy dispatcher work.
for api in keystone.api.__apis__:
for api_bp in api.APIs:
api_bp.instantiate_and_register_to_app(app) # Build and construct the dispatching for the Legacy dispatching model
sub_routers.append(_ComposibleRouterStub(_routers))
legacy_dispatcher = keystone_wsgi.ComposingRouter(mapper, sub_routers) for pfx in itertools.chain(*[rtr.Routers._path_prefixes for
rtr in ALL_API_ROUTERS]):
import pdb;pdb.set_trace()
dispatch_map['/v3/%s' % pfx] = legacy_dispatcher
app.wsgi_app = KeystoneDispatcherMiddleware(
app.wsgi_app,
dispatch_map)
return app
fail_gracefully是个装饰器,主要是为了防止函数报错,抓一下exception,并记录报错信息,其中又使用了一个functools.wraps的装饰器,防止fail_gracefully对被装饰的函数造成影响
主要看27行dispatch_map = collections.OrderedDict(),这里创建了一个dispatch_map的变量,这个变量用于记录所有的路由分发

33行创建了一个router.Mapper()的对象mapper
     for api_routers in ALL_API_ROUTERS:
moved_found = [pfx for
pfx in getattr(api_routers, '_path_prefixes', [])
if pfx in _MOVED_API_PREFIXES]
if moved_found:
raise RuntimeError('An API Router is trying to register path '
'prefix(s) `%(pfx)s` that is handled by the '
'native Flask app. Keystone cannot '
'start.' %
{'pfx': ', '.join([p for p in moved_found])}) routers_instance = api_routers.Routers()
_routers.append(routers_instance)
routers_instance.append_v3_routers(mapper, sub_routers)

ALL_API_ROUTER是一个包含所有处理路由的类的列表,这个循环中主要是过滤掉所有的被移除的API,api_routes.Routers()继承wsgi.RoutersBase,并通过append_v3_routers将自己的路由信息记录到mapper中,其中sub_routers是记录顶层路由下的路由

sub_routers.append(_ComposibleRouterStub(_routers))这行代码将_router整合到sub_routers中
legacy_dispatcher = keystone_wsgi.ComposingRouter(mapper, sub_routers)这行代码最终调用的源代码如下
 class Router(wsgi.ComposableRouter):
def __init__(self, controller, collection_key, key,
resource_descriptions=None,
is_entity_implemented=True,
method_template=None):
self.controller = controller
self.key = key
self.collection_key = collection_key
self._resource_descriptions = resource_descriptions
self._is_entity_implemented = is_entity_implemented
self.method_template = method_template or '%s' def add_routes(self, mapper):
collection_path = '/%(collection_key)s' % {
'collection_key': self.collection_key}
entity_path = '/%(collection_key)s/{%(key)s_id}' % {
'collection_key': self.collection_key,
'key': self.key} mapper.connect(
collection_path,
controller=self.controller,
action=self.method_template % 'create_%s' % self.key,
conditions=dict(method=['POST']))
mapper.connect(
collection_path,
controller=self.controller,
action=self.method_template % 'list_%s' % self.collection_key,
conditions=dict(method=['GET', 'HEAD']))
mapper.connect(
entity_path,
controller=self.controller,
action=self.method_template % 'get_%s' % self.key,
conditions=dict(method=['GET', 'HEAD']))
mapper.connect(
entity_path,
controller=self.controller,
action=self.method_template % 'update_%s' % self.key,
conditions=dict(method=['PATCH']))
mapper.connect(
entity_path,
controller=self.controller,
action=self.method_template % 'delete_%s' % self.key,
conditions=dict(method=['DELETE'])) # Add the collection resource and entity resource to the resource
# descriptions. collection_rel = json_home.build_v3_resource_relation(
self.collection_key)
rel_data = {'href': collection_path, }
self._resource_descriptions.append((collection_rel, rel_data))
json_home.JsonHomeResources.append_resource(collection_rel, rel_data) if self._is_entity_implemented:
entity_rel = json_home.build_v3_resource_relation(self.key)
id_str = '%s_id' % self.key
id_param_rel = json_home.build_v3_parameter_relation(id_str)
entity_rel_data = {
'href-template': entity_path,
'href-vars': {
id_str: id_param_rel,
},
}
self._resource_descriptions.append((entity_rel, entity_rel_data))
json_home.JsonHomeResources.append_resource(
entity_rel, entity_rel_data)

通过add_router为route添加mapper

     for pfx in itertools.chain(*[rtr.Routers._path_prefixes for
rtr in ALL_API_ROUTERS]):
dispatch_map['/v3/%s' % pfx] = legacy_dispatcher

这里主要添加dispatch_map中的前缀和处理代码的映射关系,涉及到itertools.chain()用法的小技巧

最后一行的KeystoneDispatcherMiddleware类负责API的分发,同样是通过__call__()这个魔法函数

openstack Rocky系列之keystone:(二)keystone中API注册的更多相关文章

  1. openstack Rocky系列之keystone:(一)keystone的启动

    keystone在httpd的入口执行文件为/usr/bin/keystone-wsgi-public 查看文件/usr/bin/keystone-wsgi-public,根据代码,看到主要是这几行代 ...

  2. OpenStack学习系列之十二:安装ceph并对接OpenStack

        Ceph 是一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统.Ceph 的统一体现在可以提供文件系统.块存储和对象存储,分布式体现在可以动态扩展.在国内一些公司的云环境中,通常 ...

  3. 我非要捅穿这 Neutron(三)架构分析与代码实现篇(基于 OpenStack Rocky)

    目录 文章目录 目录 Neutron 的软件架构分析与实现 Neutron Server 启动流程 获取 WSGI Application Core API & Extension API C ...

  4. OpenStack实践系列②认证服务Keystone

    OpenStack实践系列②认证服务Keystone 三.实战OpenStack之控制节点3.1 CentOS7的时间同步服务器chrony 下载chrony # yum install -y chr ...

  5. (原创)OpenStack服务如何使用Keystone (二)---部署和配置Keystone中间件

    (一)Keystone端的操作 (二)如何在OpenStack服务上部署Keystone中间件 (三)详细配置keystonemiddleware 部署OpenStack时一般先安装Keystone服 ...

  6. OpenStack组件系列☞Keystone搭建

    一:版本信息 官网:http://docs.openstack.org/newton/install-guide-rdo/keystone.html 二:部署keystone 官网文档:http:// ...

  7. OpenStack组件系列☞Keystone

    Keystone(OpenStack Identity Service)是 OpenStack 框架中负责管理身份验证.服务规则和服务令牌功能的模块.用户访问资源需要验证用户的身份与权限,服务执行操作 ...

  8. openstack项目【day23】:keystone组件基础

    本节内容 一 什么是keystone 二 为何要有keystone 三 keystone的功能 四 keystone概念详解 五 keystone内包含的组件 六 keystone与openstack ...

  9. openstack项目【day24】:keystone部署及操作

    阅读目录 一 前言 二 版本信息 三 部署keystone 四 keystone操作 五 验证 六 创建脚本 七 keystone使用套路总结 一 前言 任何软件的部署都是没有技术含量的,任何就部署讲 ...

随机推荐

  1. firefox浏览器插件---网址优化

    安装:YSlow插件 之后还必须安装firebug.否则YSlow不能使用. 安装:firebug 下面就可以了

  2. java源码-HashMap源码分析

    这次开始分析JDK8中的HashMap源码. 首先理解HashMap中几个关键变量, TREEIFY_THRESHOLD  链表转换红黑树扩容值 table 数组+链表+红黑树  size 当前存储数 ...

  3. dokcer部署code-server web版vscode

    #dokcer部署code-server web版vscode codercom/code-server:latest不支持插件在线安装 codercom/code-server:v2目前为最新版1. ...

  4. Python中的变量和作用域详解

    Python中的变量和作用域详解 python中的作用域分4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部 ...

  5. Mac搭建学习PHP环境

    在sublime text 3中学习PHP,编写PHP代码: 使用的xampp开发环境: 第一步,就是安装xampp,这个没啥可说的,根据自己的系统下载安装就好,我的是OSX;第二步,就是用XAMPP ...

  6. message-digest algorithm 5

    using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptograph ...

  7. 【Python开发】python重命名文件和遍历文件夹操作

    当前文件夹下,把所有文件名中的"50076"替换成"50092",用Python实现,代码所下: # encoding: utf-8 import os imp ...

  8. cm_api

    cm API:https://github.com/cloudera/cm_api/tree/master/python/examples/auto-deploy#看集群有几个clustercurl ...

  9. 牛客小白月赛12-C(欧拉筛解积性方程)

    题目链接:https://ac.nowcoder.com/acm/contest/392/C 题意:给定n,求: 思路:令res[i]=iN  (%MOD),因为xn是一个积性函数,即(x*y)n=x ...

  10. [转帖]深度: NVMe SSD存储性能有哪些影响因素?

    深度: NVMe SSD存储性能有哪些影响因素? http://www.itpub.net/2019/07/17/2434/ 之前有一个误解 不明白NVME 到底如何在队列深度大的情况下来提高性能, ...