nova-api·¢²¼api·þÎñûÓÐÓõ½Ò»¸öЩ¿ò¼Ü£¬»ù±¾¶¼ÊÇ´ÓͷдµÄ¡£ÔÚ²»Á˽âËüʱ£¬ÒÔΪËü·Ç³£¸´ÔÓ£¬ÄÑÒÔÕÆÎÕ¡£»¨ÁËÁ½ÈýÌìµÄʱ¼ä°ÑËü·ÖÎöÒ»±éºó£¬·¢ÏÖËü±¾ÉíµÄ½á¹¹±È½Ï¼òµ¥£¬Ö÷ÒªÄѵãÔÚÓÚ¶ÔËüËùʹÓõÄһЩÀà¿â²»Á˽⣬Èçpaste.deploy/webob/routes¡£¶ÔÓÚpaste.deploy£¬½áºÏËüµÄ¹ÙÍøÎĵµ°ÑËüµÄÔ´Âë¿´ÁËÁ½±é¡£webob¿´µÄÊÇÔ´Âë¡£routes¿´µÄÊÇÎĵµ¡£¶ÔÓÚÕâЩÀà¿âÌṩµÄº¯Êý£¬Èç¹û´ÓÎĵµÖÐÈ¥Àí½âËûÃÇÏëÒª×öʲô£¬Õæ²»ÊǼþÈÝÒ×µÄÊ¡£²é¿´ÆäʵÏÖÔ´Â룬¾ÍÃ÷ÁËÁË¡£²»¹ýÔÚ·ÖÎöÔ´Âë¹ý³ÌÖУ¬Åöµ½Ã¿Ò»¸öÀà¿â¶¼È¥·Ò»±éËüµÄÔ´Â룬ÕâÒ²ÊǷdz£ÀÛÈ˵ģ¬ºóÆÚÉõÖÁ¶¼²»ÏëÔÙ¿´ÏÂÈ¥ÁË£¬ÒòΪÄÔ×ӱȽÏÑá·³ÁË¡£ËùÒÔÔÚѧϰroutesʱÖ÷ÒªÊÇ¿´ËüµÄÎĵµ£¬»ù±¾Àí½âÁË¡£
paste.deploy
ÓÃÀ´½âÎö/etc/nova/api-paste.iniÎļþ£¬¼ÓÔØÓÃÓÚ·þÎñµÄwsgi
app¡£ËüµÄ¹¦ÄÜÓУº
1 api-paste.iniÖÐÅäÖöà¸öwsgi app£¬deploy¿É¸ù¾Ý´«ÈëµÄapp
name¼ÓÔØÖ¸¶¨µÄwsgi app£»
deploy.loadapp("config:/etc/nova/api-paste.ini", name="osapi-compute") |
¼ÓÔØapi-paste.iniÖУ¬ÃûΪosapi-computeµÄWSGI
APP£¬²¢×÷Ϊ½á¹û·µ»Ø¡£
2 ͨ¹ýдÈëapi-paste.iniµÄÅäÖ㬿ɷ½±ãµØÊµÏÖÌØ¶¨×Ö·û¿ªÊ¼µÄurlµ½Ìض¨wsgi
appµÄÓ³Éä¡£È磺
[composite:osapi_compute] use = call:nova.api.openstack.urlmap:urlmap_factory /: oscomputeversions /v2: openstack_compute_api_v2 |
ͨ¹ý¸ÃÅäÖã¬ÒÔ¡°/v2¡±¿ªÊ¼µÄurl½«½»¸øÃûΪopenstack_compute_api_v2µÄWSGI
APP´¦Àí£¬ÆäËüÒÔ¡°/¡±¿ªµÄurl¾Í½»¸øoscomputerversions´¦Àí¡£ÆäʵÕâ²¢·ÇdeployµÄ¹¦ÄÜ£¬¶øÊÇÉÏÃæÅäÖõÄurlmapʵÏֵġ£²»¹ýͨ¹ýÅäÖÃÎļþ£¬ÔÙÓÉdeployµ÷ÓÃurlmap£¬Ê¹Óþ͸ü¼òµ¥ÁË¡£
3 middle wareµÄ¼òµ¥¼ÓÔØºÍÈ¥³ý¡£
[composite:openstack_compute_api_v2] use = call:nova.api.auth:pipeline_factory keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2 |
ÉÏÃæµÄfaultwrap sizelimit authtoken keystonecontext
ratelimit¶¼Îªmiddle ware£¨ÔÚnova´úÂëÖгÆÎªMiddleWare£¬deployÖгÆÎªfilter£©£¬osapi_compute_app_v2²ÅÊÇwsgi
app¡£ÇëÇóÏȽ»¸ømiddle ware´¦Àí£¬ÔÙÓÉmiddle ware¾ö¶¨Òª²»Òª»òÕßÔõô½»¸øwsgi
app´¦Àí¡£ÕâЩmiddle wareÊÇ¿ÉÒÔÌí¼ÓºÍÈ¥³ýµÄ£¬Èç¹û²»Ïë¶Ôosapi_compute_app_v2½øÐÐÏÞËÙ£¬ÄÇôȥµôratelimit¾Í¿ÉÒÔÁË¡£ÆäʵÕâÊÇpipeline_factoryʵÏֵŦÄÜ£¬²»¹ýͨ¹ýdeployÀ´ÅäÖüÓÔØ¸ü·½±ã¡£
nova-apiÖÐÌṩÁ˺ܶà·þÎñAPI£ºec2(ÓëEC2¼æÈݵÄAPI)£¬osapi_compute(openstack
compute×Ô¼º·ç¸ñµÄAPI)£¬osapi_volume(openstack volume·þÎñAPI)£¬metadata(metadata
·þÎñAPI)µÈ¡£Í¨¹ýÅäÖÃÎļþapi-paste.ini£¬¿ÉÒÔ·½±ã¹ÜÀíÕâЩAPI¡£
deployÌṩÁËserver¡¢filter¡¢appµÄ¸ÅÄÆäÖÐfilter£¨¼´middle
ware£©¡¢appÔÚnova-api±»ÖضÈʹÓ㬵ÄÈ·Ì«ºÃÓÃÁË¡£·¢²¼Ã¿¸öAPIʱ£¬ËüÃÇÓÐʱÐèҪһЩÏàͬµÄ¹¦ÄÜ£¬È磺keystoneÑéÖ¤¡¢ÏÞËÙ¡¢´íÎó´¦ÀíµÈ¹¦ÄÜ¡£nova½«ÕâЩ¹¦ÄÜʵÏÖΪmiddle
ware£¬Èç¹ûÐèÒª£¬Í¨¹ýapi-paste.iniÅäÖ㬸øËü¼ÓÉϾͿÉÒÔ¡£±ÈÈ磬ÎÒÐèÒª¼Ç¼ÿ¸ö·ÃÎÊnova-apiµÄip£¬¼°ËüÃǵķÃÎÊ´ÎÊýºÍ·ÃÎʵÄʱ¼ä¡£ÄÇôÎÒʵÏÖÒ»¸ömiddle
ware--nova.api.middleware:MonitorMiddlewareÀ´¼Ç¼ÕâЩÊý¾Ý¡£Í¨¹ýÏÂÃæµÄapi-paste.iniÅäÖ㬾ͿɶÔnova-apiµÄ·ÃÎʽøÐмǼÁË¡£
[composite:openstack_compute_api_v2] use = call:nova.api.auth:pipeline_factory keystone = faultwrap sizelimit authtoken keystonecontext ratelimit <strong>monitor</strong> osapi_compute_app_v2 [filter:<strong>monitor</strong>] paste.filter_factory = nova.api.middleware:MonitorMiddleware.factory |
webob
ÓÃÓÚ¶Ôwsgi app½øÐзâ×°£¬¼ò»¯wsgi appµÄ¶¨ÒåÓë±àд¡£webobÖ÷ÒªÌṩÈýÖÖ¹¦ÄÜ¡£
1 Request¡£¸ÃÀàÓÃÓÚ¶Ô´«¸øwsgi appµÄenv²ÎÊý½øÐзâ×°£¬¼ò»¯¶ÔHTTPÇëÇó²ÎÊýµÄ·ÃÎʺÍÉèÖá£ÕâÖÖ¼ò»¯ÌåÏÖÔÚ£¨¼ÙÉèÓÃenv¶ÔRequestʵÀý»¯ÁËÒ»¸ö¶ÔÏóreq£©£º
1) ʹÓüä½ÓÃ÷Á˵ÄÊôÐÔÃû¶ÔHTTP²ÎÊý½øÐзÃÎÊ£¬req.method¿É»ñÈ¡HTTPÇëÇó·½·¨£¨Ìæ´úREQUEST_METHOD£©£»req.scheme¿É»ñÈ¡HTTPÇëÇóÐÒéhttp
or https£¨Ìæ´úwsgi.url_scheme£©£»req.body»ñÈ¡ÇëÇóbody£¨Ìæ´úwsgi.input£©¡£
2£©´óÁ¿Ê¹ÓÃproperty£¬Ê¡È¥·±Ëöϸ½Ú£¬¼ò»¯HTTP²ÎÊýµÄ·ÃÎʺÍÉèÖá£req.bodyÖ±½Ó·ÃÎÊHTTPÇëÇóµÄbody£¬¶ø²»Óÿ¼ÂÇ£¨bodyµÄ³¤¶ÈºÍ×Ö·û±àÂ룩£»req.POSTÒÔ×ÖµäÐÎʽ·µ»ØPOSTÇëÇóµÄ²ÎÊý£»req.GETÒÔ×ÖµäÐÎʽ·µ»ØGETÇëÇóµÄ²ÎÊý¡£
nova.api.openstack.wsgi.Request¼Ì³Ð¸ÃÀ࣬²¢¼ÓÁËÒ»¸ö»º´æÒÑ·ÃÎÊdbµÄ¼Ç¼µÄ¹¦ÄÜ£¬ºÍ¶Ôcontent_typeÅжϺͼì²âµÄ¹¦ÄÜ¡£
2 Response¡£¸ÃÀàÓÃÓÚ¶ÔHTTPµÄ·µ»ØÖµ½øÐзâ×°¡£ÓëRequest¶ÔÏóÀàËÆ£¬Í¬ÑùʹÓÃÁËproperty¼ò»¯¶Ôhttp²ÎÊýµÄ·ÃÎʺÍÉèÖá£Ö§³Öwsgi
appÒ»´Î·µ»ØstatusºÍbody£¬ÕâÑù¸üÖ±¹Û¡£ÆäʵResponseʵÀý±¾ÉíÒ²ÊÇÒ»¸öwsgi app¡£
3 decorator--wsgify£¬×°ÊÎwsgi app£¬Ê¹Æä¿ÉÒÔÒÔÈçÏ·½Ê½¶¨Ò壺
@webob.dec.wsgify def wsgi_app(req): #do something with req return req.Response(...) |
ÆäÖвÎÊýreqÊÇÒ»¸öRequest£¨Ä¬ÈÏ£©»òÆä×ÓÀࣨͨ¹ýwsgify(RequestClass=XXX)Ö¸¶¨£©µÄʵÀý£¬ÊÇÓÃenv³õʼ»¯µÄ¡£req.ResponseĬÈÏΪwebob.Response¡£ÒÔ¸ÃÖÖ·½Ê½¶¨ÒåµÄwsgi
app£¬Æä½á¹û¿ÉÒÔÒÔÈýÖÖÐÎʽ·µ»Ø£º
1£©·µ»ØÒ»¸ö×Ö·û´®¡£wsgify½«Æä×÷Ϊbody£¬²¢¼ÓÉÏһЩĬÈϵIJÎÊý£¬Èçstatus=¡°200
OK", content_type, content_lengthµÈ£¬¹¹Ôì³ÉÒ»¸öHTTPÏìÓ¦½á¹û²¢·µ»Ø£»
2£©·µ»ØÒ»¸öResponseʵÀý£¬Ö±½Ó·µ»Ø¸Ãresp´ú±íµÄHTTPÇëÇó½á¹û£»
3£©·µ»ØÒ»¸öwsgi app£¬wsgify»á¼ÌÐøµ÷ÓøÃapp£¬²¢·µ»ØappµÄÏìÓ¦½á¹û¡£
nova.wsgi.Router¾ÍÊÇÓõÚÈýÖÖ·µ»ØÐÎʽ£¬Á½´Î·µ»Øwsgi
app£¬×îÖÕ½«HTTPÇëÇó¸ù¾ÝurlÓ³Éäµ½¶ÔÓ¦µÄcontroller´¦Àí¡£
routes
ÓÃÀ´¸ø·þÎñÄÚ²¿¶¨Òåurlµ½¾ßÌ庯ÊýµÄÓ³Éä¡£deployÒ²ÓÐurlµ½·þÎñÓ³É书ÄÜ£¬µ«Õâ¸öÓ³Éä²ã´ÎÆ«¸ßÒ»µã¡£¸ù¾ÝÉÏÃæÅäÖã¬deploy½«ÒÔ¡°/v2¡±¿ªÊ¼µÄurl½«½»¸øÃûΪopenstack_compute_api_v2´¦Àí¡£µ«openstack_compute_api_v2Ôõô½«/v2/project_id/servers/µÄGETÇëÇ󽻸ønova.api.openstack.compute.servers.Controller.index()´¦Àí£¬²¢ÇÒ½«POSTÇëÇ󽻸øcreate()´¦ÀíÄØ£»Ôõô½«/v2/project_id/servers/idµÄGETÇëÇ󽻸øshow()´¦ÀíÄØ£¿Õâ¸ö¾ÍÊÇroutes.mappersËùÌṩµÄ¹¦ÄÜ£¬Ëü¸ù¾ÝpathºÍÇëÇó·½·¨£¬½«ÇëÇóÓ³Éäµ½¾ßÌåµÄº¯ÊýÉÏ¡£ÈçÔÚnovaÖУ¬Ìí¼Ó/v2/project_id/servers/{list_vm_state,
os_vmsum}Á½¸öGETÇëÇóÀ´·Ö±ð»ñȡָ¶¨VMµÄ״̬ºÍVMµÄ×ÜÊý¡£¿ÉÔÚnova.api.openstack.compute.APIRouterÖÐÌí¼ÓÈçÏÂÁ½ÐУ¬½«ÇëÇó·Ö±ð½»¸ølist_vm_stateºÍos_vmsumÁ½¸öº¯Êý´¦Àí²¢·µ»Ø½á¹û£º
self.resources['servers'] = servers.create_resource(ext_mgr) mapper.resource("server", "servers", controller=self.resources['servers'], <strong>collection={'list_vm_state': 'GET', 'os_vmsum': 'GET'}</strong>) |
ÕâÀïÀûÓÃÁËroutes.mapperÖ§³Örestful apiµÄÌØÐÔ£¬½öÓÃÁ½ÌõÖ¸Á¾Í¶¨ÒåÁËÊ®¶à¸öurlµ½º¯ÊýµÄÓ³Éä¡£µ±È»Äã¿ÉÒÔÈçÏ·½Ê½Ìí¼Ó½Ó¿Ú£¬²»¹ý´úÂëÉԶ࣬·ç¸ñ²»ÄÇôͳһ£º
mapper.connect("server", "/{project_id}/servers/list_vm_state", controller=self.resources['servers'], action='list_vm_state', conditions={'list_vm_state': 'GET'}) mapper.connect("server", "/{project_id}/servers/os_vmsum", controller=self.resources['servers'], action='os_vmsum', conditions={'os_vmsum': 'GET'}) |
Ö÷Ìâ--nova-api·þÎñÁ÷³Ì·ÖÎö
ÉÏÃæ½éÉÜÁËnova-api·¢²¼ËùÓõ½µÄһЩlib¿â£¬ÓÐÁËÉÏÃæµÄ»ù´¡ÖªÊ¶£¬ÔÙÀ´·ÖÎönova-apiµÄ·¢²¼Á÷Á¿£¬¾Í±È½ÏÇáËÉÁË¡£
nova-api¿ÉÒÔÌṩ¶àÖÖapi·þÎñ£ºec2, osapi_compute,
osapi_volume, metadata¡£¿ÉÒÔͨ¹ýÅäÖÃÏîenabled_apisÀ´ÉèÖÃÆô¶¯ÄÄЩ·þÎñ£¬Ä¬ÈÏÇé¿öÏ£¬ËÄÖÖ·þÎñ¶¼ÊÇÆô¶¯µÄ¡£
´Ónova-apiµÄ¿ÉÖ´Ðнű¾ÖУ¬¿ÉÒÔ¿´³öÿ¸önova-api·þÎñ¶¼ÊÇͨ¹ýnova.service.WSGIServiceÀ´¹ÜÀíµÄ£º
class WSGIService(object): def __init__(self, name, loader=None): self.name = name self.manager = self._get_manager() self.loader = loader or wsgi.Loader() self.app = self.loader.load_app(name) self.host = getattr(FLAGS, '%s_listen' % name, "0.0.0.0") self.port = getattr(FLAGS, '%s_listen_port' % name, 0) self.workers = getattr(FLAGS, '%s_workers' % name, None) self.server = wsgi.Server(name, #ÕâÀïͨ¹ýeventletÀ´Æô¶¯·þÎñ self.app, host=self.host, port=self.port) def start(self): if self.manager: self.manager.init_host() self.server.start() ...... |
´ÓÉÏ¿ÉÖª£¬WSGIServiceʹÓÃself.app = self.loader.load_app(name)À´¼ÓÔØwsgi
app£¬app¼ÓÔØÍê³Éºó£¬Ê¹ÓÃnova.wsgi.ServerÀ´·¢²¼·þÎñ¡£ServerÊ×ÏÈÓÃÖ¸¶¨ipºÍportʵÀý»¯Ò»¸ö¼àÌýsocket£¬²¢Ê¹ÓÃwsgi.serverÒÔг̵ķ½Ê½À´·¢²¼socket£¬²¢½«¼àÌýµ½µÄhttpÇëÇ󽻸øapp´¦Àí¡£¶ÔÓÚServerµÄÆô¶¯¹ý³Ì£¬´úÂëÉÏÀí½â»¹ÊDZȽϼòµ¥µÄ£¬Ã»¶àÉÙ·ÖÎöµÄ¡£ÏÂÃæÎÒÃÇÖ÷ÒªÀ´·ÖÎö´¦ÀíHTTPÇëÇóµÄwsgi
appÊÇÈçºÎ¹¹½¨µÄ£¬¶ÔÓÚÿһ¸öÇëÇó£¬ËüÊÇÈçºÎ¸ù¾ÝurlºÍÇëÇó·½·¨½«ÇëÇó·Ö·¢µ½¾ßÌåµÄ¾ßÌ庯Êý´¦ÀíµÄ¡£
ÉϸöÓï¾äself.loader.load_app(name)ÖеÄloaderÊÇnova.wsgi.LoaderµÄʵÀý¡£Loader.load_app(name)Ö´ÐÐÏÂÃæÖ¸ÁʹÓÃdeployÀ´¼ÓÔØwsgi
app£º
deploy.loadapp("config:%s" % self.config_path, name=name) |
self.config_pathΪapi-paste.iniÎļþ·¾¶£¬Ò»°ãΪ/etc/nova/api-paste.ini¡£nameΪec2,
osapi_compute, osapi_volume, metadataÖ®Ò»£¬¸ù¾ÝÖ¸¶¨µÄname²»Í¬À´¼ÓÔØ²»Í¬µÄwsgi
app¡£ÏÂÃæÒÔname=¡°osapi_compute¡±Ê±£¬¼ÓÔØÌṩopenstack compute API·þÎñµÄwsgi
app×÷Ϊ¾ßÌå·ÖÎö¡£osapi_computeµÄÅäÖÃÈçÏÂ
[composite:osapi_compute] use = call:nova.api.openstack.urlmap:urlmap_factory /: oscomputeversions /v2: openstack_compute_api_v2 |
osapi_computeÊǵ÷ÓÃurlmap_factoryº¯Êý·µ»ØµÄÒ»¸önova.api.openstack.urlmap.URLMapʵÀý£¬nova.api.openstack.urlmap.URLMap¼Ì³Ðpaste.urlmap.URLMap£¬ËüÌṩÁËwsgiµ÷Óýӿڣ¬ËùÒÔ¸ÃʵÀýΪwsgi
app¡£µ«ÊǺ¯Êýnova.api.openstack.urlmap:urlmap_factoryÓëpaste.urlmap.urlmap_factory¶¨ÒåÍêȫһÑù£¬²»¹ýÓÉÓÚËüÃÇËùÔÚµÄmodule²»Í¬£¬Ê¹µÃËüÃÇËùÓõÄURLMap·Ö±ðΪÓëËü´¦ÓÚͬһmoduleµÄURLMap¡£paste.urlmap.urlmap_factoryÕ¦²»Ö§³ÖÒ»¸ö´«²Î£¬À´Ö¸¶¨URLMapÄØ£¿ÕâÑùnova¾Í²»ÓÃÖØÐ´Ò»ÑùµÄurlmap_factoryÁË¡£paste.urlmap.URLMapʵÏֵŦÄܼܺòµ¥£º¸ù¾ÝÅäÖý«urlÓ³Éäµ½ÌØ¶¨wsgi
app£¬²¢¸ù¾ÝurlµÄ³¤¶Ì×÷Ò»¸öÓÅÏȼ¶ÅÅÐò£¬url½Ï³¤µÄ½«ÓÅÏȽøÐÐÆ¥Åä¡£ËùÒÔ/v2½«ÏÈÓÚ/½øÐÐÆ¥Åä¡£URLMapÔÚµ÷ÓÃϲãµÄwsgi
appǰ£¬»á¸üÐÂSCRIPT_NAMEºÍPATH_INFO
nova.api.openstack.urlmap.URLMap¼Ì³ÐÁËpaste.urlmap.URLMap£¬²¢Ð´ÁËÒ»¶Ñ´úÂ룬ÆäʵֻÊÇΪÁËʵÏÖ¶ÔÇëÇóÀàÐ͵ÄÅжϣ¬²¢ÉèÖÃenviron['nova.best_content_type']£ºÈç¹ûurlµÄºó׺ÃûΪjson£¨Èç/xxxx.json£©£¬ÄÇôenviron['nova.best_content_type']=¡°application/json¡±¡£Èç¹ûurlûÓкó׺Ãû£¬ÄÇô½«Í¨¹ýHTTP
headersµÄcontent_type×Ö¶ÎÖÐmimetypeÅжϡ£·ñÔòĬÈÏenviron['nova.best_content_type']=¡°application/json¡±¡£
¾ÉÏÃæÅäÖüÓÔØµÄosapi_computeΪһ¸öURLMapʵÀý£¬wsgi
serverµÄ½ÓÊܵÄHTTPÇëÇó½«Ö±½Ó½»¸ø¸ÃʵÀý´¦Àí¡£Ëü½«urlΪ'/v2/.*'µÄÇëÇ󽫽»¸øopenstack_compute_api_v2£¬urlΪ'/'µÄÇëÇ󽻸øoscomputerversions´¦Àí£¨ËüÖ±½Ó·µ»ØÏµÍ³°æ±¾ºÅ£©¡£ÆäËüµÄurlÇëÇó£¬Ôò·µ»ØNotFound¡£ÏÂÃæ¼ÌÐø·ÖÎöopenstack_compute_api_v2£¬ÆäÅäÖÃÈçÏ£º
[composite:openstack_compute_api_v2] use = call:nova.api.auth:pipeline_factory noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2 keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2 keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v2 |
openstack_compute_api_v2Êǵ÷ÓÃnova.api.auth.pipeline_factory()·µ»ØµÄwsgi
app¡£pipeline_factory()¸ù¾ÝÅäÖÃÏîauth_strategyÀ´¼ÓÔØ²»Í¬µÄfilterºÍ×îÖÕµÄosapi_compute_app_v2¡£filterµÄ´ó¸ÅÅäÖÃÈçÏ£º
[filter:faultwrap] paste.filter_factory = nova.api.openstack:FaultWrapper.factory |
filterÔÚnovaÖжÔÓ¦µÄÊÇnova.wsgi.Middleware£¬ËüµÄ¶¨ÒåÈçÏ£º
class Middleware(Application): @classmethod def factory(cls, global_config, **local_config): def _factory(app): return cls(app, **local_config) return _factory def __init__(self, application): self.application = application def process_request(self, req): return None def process_response(self, response): return response @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): response = self.process_request(req) if response: return response response = req.get_response(self.application) return self.process_response(response) |
Middleware³õʼ»¯½ÓÊÕÒ»¸öwsgi app£¬ÔÚµ÷ÓÃwsgi app֮ǰ£¬Ö´ÐÐprocess_request()¶ÔÇëÇó½øÐÐÔ¤´¦Àí£¬ÅжÏÇëÇóÊÇ·ñ½»¸ø´«ÈëµÄwsgi
app£¬»¹ÊÇÖ±½Ó·µ»Ø£¬»òÕßÐÞ¸ÄЩreqÔÙ¸ø´«ÈëµÄwsgi app´¦Àí¡£wsgi app·µ»ØµÄresponseÔÙ½»¸øprocess_response()´¦Àí¡£ÀýÈ磬¶ÔÓÚ½øÐÐÑéÖ¤µÄÂß¼£¬¿ÉÒÔ·ÅÔÚprocess_requestÖУ¬Èç¹ûÑé֤ͨ¹ýÔò¼ÌÐø½»¸øapp´¦Àí£¬·ñÔò·µ»Ø¡°Authentication
required¡±¡£²»¹ý²é¿´novaËùÓÐMddlerwareµÄ±àд£¬Ëƺõ¶¼²»ÓÃÕâÖÖ¶¨ÒåºÃµÄ½á¹¹£¬¶øÊǰѴ¦ÀíÂß¼¶¼·Åµ½__call__ÖУ¬ÕâÑùµ¼ÖÂ__call__±äµÃ¸´ÔÓ£¬´úÂë²»¹»Õû½à¡£¶ÔÓÚFaultWrapperÉпÉÀí½â£¬±Ï¾¹ÐèÒª²¶»ñwsgi
app´¦ÀíÒì³£Âµ«ÆäËüµÄMiddleware¾Í²»Ó¦¸ÃÁË¡£Õâ¿ÉÄÜÊDz»Í¬³ÌÐòԱд£¬¹æ·¶¾ÍºöÂÔÁË¡£
µ±auth_strategy=¡°keystone¡±Ê±£¬openstack_compute_api_v2=FaultWrapper(RequestBodySizeLimiter(auth_token(NovaKeystoneContext(RateLimitingMiddleware(osapi_compute_app_v2)))))¡£ËùÒÔHTTPÇëÇóÐèÒª¾¹ýÎå¸öMiddlewareµÄ´¦Àí£¬²ÅÄܵ½´ïosapi_compute_app_v2¡£ÕâÎå¸öMiddleware·Ö±ðÍê³É£º
1£©Òì³£²¶»ñ£¬·ÀÖ¹·þÎñÄÚ²¿´¦ÀíÒì³£µ¼ÖÂwsgi server¹Òµô£»
2£©ÏÞÖÆHTTPÇëÇóbody´óС£¬¶ÔÓÚÌ«´óµÄbody£¬½«Ö±½Ó·µ»ØBadRequest£»
3£©¶ÔÇëÇókeystone¶ÔheaderÖÐtoken id½øÐÐÑéÖ¤£»
4£©ÀûÓÃheaders³õʼ»¯Ò»¸önova.context.RequestContextʵÀý£¬²¢¸³¸øreq.environ['nova.context']£»
5£©ÏÞÖÆÓû§µÄ·ÃÎÊËÙ¶È¡£
µ±HTTPÇë¾¹ýÉÏÃæÎå¸öMiddlerware´¦Àíºó£¬×îÖÕ½»¸øosapi_compute_app_v2£¬ËüÊÇÔõô¼ÌÐø´¦ÀíÄØ£¿ËüµÄÅäÖÃÈçÏ£º
[app:osapi_compute_app_v2] paste.app_factory = nova.api.openstack.compute:APIRouter.factory |
osapi_compute_app_v2Êǵ÷ÓÃnova.api.openstack.compute.APIRouter.factory()·µ»ØµÄÒ»¸öAPIRouterʵÀý¡£nova.api.openstack.compute.APIRouter¼Ì³Ðnova.api.openstack.APIRouter£¬nova.api.openstack.APIRouterÓּ̳Ðnova.wsgi.APIRouter¡£APIRouterͨ¹ýAËüµÄ³ÉÔ±±äÁ¿mapperÀ´½¨Á¢ºÍά»¤urlÓëcontrollerÖ®¼äµÄÓ³É䣬¸ÃmapperÊÇnova.api.openstack.ProjectMapperµÄʵÀý£¬Ëü¼Ì³Ðnova.api.openstack.APIMapper(routes.Mapper)¡£APIMapper½«Ã¿¸öurlµÄformatÏÞÖÆÎªjson»òxml£¬¶ÔÓÚÆäËüÀ©Õ¹ÃûµÄurl½«·µ»ØNotFound¡£ProjectMapperÔÚÿ¸öÇëÇóurlÇ°Ãæ¼ÓÉÏÒ»¸öproject_id£¬ÕâÑùÿ¸öÇëÇóµÄurl¶¼ÐèÒª´øÉÏÓû§ËùÊôµÄproject
id£¬ËùÒÔÒ»°ãÇëÇóµÄurlΪ/v2/project_id/resources¡£nova.api.openstack.compute.APIRouter.setup_routes´úÂëÈçÏ£º
class APIRouter(nova.api.openstack.APIRouter): ExtensionManager = extensions.ExtensionManager def _setup_routes(self, mapper, ext_mgr): self.resources['servers'] = servers.create_resource(ext_mgr) mapper.resource("server", "servers", controller=self.resources['servers']) self.resources['ips'] = ips.create_resource() mapper.resource("ip", "ips", controller=self.resources['ips'], parent_resource=dict(member_name='server', collection_name='servers')) ...... |
APIRouterͨ¹ýµ÷ÓÃroutes.Mapper.resource()º¯Êý½¨Á¢RESTFUL
API£¬Ò²¿ÉÒÔͨ¹ýroutes.Mapper.connect()À´½¨Á¢urlÓëcontrollerµÄÓ³Éä¡£ÈçÉÏËùʾ£¬serversÏà¹ØÇëÇóµÄcontrollerÉèΪservers.create_resource(ext_mgr)£¬¸Ãº¯Êý·µ»ØµÄÊÇÒ»¸öÓÃnova.api.openstack.compute.servers.Controller()×÷Ϊ³õʼ»¯²ÎÊýµÄnova.api.openstack.wsgi.ResourceʵÀý£¬ipsÏà¹ØÇëÇóµÄcontrollerÉèΪÓÉnova.api.openstack.ips.Controller()³õʼ»¯µÄnova.api.openstack.wsgi.ResourceʵÀý¡£ÒòΪµ÷ÓÃmapper.resource½¨Á¢ipsµÄurlÓ³Éäʱ£¬Ìí¼ÓÁËÒ»¸öparent_resource²ÎÊý£¬Ê¹µÃÇëÇóipsÏà¹ØapiµÄurlÐÎʽΪ/v2/project_id/servers/server_id/ips¡£¶ÔÓÚlimits¡¢flavors¡¢metadataµÈÇëÇóÇé¿öÀàËÆ¡£µ±osapi_compute_app_v2½ÓÊÕµ½HTTPÇëÇóʱ£¬½«µ÷ÓÃnova.wsgi.Router.__call__£¬ËüµÄ¶¨ÒåÈçÏ£º
class Router(object): def __init__(self, mapper): self.map = mapper self._router = routes.middleware.RoutesMiddleware(self._dispatch, self.map) @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): return self._router @staticmethod @webob.dec.wsgify(RequestClass=Request) def _dispatch(req): match = req.environ['wsgiorg.routing_args'][1] if not match: return webob.exc.HTTPNotFound() app = match['controller'] return app |
ÕâÀ↑ʼÈÃÎÒÃÔ»óÁËһϣ¬__call__()ÔõôÄÜ·µ»ØÒ»¸öwsgi appÄØ£¬Ö±½Ó·µ»Øwsgi
appÄÇËüÓÖÔõô±»µ÷ÓÃÄØ£¿²é¿´Ò»ÏÂwsgifyÔ´Â룬·¢ÏÖÈç¹ûº¯Êý·µ»ØµÄÊÇwsgi appʱ£¬Ëü»¹»á±»¼ÌÐøµ÷Ó㬲¢·µ»ØËüµÄ´¦Àí½á¹û¡£ËùÒÔËü»á¼ÌÐøµ÷ÓÃself._router£¬_routerÊÇroutes.middleware.RoutesMiddlewareµÄʵÀý£¬Ê¹ÓÃself._dispatchºÍself.mapÀ´³õʼ»¯µÄ£¬self.mapÊÇÔÚRouterµÄ×ÓÀànova.api.openstack.APIMapper.__init__ÖУ¬±»³õʼ»¯ÎªProjectMapperʵÀý£¬²¢µ÷ÓÃ_setup_routes½¨Á¢ºÃurlÓëcotrollerÖ®¼äµÄÓ³Éä¡£routes.middleware.RoutesMiddleware.__call__µ÷ÓÃmapper.routematchÀ´»ñÈ¡¸ÃurlÓ³ÉäµÄcontrollerµÈ²ÎÊý£¬ÒÔ{"controller":Resource(Controller()),
"action": funcname, "project_id":
uuid, ...}µÄ¸ñʽ·ÅÔÚmatchÖС£²¢ÉèÖÃÈçϵÄenviron±äÁ¿£¬·½±ãºóÃæµ÷ÓõÄself._dispatch·ÃÎÊ¡£×îºóµ÷ÓÃself._dispatch¡£
|