设为首页 收藏本站
查看: 811|回复: 0

[经验分享] openstack XXX-api分析

[复制链接]

尚未签到

发表于 2017-6-26 15:24:22 | 显示全部楼层 |阅读模式
一、概述


  • RESTful API: 表征状态迁移,也就是说client端使用http的基本操作(主要四种:get, post, put, delete 对应增删改查)使服务端的资源状态转化;
  • WSGI: web server gateway interface  web服务网关接口,可以看作一个桥梁,一端连这服务端(wsgi server), 一端连接应用程序(wsgi app),桥体(wsgi middleware),也就是说wsgi server直接处理client端的http请求,将请求内容转译为应用app能够处理的对象; 
  api服务是入口,主要把client端发送http请求映射到具体处理函数上,主要涉及三个模块:


  • paste.deploy: 构建openstack的wsgi服务, /etc下都有对应项目的paste的文件,nova为例: /etc/nova/api-paste.ini, paste.deploy构建wsgi服务就是基于该配置文件
  • webob: 对wsgi的请求和响应进行封装(将wsgi与应用app的信息进行处理,使用端更方便进行处理,可以放入wsgi模块内理解)
  • routes: 定义url到内部函数的映射;    

二、python route 深入
  route 可以从url提取相应的参数,如controller,action或者其它用户自己定义的变量



#routes中的Mapper
#Mapper().connect    Mapper().match
from routes import Mapper  
map = Mapper()  
map.connect(None,"error/{action}/{id}",controller="controller_obj") #定义匹配规则  
result = map.match('error/myapp/4')  #匹配url='error/myapp/4'  
#result 匹配结果  
{'action': u'myapp', 'controller': u'controller_obj', 'id': u'4'}  
map.connect(None,"/message/:name",controller='my_contro')  #除 {} 外,:也可以作为匹配符号  
result = map.match('/message/12')  
#result 匹配结果  
{'controller': u'my_contro', 'name': u'12'}  
  openstack中的nova-api分析:



#!/usr/bin/env/python  
#coding=utf-8  
from routes import Mapper  
from routes import middleware  
import webob.dec  
from wsgiref.simple_server import make_server  
   
class controller(object):  
     def __init__(self):  
         self.i = 1  
     def __call__(self):  
         print self.i  
     def search(self):  
         return "do search()"  
     def show(self):  
         return "do show()"  
     def index(self):  
         return "do index()"  
     def update(self):  
         return "do update()"  
     def delete(self):  
         return "do delete()"  
     def create(self):  
         return "do create()"  
     def create_many(self):  
         return "do create_many()"  
     def update_many(self):  
         return "do update_many()"  
     def list_many(self):  
         return "do list_many()"  
     def delete_many(self):  
         return "do delete_many()"  
class appclass(object):
     def __init__(self):
         a = controller()
         map = Mapper()
         """路由匹配条件1"""  
         #curl -X GET http://localhost:8088/images
         #匹配条件指定了curl的动作为GET ,访问路径为images  对应的action 为search
         #map.connect('/images',controller=a,  
         #           action='search',  
         #           conditions={'method':['GET']})  
         """路由匹配条件2"""  
         #curl -X GET http://localhost:8088/show/hihi
         #curl -X POST http://lcoalhost:8088/failfunc/test
         #匹配条件没有指定curl的动作,即action参数,
         #因此所有的动作(PUT, POST, GET, ...)都匹配
         #第二个curl请求,匹配的action为failfunc, pid为test;但是
         #没有定义failfunc函数,报错
         #map.connect('name',"/{action}/{pid}",controller=a)  
         """路由匹配条件3"""  
         #map.resource内部定义了默认的匹配条件
         #第一个参数message为 member_name(资源名),
         #第二个参数messages为collection_name(资源集合名),一般定义资源集合名为资源名的复数,我这里随便取名
         #collection_name作为访问的路径名,且当没有传入参数controller时,controller=collection_name
         #该匹配相当于:
         #   map.connect('/messages',controller=a,action='index',conditions={'method':['GET']})
         #   map.connect('/messages',controller=a,action='create',conditions={'method':['POST']})
         #   map.connect('/messages/{id}',controller=a,action='show',conditions={'method':['GET']})
         #   map.connect('/messages/{id}',controller=a,action='update',conditions={'method':['PUT']})
         #   map.connect('/messages/{id}',controller=a,action='delete',conditions={'method':['DELETE']})
         #前两条是针对整个资源集合的操作,后三条是针对资源集合中某个固定资源的操作
         #map.resource("message","messages",controller=a,collection={'search':'GET'})  
         """路由匹配条件4"""  
         """
             map.resource除了默认的路由条件外,还可以额外的 '定义资源集合的方法',以及'单个资源的方法'
             collection={'search':'GET','create_many':'POST'} 定义了资源集合方法 search,
                 其curl动作为GET,create_many,其curl动作为POST
             member={'update_many':'POST','delete_many':'POST'} 定义了单个资源方法update_many,
                 其curl动作为POST, 其curl动作为POST
         """
         #map.resource('message', 'messages',controller=a,  
                         #collection={'list_many':'GET','create_many':'POST'},  
                         #member={'update_many':'POST','delete_many':'POST'})  
         """路由匹配条件5"""  
         """
             map.resource初始化时还可以指定curl访问路径的前缀路径,如匹配条件3及4没有指定时,默认为
             collection_name(资源集合名)
         """
         map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',  
                     collection={'list_many':'GET','create_many':'POST'},  
                     member={'update_many':'POST','delete_many':'POST'})  
         self.route = middleware.RoutesMiddleware(self.dispatch,map)  
     @webob.dec.wsgify  
     def __call__(self,req):  
         return self.route  
  
     @staticmethod  
     @webob.dec.wsgify  
     def dispatch(req):  
         match = req.environ['wsgiorg.routing_args'][1]  
         print "route match result is:",match  
         if not match:  
             return "fake url"  
         controller = match['controller']  
         action = match['action']  
         if hasattr(controller,action):  
             func = getattr(controller,action)  
             ret = func()  
             return ret  
         else:  
             return "has no action:%s" %action  
   
if __name__=="__main__":  
     app = appclass()  
     server = make_server('',8088,app)  
     server.serve_forever()
  分析:
  1)webob.dec.wsgify是webob为WSGI应用程序提供的一个装饰器,作用是将一个函数转换成一个WSGI应用。
    参考资料 http://tumblr.wachang.NET/post/38149417931/Python-paste-webob-3
  2)routes.middleware.RoutesMiddleware,将接受到的url,自动调用map.match()方法,将url进行路由匹配并将结果存入request请求的环境变量['wsgiorg.routing_args'],最后会调用其第一个参数给出的函数接口,即self.dispatch。
  参考资料   http://blog.csdn.Net/networm3/article/details/8666150
  3)map.connect 及map.resource均用来建立路由匹配条件
  针对程序中的匹配条件1  
  map.connect('/images',controller=a,action='search',conditions={'method':['GET']})

curl路由匹配结果 (程序中的route match result is)curl请求得到的结果
curl -X GET http://localhost:8088/images{'action': u'search', 'controller': <__main__.controller object at 0x10c2b10>}"do search()"
    匹配条件指定了curl的动作为GET ,访问路径为images  对应的action 为search
  匹配条件2
  map.connect('name',"/{action}/{pid}",controller=a)

curl路由匹配结果 (程序中的route match result is)curl请求得到的结果
curl -X GET  http://localhost:8088/show/hihi{'action': u'show', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'hihi'}"do show()"
curl -X POST  http://localhost:8088/failfunc/test{'action': u'failfunc', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'test'}"has no action:failfunc"
  匹配条件没有指定curl的动作,因此所有的动作(PUT,POST,GET,。。)都匹配,第二个curl请求,匹配的action 为failfunc,pid为test,但是程序没有定义failfunc函数,报错
  匹配条件3   
  map.resource("message","messages",controller=a)  ,map.resource内部定义了默认的匹配条件
    第一个参数message为 member_name(资源名),第二个参数messages为collection_name(资源集合名),一般定义资源集合名为资源名的复数,我这里随便取名
  collection_name作为访问的路径名,且当没有传入参数controller时,controller=collection_name
  map.resource("message","messages",controller=a) 等同于以下匹配条件:
  map.connect('/messages',controller=a,action='index',conditions={'method':['GET']})
  map.connect('/messages',controller=a,action='create',conditions={'method':['POST']})
  map.connect('/messages/{id}',controller=a,action='show',conditions={'method':['GET']})
  map.connect('/messages/{id}',controller=a,action='update',conditions={'method':['PUT']})
  map.connect('/messages/{id}',controller=a,action='delete',conditions={'method':['DELETE']})
  前两条是针对整个资源集合的操作,后三条是针对资源集合中某个固定资源的操作
DSC0000.png

  这里匹配结果中的id为某个具体资源id,这里乱取,后三条curl针对具体资源(id为12)的操作,前两条是针对整个资源集合的操作
  当url传入的id包含'.',会将'.'后的字符窜匹配为format,如输入的id 为 '12.hihi' ,匹配id='12', format='hihi'
  匹配条件4
  map.resource('message', 'messages',controller=a,
                        collection={'search':'GET','create_many':'POST'},
                        member={'update_many':'POST','delete_many':'POST'})
  map.resource除了默认的路由条件外,还可以额外的定义‘资源集合的方法’以及‘单个资源的方法’
  collection={'search':'GET','create_many':'POST'}       定义了资源集合方法 search,其curl动作为GET,create_many,其curl动作为POST
  member={'update_many':'POST','delete_many':'POST'}    定义了单个资源方法 update_many,其curl动作为POST,delete_many,其curl动作为POST
DSC0001.png

  匹配条件5
  map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',
                    collection={'list_many':'GET','create_many':'POST'},
                    member={'update_many':'POST','delete_many':'POST'})
  map.resource初始化时还可以指定curl访问路径的前缀路径,如匹配条件3及4没有指定时,默认为collection_name(资源集合名)
  指定path_prefix后,路径为path_prefix/collection_name
DSC0002.png

  在路由5的条件下,添加一条
  map.resource('type', 'types',controller=other_controller,
  parent_resource=dict(member_name='message',
  collection_name='messages'),
  path_prefix = '{projectid}/%s/:%s_id' %('nex','nexs'))
  curl -X POST  http://localhost:8088/proj1/nex/17/types
  匹配nexs_id 为17,controller 为other_controller,  parent_resource的作用为形成name_prefix = 'message_',具体作用不详,有待研究


  参考资料:http://routes.readthedocs.org/en/latest/restful.html
  疑问:
  resource中的controller对象的类定义必须要有__call__,要不然,匹配后变为type(controller)为unicode,原因不明,有待研究

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-388236-1-1.html 上篇帖子: libcloud----keystone----openstack SAIO 下篇帖子: Detach Volume 操作
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表