how to read openstack code: Core plugin and resource extension
本章我们将写一个自己的core plugin 和一个resource extension来加深理解。(阅读本文的前提是你已经理解了restful以及stevedore等内容)
什么是 core plugin
neutron的plugin有core和service两种。core plugin实现core resource的增删改查,service plugin我们在本文暂不讨论。
core resource 有network/subnet/port/subnet-pool。每种资源对应CURD和index5种操作。以network资源为例,相关操作和HTTP请求的对应关系如下
create_network POST networks
delete_network DELETE networks/network_id
update_network PUT networks/network_id
get_network GET networks/network_id
get_networks GET networks
因此,core plugin中对各种核心资源都有如下的函数对应:
create_{resource_name}
update_{resource_name}
delete_{resource_name}
get_{resource_name}
get_{resource_names}
how to write core plugin
既然是plugin,也就是我们前面说过的third-party code,那就应该定义一些接口,好让第三方的组织可以参与开发。
neutron中定义的接口在neutron.neutron_plugin_base_v2.NeutronPluginBaseV2。要实现一个core plugin,你需要实现这个class。
下面是我写的一个core plugin 代码
from neutron import neutron_plugin_base_v2
from oslo_log import log
LOG = log.getLogger(__name__)
class MyNeutronPlugin(neutron_plugin_base_v2.NeutronPluginBaseV2):
supported_extension_aliases = ['gold']
def __init__(self):
super(MyNeutronPlugin,self).__init__()
#### network ####
def create_network(self, context, network):
LOG.info("network is %s" %network)
return network
def update_network(self, context, id, network):
return network
def get_network(self, context, id, fields=None):
network = {}
return network
def get_networks(self, context, filters=None, fields=None):
network = {}
LOG.info("return network %s" %network)
return network
def delete_network(self, context, id):
return id
...
#### gold ####
def create_gold(self, context, gold):
LOG.info("gold is %s" %gold)
return gold
def update_gold(self, context, id, gold):
return gold
def get_gold(self, context, id, fields=None):
gold = {}
return gold
def get_golds(self, context, filters=None, fields=None):
gold = {}
LOG.info("return gold %s" %gold)
return gold
def delete_gold(self, context, id):
return id
请注意,除了network等核心资源,我们还实现了一个gold资源。 上面粘贴的内容省略了subnet/port/subnet-pool的相关代码。 既然是thirty-party code,就应该可以独立安装。所以我们的代码结构如下:
myPlugin/
├── myPluginPKG
│ ├── __init__.py
│ └── myPluginModule.py
└── setup.py
init.py的内容为
import myPluginModule
setup.py内容如下:
from setuptools import setup, find_packages
setup(
name='myPluginPKG',
version='1.0',
packages=find_packages(),
entry_points={
'neutron.core_plugins': [
'myNeutronPlugin = myPluginPKG.myPluginModule:MyNeutronPlugin',
],
},
)
这样在运行python setup.py install 后,我们的plugin就注册到了neutron.core_plugins这个namespace下。这部分内容其实就是前面stevedore中driver开发的内容。neutron通过stevedore在这个namespace下加载core_plugin
OK。在python setup.py install 后,我们的core plugin安装完成了,这时要修改/etc/neutron/neutron.conf,让neutron使用我们的core plugin。
[default]
core_plugin = myNeutronPlugin
然后重启neutron服务
systemctl restart neutron-server
接下来你就可以通过API 尝试了, 我们创建一个network 如下:
curl -g -i -X POST "http://liberty-controller01:9696/v2.0/networks" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token:$token" -d '{"network": {"name": "n2", "admin_state_up": true}}'
HTTP/1.1 201 Created
Content-Type: application/json; charset=UTF-8
Content-Length: 15
X-Openstack-Request-Id: req-a8cfde05-6425-42fe-b516-0bb2d264cf61
Date: Tue, 07 Feb 2017 08:01:47 GMT
{"network": {}}
可以看到成功返回,因为我们的plugin中什么也没做,所以返回的其实是一个空的字典。但至少证明该api成功了。
之前我们还在plugin中增加了gold资源对应的函数,我们试试访问gold资源:
curl -g -i "http://liberty-controller01:9696/v2.0/golds" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token:$token"
HTTP/1.1 404 NOT FOUND
为什么gold资源的API不好使呢。这是因为要想在neutron core plugin中定义一个资源,不仅要提供该资源的CURD 函数,还要有对应的RESOURCE_ATTRIBUTE_MAP.
RESOURCE_ATTRIBUTE_MAP
RESOURCE_ATTRIBUTE_MAP是neutron/api/v2/attribute.py中的一个字典,其结构大概如下:
RESOURCE_ATTRIBUTE_MAP = {
NETWORKS: {
'id': {'allow_post': False, 'allow_put': False,
'validate': {'type:uuid': None},
'is_visible': True,
'primary_key': True},
'name': {'allow_post': True, 'allow_put': True,
'validate': {'type:string': NAME_MAX_LEN},
'default': '', 'is_visible': True},
'subnets': {'allow_post': False, 'allow_put': False,
'default': [],
'is_visible': True},
'admin_state_up': {'allow_post': True, 'allow_put': True,
'default': True,
'convert_to': convert_to_boolean,
'is_visible': True},
'status': {'allow_post': False, 'allow_put': False,
'is_visible': True},
'tenant_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:string': TENANT_ID_MAX_LEN},
'required_by_policy': True,
'is_visible': True},
SHARED: {'allow_post': True,
'allow_put': True,
'default': False,
'convert_to': convert_to_boolean,
'is_visible': True,
'required_by_policy': True,
'enforce_policy': True},
},
该字典定义了资源以及资源对应的属性,我们这里只列出了network。所以,要想定义gold资源,除了在core plugin中添加对应的函数,还有在这个attribute map中添加相关的信息。不过,我们不建议直接修改这里的代码,正确的方法是通过resource extension来实现。
how to code an extension (resource extension)
之前提到了extension有3种类型,resource,action,request。我们这里要实现一个新的资源,就是用resource extension。无论是哪种extension 都要遵守一些特定的规则,或者说接口,这些规则如下:
1. extension应该放在neutron/extensions文件夹下,或者在配置文件中设置api_extensions_path
2. extension的class名应该和文件同名,当然首字母应该大写
3. 应该实现neutron.api.extensions.py中ExtensionDescriptor定义的接口
4. 在对应的plugin的supported_extension_aliases 中增加我们extension的别名。前面我们写的core plugin就有这个属性,当时没有做说明,其实是这里应该添加的。所谓别名是该extension要实现的一个接口,后面会看到。
另外很重要的一点是,因为我们要实现的是resource extension,所以还要实现
get_resources
这个接口。
下面我们实现一个自己的resource extension来增加 gold 资源。
from neutron.api import extensions
from neutron import manager
from neutron.api.v2 import base
# You have to specify the attributes neutron-server should expect when
# someone invokes this plugin. Let's say you want
# 'name', 'priority', 'credential' for your extension /golds
# then following dictionary must be declared.
# I am following the naming convention used by other extensions.
RESOURCE_ATTRIBUTE_MAP = {
'golds': {
'name': {'allow_post': True, 'allow_put': True,
'is_visible': True},
'priority': {'allow_post': True, 'allow_put': True,
'is_visible': True},
'credential': {'allow_post': True, 'allow_put': True,
'is_visible': True},
# tenant_id is the user id used by keystone for authorisation
# It's good to use the following as it is and it is necessary
# for every extension
'tenant_id': {'allow_post': True, 'allow_put': False,
'required_by_policy': True,
'validate': {'type:string': None},
'is_visible': True}
}
}
# Great! Now you have the defined the attributes that you need for your
# extensions. You need to store this dictionary in the neutron-server
# by the following class
class Golds(extensions.ExtensionDescriptor):
# The name of this class should be the same as the file name
# There are a couple of methods and their properties defined in the
# parent class of this class, ExtensionDescriptor you can check them
@classmethod
def get_name(cls):
# You can coin a name for this extension
return "Name of golds"
@classmethod
def get_alias(cls):
# This alias will be used by your core_plugin class to load
# the extension
return "gold"
@classmethod
def get_description(cls):
# A small description about this extension
return "A quick brown fox jumped over a lazy dog"
@classmethod
def get_namespace(cls):
# The XML namespace for this extension
# but as we move on to use JSON over XML based request
# this is not that important, correct me if I am wrong.
return "namespace of xml"
@classmethod
def get_updated(cls):
# Specify when was this extension last updated,
# good for management when there are changes in the design
return "2017-02-07T10:00:00-00:00"
@classmethod
def get_resources(cls):
# This method registers the URL and the dictionary of
# attributes on the neutron-server.
exts = list()
plugin = manager.NeutronManager.get_plugin()
resource_name = 'gold'
collection_name = resource_name + 's'
params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + 's', dict())
controller = base.create_resource(collection_name, resource_name,
plugin, params, allow_bulk=False)
ex = extensions.ResourceExtension(collection_name, controller)
exts.append(ex)
return exts
代码的大部分解释都包含在注释里,因此请详细阅读每一行。这里只重点说一下RESOURCE_ATTRIBUTE_MAP 和 get_resources。 我们的extension就是通过这个函数来在resource attribute map中增加了gold资源。
另外要注意的是get_alias,该函数返回extension的别名,plugin的supported_extension_alias中用该别名来找extension。
ok,我们现在尝试一下访问gold 资源
curl -g -i http://liberty-controller01:9696/v2.0/golds.json -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token:$token"
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 13
X-Openstack-Request-Id: req-7b925f97-4df0-49ee-bb6a-fd7c86fda9aa
Date: Tue, 07 Feb 2017 08:29:34 GMT
{"golds": []}
这次成功了。 以上就是core plugin和resource extension
how to read openstack code: Core plugin and resource extension的更多相关文章
- how to read openstack code: service plugin
We have learned core plugin, service plugin and extension in last post. Now let`s review: Core Plugi ...
- how to read openstack code
本文的目的不是介绍openstack.我们这里假设你已经知道了openstack是什么,能够做什么.所以目的是介绍如何阅读openstack的代码.通过读代码来进一步学习openstack. 转载要求 ...
- how to read openstack code: action extension
之前我们看过了core plugin, service plugin 还有resource extension. resource extension的作用是定义新的资源.而我们说过还有两种exten ...
- 详解 ML2 Core Plugin(II) - 每天5分钟玩转 OpenStack(72)
上一节我们讨论了 ML2 Plugin 解决的问题,本节将继续研究 ML2 的架构. ML2 对二层网络进行抽象和建模,引入了 type driver 和 mechansim driver. 这两类 ...
- 详解 ML2 Core Plugin(I) - 每天5分钟玩转 OpenStack(71)
我们在 Neutron Server 小节学习到 Core Plugin,其功能是维护数据库中 network, subnet 和 port 的状态,并负责调用相应的 agent 在 network ...
- 怎样写 OpenStack Neutron 的 Plugin (一)
鉴于不知道Neutron的人也不会看这篇文章,而知道的人也不用我再啰嗦Neutron是什么东西,我决定跳过Neutron简介,直接爆料. 首先要介绍一下我的开发环境.我没有使用DevStack,而是直 ...
- Neutron:ML2 Core Plugin
两个 Core Plugin:linux bridge plugin 和 open vswitch plugin. Moduler Layer 2(ML2)是 Neutron 在 Havana 版 ...
- how to read openstack code: loading process
之前我们了解了neutron的结构,plugin 和 extension等信息.这一章我们看一下neutron如何加载这些plugin和extension.也就是neutron的启动过程.本文涉及的代 ...
- how to read openstack code: Neutron architecture
今天这一章节非常重要.我们知道neutron是一个非常复杂的系统,由很多组件构成.研究这样一个复杂的系统,正确的顺序应该是现在宏观上对其整体结构有所了解,然后再由针对性的对其组件进行深入了解.本章要做 ...
随机推荐
- linux下C的建立、编译和运行 gcc (附上Windows下visual c++的用法)
2019/6/24 1. 环境:window10下安装了MobaXterm,这里申请了阿里云的服务账号,可以直接使用linux系统,避免安装虚拟机等. 2. 判断linux下是否有GCC编译工具(我们 ...
- Python3简明教程(十)—— 异常
在本节我们学习 Python 的异常以及如何在你的代码中处理它们. 异常 在程序执行过程中发生的任何错误都是异常.每个异常显示一些相关的错误信息,比如你在 Python3 中使用 Python2 独有 ...
- 在.vue文件中让html代码自动补全的方法(支持vscode)
在.vue文件中让html代码自动补全的方法(支持vscode) https://blog.csdn.net/qq_36529459/article/details/79196763 "fi ...
- ideal取消按下两次shift弹出搜索框 修改idea,webstrom,phpstrom 快捷键double shift 弹出search everywhere
因为经常需要在中英文之间切换,所以时常使用shift键,一不小心就把这个Searchwhere 对话框调出来了,很是麻烦. 因此痛定思痛, 我决定将这个按两下shift键就弹出搜索框的快捷键禁用了! ...
- Archive for required library: 'D:/Program Files/Apache/maven-repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar'
今天导入一个项目工程,发现报错:Archive for required library: 'D:/Program Files/Apache/maven-repository/dom4j/dom4j/ ...
- python3 yum not found
vi /urs/bin/yum 将#!/usr/bin/python的python改为python2.x(你系统的python2的版本)
- 《编译原理》画 DAG 图与求优化后的 4 元式代码- 例题解析
<编译原理>画 DAG 图与求优化后的 4 元式代码- 例题解析 DAG 图(Directed Acylic Graph)无环路有向图 (一)基本块 基本块是指程序中一顺序执行的语句序列, ...
- java list去重操作实现方式
Java中的List是可以包含重复元素的(hash code 和equals),接下来将介绍两种方式实现java list去重操作,感兴趣的朋友可以参考下 Java中的List是可以包含重复元素的 ...
- js 调用flash在chrome报错
1.网页内嵌动态生成的flash出错,出错信息如下: #25081850 myChartId::RendererManager Error >> There was an error re ...
- [LUOGU] P2920 [USACO08NOV]时间管理Time Management
见7.3测试 #include<iostream> #include<algorithm> #include<cstdio> using namespace std ...