本文为扶艾原创文章,版权所有,禁止转载!
请大家静下心来看源码分析的文章,看完后相信你会有收获的!
本文来自于微信公众号“扶艾”,欢迎大家关注获取更多精彩内容!
上篇内容主要分析了下创建虚拟机从点击按钮到发送http请求部分源码。这篇文章是本系列的第二篇文章,按照内容来说,这篇内容更多的在说nova api,和创建虚拟机的关系实在不大。不过这边文章能帮助大家更清晰的理解restful架构、wsgi以及openstack 如何构建api接口的。文中涉及东西很多,但都是必要得铺垫,有说得不对的地方,欢迎大家指出,欢迎大家拍砖!
nova api
这部分源码主要在两个地方:
- nova源码 /usr/lib/python2.7/site-packages/nova
- openstack服务管理源码 /usr/lib/python2.7/site-packages/oslo_service
首先,在开始阅读源码之前,需要先有几个铺垫。
rest
restful在openstack中大家应该是听得比较多了。rest是Roy Thomas Fielding在2000年的博士论文中提出的。如果大家想深入理解rest是什么,相比于网上去搜索答案,不如看下那篇博士论文。这里我们为大家准备了一份他的中文版的博士论文,大家扫描下方微信公众号二维码,回复fuai_rest即可获取。
现在网上一搜restful是什么?会出来很多的解释,很多术语都很专业,很多人都是看得云里雾里的。之前在网上看到一篇形象的解释,现在放在这大家理解理解:
没有用rest
POST /users/getuser 获取用户信息
POST /users/createuser 创建用户
POST /users/updateuser 更新用户信息
POST /users/deleteUser 删除用户
使用rest风格
GET /users/{user_id} 获取用户信息
POST /users 创建用户
PUT /users/{user_id} 更新用户信息
DELETE /users/{user_id} 删除用户信息
这里我也不过多解释rest了。openstack的api就是这种风格的api,所以叫它restful api。举个简单的例子:
POST v2/{project_id}/servers 创建虚拟机
GET v2/{project_id}/servers 获取所有虚拟机信息
routes
openstack的api是restful api,而restful架构的核心是资源以及对这些资源的操作。openstack定义了很多资源以及这些资源的操作函数。当openstack api接收到http请求时,怎么知道请求调用的是哪个资源的操作函数?这时候路由模块就登场了,它可以将请求url转换成相应的资源,并路由到对应的操作函数上。
Example:
#创建一个映射对象
mapper = routes.Mapper()
#实现一个资源类,openstack中有很多类似的Controller类,每一个Controller都对应了一个restful资源,该类下有对该资源的各种操作函数,比如index、show、create等
sc = ServerController()
#定义url到资源的映射
mapper.connect(None, '/svrlist', controller=sc, action='list')
mapper.resource('server', 'servers', controller=sc)
wsgi
wsgi是python中定义的web服务器和web应用程序之间的通用接口标准。它分成三个部分web服务器、web中间件、web应用程序。如果不理解这句话,那我再白话一点,它就像web服务器与你的应用程序之间管道一样。还不理解?那你知道nova api是需要实现那三个部分的就行了。
oslo.service
openstack的api接口既然采用的是wsgi标准,那它们是怎么实现这个标准的,翻了下前面几个版本的源码,kilo版本及之前实现wsgi相关的东西都是在nova这个源码目录下的,到了liberty版本之后,就正式将这部分源码从各个组件模块中提出了,就是现在的oslo.service。
oslo_service实现中,核心是oslo_serivce.service中的Service类和Launcher类。Service类描述一个服务,Launcher类用来启动服务。
paste.deploy
paste是openstack中用于实现wsgi标准的具体工具模块,它可以根据配置文件/etc/nova/api-paste.ini来加载wsgi app
api-paste.ini部分内容如下:
[composite:osapi_compute]
use = call:nova.api.openstack.urlmap:urlmap_factory
/: oscomputeversions
...
/v2.1: openstack_compute_api_v21
[composite:openstack_compute_api_v21]
use = call:nova.api.auth:pipeline_factory_v21
...
keystone = cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler authtoken keystonecontext osapi_compute_app_v21
...
[filter:sizelimit]
paste.filter_factory = oslo_middleware:RequestBodySizeLimiter.factory
[app:osapi_compute_app_v21]
paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory
上面配置文件出现了下面几个部分
- composite, 这个部分是将url请求分发到对应的app,use表明的是分发的方式,这里是urlmap进行分发的
- filter,这个其实对应的是wsgi 的middleware。上面的cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler authtoken keystonecontext这些都是middleware,osapi_compute_app_v21才是app。这些middleware是可以自行增加或删除的
接收到请求后,首先会交给middleware依次处理,最后交给app。
- paste的deploy可根据传入的app名称来加载wsgi app:
deploy.loadapp("config:/etc/nova/api-paste.ini", name=n