openstack學習之各種API
一句話: openstack各自獨立的項目通過RESTFUL API對外提供服務,而項目內的 各個主機上的進程 通訊主要通過RPC來通訊的。
openstack 獨立項目對外介面 ( RESTFUL API)
總結:aste.deploy模組載入 api-paste.init定義的,用於服務的wsgi app; 用webob庫對wsgi app進行封裝,簡化wsgi app的定義與編寫;使用routes庫來給服務內部定義url到具體函數的映射。deploy也有url到服務對應功能,但這個映射層次偏高一點,可以理解為二次精確映射。
個人覺得這個架構以後版本也會成為olso中的一個模組包。
網路上挺多相關文章不錯,這裡就轉兩章代表性,怕連結會找不到:
Python paste模組和routes模組
原作者自己寫個簡單-RESTFUL server的構架。不過要跑起來,需要自己完善下。作為實踐,修改,理解openstack RESTFUL 架構不錯。
Python paste模組和routes模組 【轉】
在閱讀openstack源碼時,發現其各個組件基本都是使用paste模組和routes模組來構建server以及處理路由資訊的,為了熟悉這些模組決定使用這些模組寫一個簡單的server,此server的構架和glance組件的設計保持一致。
首先使用paste建立一個app,然後wsgiref.simple_server啟動他,至於app的功能通過設定檔來決定
1 config = "python_paste.ini"2 appname = "common"3 wsgi_app = loadapp("config:%s" % os.path.abspath(config), appname)4 server = make_server('localhost',80,wsgi_app)5 server.serve_forever()
python_paste.ini
[composite:common]use = egg:Paste#urlmap/:showversion/log:showversion_log/v1:apiv1app[pipeline:showversion_log]pipeline = filter_log showversion[filter:filter_log ]#filter2 deal with time,read args belowmanagepaste.filter_factory = manage:LogFilter.factory[app:apiv1app]paste.app_factory = v1.router:MyRouterApp.factory[app:showversion]version = 1.0.0paste.app_factory = manage:ShowVersion.factory
/:showversion:列印版本號碼/log:showversion_log:列印版本號碼的同時做相應的日誌記錄/v1:apiv1app:模仿glance中的多版本api,將所有v1的請求轉寄apiv1app處理。
1 class ShowVersion(object): 2 ''' 3 app 4 ''' 5 def __init__(self,version): 6 self.version = version 7 def __call__(self,environ,start_response): 8 res = Response() 9 res.status = '200 OK'10 res.content_type = "text/plain"11 content = []12 content.append("%s\n" % self.version)13 res.body = '\n'.join(content)14 return res(environ,start_response)15 @classmethod16 def factory(cls,global_conf,**kwargs):17 print 'factory'18 print "kwargs:",kwargs19 return ShowVersion(kwargs['version'])
1 class LogFilter(object): 2 ''' 3 Log 4 ''' 5 def __init__(self,app): 6 self.app = app 7 def __call__(self,environ,start_response): 8 print 'you can write log.‘ 9 return self.app(environ,start_response)10 @classmethod11 def factory(cls,global_conf,**kwargs):12 return LogFilter
到此uri為/和/log時,均可得到伺服器的正常響應。但是/v1還沒有實現。不得不佩服python的強大,這麼幾行就實現了一個web伺服器的準系統,下面在介紹routes,配合routes就能夠實現更多的更優雅的uri路由機制。
註:此處對paste的設定檔介紹不多,大家去paste官網查看即可,寫的很詳細了,這個也不是很難,沒必要去一一介紹。
建立一個python模組v1,在v1裡面建立兩個檔案router.py和wsgi.py,wsgi.py是一個通用檔案,和業務無關,我們只需要關注router.py的實現即可,使用起來非常簡單方便。
router.py:
1 import wsgi 2 3 class ControllerTest(object): 4 def __init__(self): 5 print "ControllerTest!!!!" 6 def test(self,req): 7 print "req",req 8 return { 9 'name': "test",10 'properties': "test"11 }12 13 class MyRouterApp(wsgi.Router):14 '''15 app16 '''17 def __init__(self,mapper):18 controller = ControllerTest()19 mapper.connect('/test',20 controller=wsgi.Resource(controller),21 action='test',22 conditions={'method': ['GET']})23 super(MyRouterApp, self).__init__(mapper)
wsgi.py:
1 import datetime 2 import json 3 import routes 4 import routes.middleware 5 import webob 6 import webob.dec 7 import webob.exc 8 9 class APIMapper(routes.Mapper): 10 """ 11 Handle route matching when url is '' because routes.Mapper returns 12 an error in this case. 13 """ 14 15 def routematch(self, url=None, environ=None): 16 if url is "": 17 result = self._match("", environ) 18 return result[0], result[1] 19 return routes.Mapper.routematch(self, url, environ) 20 21 class Router(object): 22 def __init__(self, mapper): 23 mapper.redirect("", "/") 24 self.map =