Keystone controller.py & routers.py代码解析
目录
Keystone WSGI 实现
Keystone 项目把每个功能都分到单独的目录下,EXAMPLE:
- token 相关的功能 ===> keystone/token/
- assignment 相关的功能 ===> keystone/assignment/
- auth 相关的功能 ===> keystone/auth/
- catalog 相关的功能 ===> keystone/catalog/
- credential 相关的功能 ===> keystone/credential/
- identity 相关的功能 ===> keystone/identity/
- policy 相关的功能 ===> keystone/policy/
- resource 相关的功能 ===> keystone/resource/
这些功能目录下都一般会有三个文件:routers.py/ controllers.py/ core.py
controllers.py
controllers.py 中的 action 操作函数调用了 core.py 中的底层接口实现来 RESTful API 对应的操作功能。
EXAMPLE:这个例子的代码非官方源码,用于理解。
# controller.py
class AccountController(wsgi.Controller):
def __init__(self, ext_mgr):
self.ext_mgr = ext_mgr
self.account_api = account_api.API()
super(AccountController, self).__init__()
@wsgi.serializers()
def index(self, req): #Action:index ==> HTTP:Get(all)
context = req.environ['duckbill.context']
params = req.GET
qs = {}
qs['page_count'] = params.get('page_count', DEFAULT_PAGE_COUNT)
qs['page_num'] = params.get('page_num', 0)
qs['account_name'] = params.get('account_name', None)
qs['pubcloud'] = params.get('pubcloud', None)
qs['user'] = params.get('user', None)
accounts = self.account_api.list_account(context, qs) #account_api.list_account()是从core.py中实现的函数
return {'accounts': accounts}
# core.py
class API(base.Base):
"""API for handling account resources."""
def __init__(self):
super(API, self).__init__()
def list_account(self, context, filter=None):
"""Get account list.
:param context: class:`RequestContext` instance
:param filter: select data by filter
:type: ``dict``
:return: return a list of class:`AccountInfo` instance.
"""
return self.db.account_get_all(context, filter) #调用 db Module 的方法实现对数据库的操作, db Module 使用了 ORM
# db.py
def account_get_all(context, filter=None):
"""Get account list.
:param context: class:`RequestContext` instance
:param filter: select data by filter
:type: ''dict''
:return: return a list of class:`AccountInfo` instance.
"""
return IMPL.account_get_all(context, filter=filter) #IMPL 主要在 oslo.db 通用库中实现
routers.py
routers.py 中实现了 URL 路由,把 URL 和 controllers.py 中的 action 对应起来。
EXAMPLE:
URl == http://hostname:35357/v3/auth/tokens 对 Keystone 而言,/v3 开头的请求会交给 keystone.service.v3_app_factory 这个函数生成的 application 来处理。
routes 的一般用法是创建一个 mapper 对象,然后调用该 Mapper 对象的 connect() 方法把 URL_Path(这里是 /auth/tokens )和 HTTP 内建方法映射到一个 controller 的某个 action 上。如果是这样的话,那么我们就需要先实现 controller 和其 action 操作函数。然后使用 mapper.connect() 将上述的几个关键的参数映射到一起。使得一个请求,在 Client 看起来是 URL ,在程序内部看起来就是一个 Action 操作函数。
keystone.service.v3_app_factory 这个函数说明了路由转发的原理,我们来看代码:
def v3_app_factory(global_conf, **local_conf): #v3_app_factory()函数中先遍历了所有的模块,将每个模块的路由都添加到同一个mapper对象中
...
mapper = routes.Mapper() # 创建一个 mapper 对象
...
router_modules = [auth, # Keystone 功能模块列表
assignment,
catalog,
credential,
identity,
policy,
resource]
...
for module in router_modules:
routers_instance = module.routers.Routers()
_routers.append(routers_instance)
routers_instance.append_v3_routers(mapper, sub_routers)
#将每个 keystone 功能模块的路由都添加到同一个 mapper 对象中,这样的话每个模块的 routes 都拥有了 mapper 的能力。
# Add in the v3 version api
sub_routers.append(routers.VersionV3('public', _routers))
return wsgi.ComposingRouter(mapper, sub_routers)
#然后把 mapper 对象作为参数用于初始化 wsgi.ComposingRouter 对象
# ComposingRouter 对象(在其父类Router中实现)被调用时,会 Return 一个 WSGI application 。
# 即当调用 keystone.service.v3_app_factory 这个函数时会返回一个 application 对象,用于连接 WSGI Server 和 Application(application参数传递请求)。
这个 wsgi.ComposingRouter 对象一定是一个 WSGI application,我们看看代码就知道了:
class Router(object):
"""WSGI middleware that maps incoming requests to WSGI apps."""
def __init__(self, mapper):
self.map = mapper
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
self.map)
#这个 application 中则使用了 routes 模块的中间件来实现了请求路由 (在routes.middleware.RoutesMiddleware中实现)。
#这里对 Path 进行路由的结果就是返回各个模块的 controllers.py 中定义的 controller (路由的结果就是将请求中的URL的资源和一个 controller 对应起来)。
#各个模块的 controller 都是一个WSGI application,这个你可以通过这些 controller 的类继承关系看出来
@webob.dec.wsgify()
def __call__(self, req):
return self._router
...
class ComposingRouter(Router):
def __init__(self, mapper=None, routers=None):
...
routes 模块把 URL_Path 映射到了一个 controller,但是如何把对 URL_Path 的处理(HTTP方法)映射到 controller 的操作函数(Action)呢?
这个可以从 controller 的父类 keystone.common.wsgi.Application 的实现看出来。
这个 Application 类中使用了 environ[‘wsgiorg.routing_args’] 中的数据来确定调用 controller 的哪个方法,这些数据是由上面提到的routes.middleware.RoutesMiddleware 设置的。所以最近调用哪一个 Controller 的 Action 还是由 routes.middleware.RoutesMiddleware 来决定的。
class Application(BaseApplication):
@webob.dec.wsgify()
def __call__(self, req):
arg_dict = req.environ['wsgiorg.routing_args'][1]
action = arg_dict.pop('action')
参考文档
routes 库的项目官网
Python Paste 库项目官网
通过demo学习OpenStack开发–API服务
Openstack Restful API 开发框架 Paste + PasteDeploy + Routes + WebOb
Keystone controller.py & routers.py代码解析的更多相关文章
- GraphSAGE 代码解析(四) - models.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(一) - unsupervised_train.py GraphSAGE 代码解析(二) - layers.py ...
- GraphSAGE 代码解析(三) - aggregators.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(一) - unsupervised_train.py GraphSAGE 代码解析(二) - layers.py ...
- GraphSAGE 代码解析(二) - layers.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(一) - unsupervised_train.py GraphSAGE 代码解析(三) - aggregator ...
- GraphSAGE 代码解析(一) - unsupervised_train.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(二) - layers.py GraphSAGE 代码解析(三) - aggregators.py GraphSA ...
- 使用python对py文件程序代码复用度检查
#!/user/bin/env python # @Time :2018/6/5 14:58 # @Author :PGIDYSQ #@File :PyCheck.py from os.path im ...
- 用 TensorFlow 实现 k-means 聚类代码解析
k-means 是聚类中比较简单的一种.用这个例子说一下感受一下 TensorFlow 的强大功能和语法. 一. TensorFlow 的安装 按照官网上的步骤一步一步来即可,我使用的是 virtua ...
- OpenStack之虚机热迁移代码解析
OpenStack之虚机热迁移代码解析 话说虚机迁移分为冷迁移以及热迁移,所谓热迁移用度娘的话说即是:热迁移(Live Migration,又叫动态迁移.实时迁移),即虚机保存/恢复(Save/Res ...
- pointnet.pytorch代码解析
pointnet.pytorch代码解析 代码运行 Training cd utils python train_classification.py --dataset <dataset pat ...
- django基础 -- 3. urls.py view.py 参数 别名 重定向 常用方法 静态文件
一.基本格式 from django.conf.urls import url from . import views #循环urlpatterns,找到对应的函数执行,匹配上一个路径就找到对应的函数 ...
随机推荐
- bzoj1046题解
[解题思路] 先倒着求一遍LIS,然后对于每个询问L从左到右找到第一个大于等于L的上升序列即可.复杂度O(N(log2N+M)). [参考代码] #pragma GCC optimize(2) #in ...
- 线性基思想+贪心——cf1249C
/*1+3+9+...+3^n<3^(n+1),按这个思路贪心一下就好*/#include<bits/stdc++.h> using namespace std; #define l ...
- Luogu P1738 洛谷的文件夹
P1738 Luogu 发一个链表题解! 仅有24ms,排名第一哦~ 圆圈代表点,每个店有两个指针,一个指向自己兄弟(同级文件夹),另一个指向自己孩子(子文件夹),还有一个保存当前名字. 有点像二叉树 ...
- nginx填坑补充(nginx根据上下文跳转ip或者域名)
今天有一个需求,要根据上下文调到不同的ip或域名地址,使用上下文做域名跳转的时候,proxy_pass域名后面一定要带‘/’否则会把nginx的上下文自动带入,这样就行. location ^~ /d ...
- 12、testng.xml指定运行测试包、测试类、测试方法
目录如下: TestFixture.java 代码如下: package com.testng.cn; import org.testng.annotations.*; public class Te ...
- Java控制台
Console类的目的是使Java程序和控制台之间的交互更容易.Console类是java.io包中的一个实用程序类,用于访问系统控制台.控制台不能保证在所有机器上的Java程序中可访问. 例如,如果 ...
- MFC VC 双缓冲绘图基本原理与实现,详细解释
转自:http://blog.csdn.net/foreverhuylee/article/details/21548107 当然你可以直接搜索到能用的代码,并且基本能满足要求.不过这样总不是学习的态 ...
- xshell6 远程连接时提示 WARNING! The remote SSH server rejected X11 forwarding request.
1.输入命令 vi /etc/ssh/sshd_config ,修改配置文件 2.将UserLogin no 的注释解除 3.执行yum install -y xorg-x11-font xorg ...
- hdu6393 /// 树链剖分
题目大意: 给定n q 在n个点n条边的图中 进行q次操作 0 k x 为修改第k条边的值为x 1 x y 为查询x到y的最短路 https://blog.csdn.net/nka_kun/artic ...
- MySQL数据库 -- Navicat、pycharm连接数据库
内容目录 1.Navicat使用 2.pycharm使用数据库 一.Navicat使用 #1. 测试+链接数据库 #2. 新建库 #3. 新建表,新增字段+类型+约束 #4. 设计表:外键 #5. 新 ...