目录

前言

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)

Openstack-L 路由注入方式的更多相关文章

  1. Spring IOC 注入方式详解 附代码

    引言 Spring框架作为优秀的开源框架之一,深受各大Java开发者的追捧,相信对于大家来说并不陌生,Spring之所以这么流行,少不了他的两大核心技术IOC和IOP.我们这里重点讲述Spring框架 ...

  2. ASP.NET Core应用的7种依赖注入方式

    ASP.NET Core框架中的很多核心对象都是通过依赖注入方式提供的,如用来对应用进行初始化的Startup对象.中间件对象,以及ASP.NET Core MVC应用中的Controller对象和V ...

  3. spring四种依赖注入方式

    一.Set注入 这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringD ...

  4. Spring的三种通过XML实现DataSource注入方式

    Spring的三种通过XML实现DataSource注入方式: 1.使用Spring自带的DriverManagerDataSource 2.使用DBCP连接池 3.使用Tomcat提供的JNDI

  5. spring笔记--依赖注入之针对不同类型变量的几种注入方式

    控制反转和依赖注入讲的都是一个概念,只不过是站在了不同的角度,所谓的依赖注入: 是指在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bea ...

  6. 控制反转IOC的依赖注入方式

    引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...

  7. spring ioc三种注入方式

    spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容 ...

  8. spring 学习之 bean 的注入方式 property和constructor-arg的使用方式

    spring 学习之 bean 的注入方式 property和constructor-arg的使用方式. bean的注入方式: property 注入是: 通过setxx方法注入. construct ...

  9. Spring IOC 注入方式

    依赖注入通常有如下两种方式: ①设值注入:IOC容器使用属性的Setter方法来注入被依赖的实例. 设值注入是指IOC容器使用属性的Setter方法来注入被依赖的实例.这种注入方式简单.直观,因而在S ...

随机推荐

  1. Read Committed

    在Read Committed隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题. 不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一 ...

  2. thinkphp rpc

    RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议的存在 ...

  3. HZOI2019SF

    Simulation Final 坑.下午我要爆零(RP++) upd: 哈哈哈哈哈哈哈哈哈哈我真的爆零了哈哈哈哈哈哈哈哈哈哈 关于细节, T1A了但是和T3交反了哈哈哈哈哈哈哈哈哈哈 我说我真的不是 ...

  4. 【LeetCode 27】移除元素

    题目链接 [题解] 沙比提 [代码] class Solution { public: int removeElement(vector<int>& nums, int val) ...

  5. Robotframework之下拉列表select

    下拉框控件很常见啊,主要说一下robotframework中怎么玩转下拉框,第一点要注意的就是,别看到下拉的就用select控件去操作,因为很多下拉列表用的不一定就是select控件.robotfra ...

  6. maven surefire入门

    一.maven常用命令: mvn compile mvn install mvn test mvn clean mvn dependency:resolve -X   #查看完整的debug信息!!! ...

  7. 【Java多线程系列二】Thread类的方法

    Thread实现Runnable接口并实现了大量实用的方法. /* * 此方法释放CPU,但并不释放已获得的锁,其它就绪的线程将可能得到执行机会,它自己也有可能再次得到执行机会 */ public s ...

  8. 前端(八)—— 高级布局:文档流、浮动布局、流式布局、定位布局、flex布局、响应布局

    高级布局:文档流.浮动布局.流式布局.定位布局.flex布局.响应布局 一.文档流 1.什么是文档流 将窗体自上而下分成一行一行,块级元素从上至下.行内元素在每行中从左至右的顺序依次排放元素 2.本质 ...

  9. 人人开源打包jar

    先在renren-security执行mvn clean install 再到renren-admin目录下,执行mvn clean package,就可以打成renren-admin.jar 如果想 ...

  10. Dubbo面试20问!这些题你都遇到过吗?

    作者:Dean Wang https://deanwang1943.github.io/bugs/2018/10/05/面试/饿了么/dubbo 面试题/ 1.dubbo是什么 dubbo是一个分布式 ...