主要说一下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. Java语言实现 Base64 加密 & 解密

    Java语言实现 Base64 加密 & 解密 Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法. Base64 ...

  2. 基于axis的WebService的案例

    1.axis axis是Apache旗下产品,它是一个webservice容器,可被用于创建.部署和运行webservice.网址http://axis.apache.org/,网址上的部分截图如下. ...

  3. Node、Document关系的探究

    上图来自于<JavaScript权威指南(第六版)>P375 受到上图的启发,写了如下测试代码: var head = document.getElementsByTagName(&quo ...

  4. C#反射动态创建实例并调用方法

    在.Net 中,程序集(Assembly)中保存了元数据(MetaData)信息,因此就可以通过分析元数据来获取程序集中的内容,比如类,方法,属性等,这大大方便了在运行时去动态创建实例. MSDN解释 ...

  5. JavaScript基础入门06

    目录 JavaScript 基础入门06 Math 对象 Math对象的静态属性 Math对象的静态方法 指定范围的随机数 返回随机字符 三角函数 Date对象 基础知识 日期对象具体API 构造函数 ...

  6. 大觅网01Day

    1.首先在上手之前准备几样开发辅助工具: ①vmware ②ubuntu ③xshell ④xftp 2.创建ubuntu系统 打开vmware创建一个新的虚拟机 在创建虚拟机时有几处需要留意 首先是 ...

  7. PJzhang:今天才搞清身份证、银行卡……的编码规则

    猫宁!!! ​​   之前思考过常见证件的编码规则,抽空查了一下,发现挺有意思.   一般查询证件或者手机号归属地都是直接百度小工具,但是背后的查询机制如何,可能大多人不甚了解.   介绍几种生活中最 ...

  8. Java的Comparable接口

    Comparable接口提供比较对象大小功能,实现了此接口的类的对象比较大小将通过接口提供的compareTo方法. 此方法的返回int类型,分三种情况. 返回正数,当前对象大于目标对象 返回负数,当 ...

  9. 手写k-means算法

    作为聚类的代表算法,k-means本属于NP难问题,通过迭代优化的方式,可以求解出近似解. 伪代码如下: 1,算法部分 距离采用欧氏距离.参数默认值随意选的. import numpy as np d ...

  10. C++学习笔记-面向对象模型探究

    C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类.从计算机的角度,程序依然由数据段和代码段构成.那么C++编译器如何完成面向对象理论到计算机程 ...