主要说一下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. 表视图为Group类型的注意问题

    使用group类型的tableview时,第一个section距离navigationbar的距离很大,不符合这边的设计图. 使用 myTableView . sectionHeaderHeight  ...

  2. 【.NET】CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\d29b5393\123c3a1c\App_Code.odl3w4o6.dll”--“拒绝访问。 ”

    IIS部署网站或者Webservice时,出现以下问题: CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Tempor ...

  3. ORACLE 更新 和 插入多条 数据

    --插入语句INSERT INTO OA_W_BAOXIAOMXYWB (ID,DONGTAITABLEPARENTSN,CHANPINNAMEGKFK,CHANPINJITIGKFK,CHANPIN ...

  4. 【Python开发】增强的格式化字符串format函数

    自python2.6开始,新增了一种格式化字符串的函数str.format(),可谓威力十足.那么,他跟之前的%型格式化字符串相比,有什么优越的存在呢?让我们来揭开它羞答答的面纱. 语法 它通过{}和 ...

  5. 【Linux开发】linux设备驱动归纳总结(四):3.抢占和上下文切换

    linux设备驱动归纳总结(四):3.抢占和上下文切换 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  6. java内存模型的实现

    前几天,发了一篇文章,介绍了一下JVM内存结构.Java内存模型以及Java对象模型之间的区别.其中,Java内存模型,是这三个知识点当中最晦涩难懂的一个,而且涉及到很多背景知识和相关知识. 网上有很 ...

  7. jump用户管理命令

    ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa手动拷贝id_rsa.pub的内容到其他机器 或者用 ssh-copy,但你得知道对方root密码 ssh-copy-i ...

  8. Oracle数据块

    最小单位的输入\输出 数据块由操作系统中的一个或多个块组成 数据库是表空间的基本单位 DB_BLOCK_SIZE 查看 Oracle 块的大小语句: SQL> show parameter db ...

  9. # 解决MongoDB突然无法连接的问题

    解决MongoDB突然无法连接的问题 使用命令,加上路径sudo mongod --dbpath=/var/lib/mongodb 这种情况一般是上一次使用的时候没有正常关闭数据库,正常启动:mong ...

  10. python-day43(正式学习)

    目录 复习 今日内容 字段操作 多表关系 外键 一对一:无级联关系 一对一:有级联关系 一对多 多对多 复习 """ 1.数据库的配置:my.ini [mysqld][m ...