from nova to ironic(4)

来源:互联网 发布:交管12123一直网络失败 编辑:程序博客网 时间:2024/06/09 21:30

前面nova启动wsgi服务之时,load paste-api.ini文件,rest的入口(以v2为例)在nova.api.openstack.compute.__init__.APIRouter中,

继承自:nova.api.openstack.APIRouter,在子类中ExtensionManager = extensions.ExtensionManager,

ext_opts = [
    cfg.MultiStrOpt('osapi_compute_extension',
                    default=[
                      'nova.api.openstack.compute.contrib.standard_extensions'
                      ],
                    help='osapi compute extension to load'),
]

在extensions.ExtensionManager中self._load_extensions(), extensions为list [ 'nova.api.openstack.compute.contrib.standard_extensions'],_load_extensions(),调用

load_extensions(),最后一句“factory(self)”, self是一个ExtensionManager, 也就是执行standard_extensions时的ext_mgr。

调用standard_extensions方法,将nova.api.openstack.compute.contrib目录下.py文件,对和文件名相同的class(首字母大写),比如cells.py对应类Cells,执行

ext_mgr.load_extension(classpath),调用ExtensionManager将类load进来,而每个contrib下的类,比如Cells都继承自extensions.ExtensionDescriptor,在__init__中

执行“ ext_mgr.register(self)”, 在register时会将alias和类关系对应起来放在“self.extensions[alias] = ext(此处为ExtensionDescriptor,即各个扩展类)”中。


接下来看nova中rest 和 controller是如何对应起来的,在nova.api.openstack.APIRouter中

 self._setup_routes(mapper, ext_mgr, init_only)

self.resources['servers'] = servers.create_resource(ext_mgr)
            mapper.resource("server", "servers",
                            controller=self.resources['servers'],
                            collection={'detail': 'GET'},
                            member={'action': 'POST'})

以server为例,mapper为ProjectMapper,继承自APIMapper,再向上继承自routes.Mapper, ProjectMapper重载了resources方法,并在方法最后调用了

routes.Mapper.resource(self, member_name,  collection_name, **kwargs), trace into routes.Mapper.resource,在注释中详细的解释了参数和url的对应关系:

map.resource('message', 'messages', collection={'rss':'GET'}) # GET /message/rss (maps to the rss action)

map.resource('message', 'messages', member={'mark':'POST'})# POST /message/1/mark (maps to the mark action)

map.resource('message', 'messages', new={'preview':'POST'}) # POST /message/new/preview (maps to the preview action)

map.resource('message', 'messages', controller='categories',  path_prefix='/category/:category_id',  name_prefix="category_") # GET /category/7/message/1

Example::
 
                >>> from routes.util import url_for
                >>> m = Mapper()
                >>> m.resource('location', 'locations',
                ...            parent_resource=dict(member_name='region',
                ...                                 collection_name='regions'))
                >>> # path_prefix is "regions/:region_id"
                >>> # name prefix is "region_"  
                >>> url_for('region_locations', region_id=13)
                '/regions/13/locations'
                >>> url_for('region_new_location', region_id=13)
                '/regions/13/locations/new'
                >>> url_for('region_location', region_id=13, id=60)
                '/regions/13/locations/60'
                >>> url_for('region_edit_location', region_id=13, id=60)
                '/regions/13/locations/60/edit'

            Overriding generated ``path_prefix``::

                >>> m = Mapper()
                >>> m.resource('location', 'locations',
                ...            parent_resource=dict(member_name='region',
                ...                                 collection_name='regions'),
                ...            path_prefix='areas/:area_id')
                >>> # name prefix is "region_"
                >>> url_for('region_locations', area_id=51)
                '/areas/51/locations'

            Overriding generated ``name_prefix``::

                >>> m = Mapper()
                >>> m.resource('location', 'locations',
                ...            parent_resource=dict(member_name='region',
                ...                                 collection_name='regions'),
                ...            name_prefix='')
                >>> # path_prefix is "regions/:region_id"
                >>> url_for('locations', region_id=51)
                '/regions/51/locations'


 self._setup_ext_routes(mapper, ext_mgr, init_only)#根据各个extension实现的get_resources()方法,得到各个extensions的路由
 self._setup_extensions(ext_mgr)#有的extension为对现有controller的补充,比如console是对server的补充,则会选择实现get_controller_extensions()方法

总得来说nova里面的routes是openstack里面最复杂的,用法很灵活,自己要扩展时应该根据自己extension的内容合理的选择实现方式。

而在基类Router中:

 self.map = mapper
self._router = routes.middleware.RoutesMiddleware(self._dispatch,self.map)

trace into RoutesMiddleware类,

results = self.mapper.routematch(environ=environ)
            if results:
                match, route = results[0], results[1]#{"controller":Resource(Controller()), "action": funcname, "project_id": uuid, ...}的格式放在match中
            else:
                match = route = None

 url = URLGenerator(self.mapper, environ)#根据Mapper和environ得到url
  environ['wsgiorg.routing_args'] = ((url), match)
  environ['routes.route'] = route
  environ['routes.url'] = url

response = self.app(environ, start_response)#此处app为Router中的_dispatch方法,根据wsgiorg.routing_args得到Resource(Controller()), 然后根据Resource中的

__call__方法,调用get_method等找到对应的方法(可以在Resource中再追一下)


http://www.it165.net/pro/html/201407/17020.html这时一篇不错的文章,mark一下

http://www.choudan.net/2013/12/09/OpenStack-WSGI-APP%E5%AD%A6%E4%B9%A0.html 由openstack讲WSGI app的,也很好,mark


0 0
原创粉丝点击