Openstack-L 路由注入方式-阿里云开发者社区

开发者社区> 开发与运维> 正文

Openstack-L 路由注入方式

简介: 目录 目录 前言 从 Commands 到 Action 操作函数 前言 Openstack 新旧版本提供了不同的路由注入方式,也就是 Route Module 的代码方式不同,就二次开发而言用那一种实现方式都是可以得。

目录

前言

Openstack 新旧版本提供了不同的路由注入方式,也就是 Route Module 的代码方式不同,就二次开发而言用那一种实现方式都是可以得。但 Openstack 现在更加倾向于使用本篇这一种方式(以 Extension 动态加载),能够通过修改 nova/setup.cfg 的代码来实现修改 URL 跟具体的 Application 的 Mapping 。而不需要跟以往一般,还需要手动的实现路由注入代码。

从 Commands 到 Action 操作函数

EXAMPLEnova --debug hypervisor-state

# Request:
DEBUG (session:198) REQ: curl -g -i -X GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/os-hypervisors/statistics -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-OpenStack-Nova-API-Version: 2.6" -H "X-Auth-Token: {SHA1}73a00cca5407858b33532ae9686ff5ed5f7448b3"
DEBUG (connectionpool:387) "GET /v2.1/6c4e4d58cb9d4451b36e774b348e8813/os-hypervisors/statistics HTTP/1.1" 200 260

# Response:
DEBUG (session:216) RESP: [200] Content-Length: 260 X-Compute-Request-Id: req-a7e8a156-49ef-4217-9679-af38d78ddfb9 Vary: X-OpenStack-Nova-API-Version Connection: keep-alive X-Openstack-Nova-Api-Version: 2.6 Date: Wed, 10 Aug 2016 11:24:23 GMT Content-Type: application/json 
RESP BODY: {"hypervisor_statistics": {"count": 1, "vcpus_used": 0, "local_gb_used": 0, "memory_mb": 44458, "current_workload": 0, "vcpus": 12, "running_vms": 0, "free_disk_gb": 458, "disk_available_least": 0, "local_gb": 458, "free_ram_mb": 43946, "memory_mb_used": 512}}

+----------------------+-------+
| Property             | Value |
+----------------------+-------+
| count                | 1     |
| current_workload     | 0     |
| disk_available_least | 0     |
| free_disk_gb         | 458   |
| free_ram_mb          | 43946 |
| local_gb             | 458   |
| local_gb_used        | 0     |
| memory_mb            | 44458 |
| memory_mb_used       | 512   |
| running_vms          | 0     |
| vcpus                | 12    |
| vcpus_used           | 0     |
+----------------------+-------+

从 DEBUG 可以得到实际的 HTTP Request 为:

GET http://200.21.18.2:8774/v2.1/6c4e4d58cb9d4451b36e774b348e8813/os-hypervisors/statistics

下面介绍该 HTTP Request 如何路由到具体的 Action 操作函数。

Step 1. nova/api-paste.ini 将 HTTP Request 分发到对应的 Application

# /opt/stack/nova/etc/nova/api-paste.ini

60  [composite:osapi_compute]                              
  1 use = call:nova.api.openstack.urlmap:urlmap_factory
  2 /: oscomputeversions
  3 # starting in Liberty the v21 implementation replaces the v2
  4 # implementation and is suggested that you use it as the default. If
  5 # this causes issues with your clients you can rollback to the
  6 # *frozen* v2 api by commenting out the above stanza and using the
  7 # following instead::
  8 # /v1.1: openstack_compute_api_legacy_v2
  9 # /v2: openstack_compute_api_legacy_v2
 10 # if rolling back to v2 fixes your issue please file a critical bug
 11 # at - https://bugs.launchpad.net/nova/+bugs
 12 # 
 13 # v21 is an exactly feature match for v2, except it has more stringent
 14 # input validation on the wsgi surface (prevents fuzzing early on the
 15 # API). It also provides new features via API microversions which are
 16 # opt into for clients. Unaware clients will receive the same frozen
 17 # v2 API feature set, but with some relaxed validation
 18 /v1.1: openstack_compute_api_v21_legacy_v2_compatible
 19 /v2: openstack_compute_api_v21_legacy_v2_compatible
 20 /v2.1: openstack_compute_api_v21


89 [composite:openstack_compute_api_v21]     
  1 use = call:nova.api.auth:pipeline_factory_v21
  2 noauth2 = compute_req_id faultwrap sizelimit noauth2 osapi_compute_app_v21
  3 keystone = compute_req_id faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v21

# 从子路径 http://200.21.18.2:8774/v2.1 我们可以定位到的 Application 为 nova.api.openstack.compute:APIRouterV21.factory
123 [app:osapi_compute_app_v21]                             
  1 paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory 

剩下在子路径 /os-hypervisors/statistics 交由 Route Module 处理,首先在服务启动时,需要加载 setup.cfg 配置和路由注入 。

Step 2. Application 的代码实现节选

# /opt/stack/nova/nova/api/openstack/compute/__init__.py

150 class APIRouterV21(nova.api.openstack.APIRouterV21):
  1     """Routes requests on the OpenStack API to the appropriate controller
  2     and method. 
  3     """         
  4     def __init__(self, init_only=None):
  5         self._loaded_extension_info = extension_info.LoadedExtensionInfo()
  6         super(APIRouterV21, self).__init__(init_only)
  7                 
  8     def _register_extension(self, ext):
  9         return self.loaded_extension_info.register_extension(ext.obj)
 10                 
 11     @property   
 12     def loaded_extension_info(self):
 13         return self._loaded_extension_info

# 在 APIRouterV21 这个类中没有定义路由,继续查看父类


# 跳转
# /opt/stack/nova/nova/api/openstack/__init__.py

303 class APIRouterV21(base_wsgi.Router):
  1     """Routes requests on the OpenStack v2.1 API to the appropriate controller
  2     and method. 
  3     """         


313     @staticmethod                         
  1     def api_extension_namespace():
  2         return 'nova.api.v21.extensions'


317     def __init__(self, init_only=None, v3mode=False):


            # 加载 setup.cfg 中的 Extensions 来实现路由的注入
364         self.api_extension_manager = stevedore.enabled.EnabledExtensionManager(                             
  1             namespace=self.api_extension_namespace(),
  2             check_func=_check_load_extension,
  3             invoke_on_load=True,      
  4             invoke_kwds={"extension_info": self.loaded_extension_info})

Step 3. 在 setup.cfg 中定义 Extensions 的映射

# /opt/stack/nova/setup.cfg
72  nova.api.v21.extensions =  
    ...
112     hypervisors = nova.api.openstack.compute.hypervisors:Hypervisors

Step 4. 从 setup.cfg 的映射中加载 Resource 的 Controller ,等待接收 HTTP Request 的子路径
EG. /os-hypervisors/statistics

# /opt/stack/nova/nova/api/openstack/compute/hypervisors.py

22 from nova import compute

    # 这个别名对应了 URL 中的子路径 /os-hypervisors
29  ALIAS = "os-hypervisors"

    # 一个 Resource 对应一个 Controller ,Controller 是 Resource 的 Action 操作函数集合
33  class HypervisorsController(wsgi.Controller):

36      def __init__(self):  
  1         self.host_api = compute.HostAPI()

        # 这个方法对应了 URL 最后一个子路径 /statistics
177     def statistics(self, req): 
  1         context = req.environ['nova.context']  # 环境变量
  2         authorize(context)        # Token 认证
  3         stats = self.host_api.compute_node_statistics(context)   # 调用了 nova.compute:HostAPI 中的函数
  4         return dict(hypervisor_statistics=stats)


184 class Hypervisors(extensions.V21APIExtensionBase): 
  1     """Admin-only hypervisor administration."""
  2              
  3     name = "Hypervisors"
  4     alias = ALIAS
  5     version = 1
  6              
  7     def get_resources(self):
  8         resources = [extensions.ResourceExtension(ALIAS,
  9                 HypervisorsController(),           # Controller 类
 10                 collection_actions={'detail': 'GET',
 11                                     'statistics': 'GET'},
 12                 member_actions={'uptime': 'GET',
 13                                 'search': 'GET',
 14                                 'servers': 'GET'})]
 15         # 将 HTTP 的内置方法绑定到指定 Action

 16         return resources
 17              
 18     def get_controller_extensions(self):
 19         return []

Step 5. HTTP Request 中子路径 /statistics 对应的具体操作函数实现

/opt/stack/nova/nova/compute/__init__.py
17  from oslo_utils import importutils

42  def HostAPI(*args, **kwargs):
  1     """Returns the 'HostAPI' class from the same module as the configured
  2     compute api
  3     """
  4     compute_api_class_name = _get_compute_api_class_name()
  5     compute_api_class = importutils.import_class(compute_api_class_name)
  6     class_name = compute_api_class.__module__ + ".HostAPI"
  7     return importutils.import_object(class_name, *args, **kwargs)

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章