Jiang Jun bio photo

Jiang Jun

Playing TensorFlow with Kubernetes

Twitter Google+ LinkedIn Instagram Github Weibo

Nova API

tags: OpenStack Nova

http://docs.openstack.org/developer/nova/devref/addmethod.openstackapi.html
https://www.ibm.com/developerworks/community/blogs/e93514d3-c4f0-4aa0-8844-497f370090f5/entry/openstack_nova_api?lang=en

nova.wsgi.Server 为每一个 Nova API worker 进程提供一个封装的 web server。它封装并管理一个 eventlet 优化过(greened) 的 WSGI server,它运行在一个自己管理的 green thread pool(这个线程池的大小可配)和一个给定的 socket (port、最大队列连接数可配)上。

详见前面的文章 了解 WSGIService nova-api 如何起来

nova.api.openstack.compute.APIRouter 用来允许将多个 WSGI applications 绑定到一个单独的 WSGI server 上,这也是为什么每个核心的 API 和插件(extension)资源都是一个个独立的 WSGI application。

它继承自 nova.api.openstack.APIRouter,这个父类会在初始化的时候寻找 ExtensionManager、用 nova.api.openstack.__init__ 里的 ProjectMapper 类 创建 mapper( mapper.resource(member_name, collection_name, ...) 它将用于把属于一个 collection 的请求都映射到一个 controller 上), 并依次 _setup_routes_setup_ext_routes_setup_extensions,其中的 _setup_routes 这一关键方法必须由子类来实现, 这里定义了详细的基本 route 策略:mapper 中的每一个 route 必须指定一个 WSGI app 作为它的 controller。 最后,用它父类 base_wsgi.Router (nova/wsgi.py) 里的 __init__ 方法,将刚刚生成的 mapper 传进去。

nova.wsgi.Routernova.api.openstack.compute.APIRouter 的父类,在内部用 routes.middleware.RoutesMiddleware 来把那些进来的请求映射到那些 WSGI applications。

nova/api/openstack/wsgi.py 中还有很多 wsgi 通讯时的实现,比如:

  • 对 Request 的简单封装,加入一些简单的 cache;
  • 定义了一些解析、生成 body 的类:TextDeserializerDictSerializer
  • 定义了一些添加 (De)serializer 的装饰器;
  • 什么是一个 action 的装饰器 @action;
  • 继承某个 action 的装饰器 @extends(xxx);ResponseObject。。。

Resource 类

它自己是一个 WSGI app,管理着 (de)serialization 和 controller 的分发。 读取由 RoutesMiddleware 提供的 routing 信息,根据它的 controller 调用请求的 action。 所有的 controller 的 action 方法都必须接受一个叫 'req' 的参数,内容是进来的 wsgi.Request 请求。 如果这个操作是 PUT 或是 POST,那么 controller 的方法就必须接受一个 'body' 参数(内容为请求的 body)。 这些方法最后要么报一个 webob.exc 异常,要么返回一个 dict,这个字典将被按照要求的 content type 序列化。请细看 _process_stack(xxx) 这个方法。

Controller 类

默认的 Controller 类。

(这里待完善)

调用过程

> /opt/stack/nova/nova/api/openstack/wsgi.py(890)__call__()
    889         return self._process_stack(request, action, action_args,
--> 890                                content_type, body, accept)
    891

> /opt/stack/nova/nova/api/openstack/wsgi.py(942)_process_stack()
    941                 with ResourceExceptionHandler():
--> 942                     action_result = self.dispatch(meth, request, action_args)
    943             except Fault as ex:

> /opt/stack/nova/nova/api/openstack/wsgi.py(1022)dispatch()
   1021
-> 1022         return method(req=request, **action_args)
   1023

> /opt/stack/nova/nova/api/openstack/compute/servers.py(480)detail()
    479         try:
--> 480             servers = self._get_servers(req, is_detail=True)
    481         except exception.Invalid as err:

> /opt/stack/nova/nova/api/openstack/compute/servers.py(564)_get_servers()
    563             self._add_instance_faults(context, instance_list)
--> 564             response = self._view_builder.detail(req, instance_list)
    565         else:

> /opt/stack/nova/nova/api/openstack/compute/views/servers.py(135)detail()
    134         """Detailed view of a list of instance."""
--> 135         return self._list_view(self.show, request, instances)
    136

> /opt/stack/nova/nova/api/openstack/compute/views/servers.py(139)_list_view()
    138         """Provide a view for a list of servers."""
--> 139         server_list = [func(request, server)["server"] for server in servers]
    140         servers_links = self._get_collection_links(request,

> nova/api/openstack/compute/views/servers.py (90)show()
def show(self, request, instance):
    ...

comments powered by Disqus