首页 首页 云计算 查看内容

Neutron集成ONOS源码分析

木马童年 2018-8-10 20:55 10 0

OpenStack Neutron集成ONOS的项目,名为“networking-onos”。目前,在Neutron项目中现已开始从源码中移除诸如SDN Plugin这些项目的代码,使之成为独立的项目,其Release的代码托管在Github上。 截止目前,ONOS已经 ...

OpenStack Neutron集成ONOS的项目,名为“networking-onos”。目前,在Neutron项目中现已开始从源码中移除诸如SDN Plugin这些项目的代码,使之成为独立的项目,其Release的代码托管在Github上。

截止目前,ONOS已经在ML2、L3层支持集成Neutron。具体详情,可参考neutron项目代码中的doc/source/stadium/sub_projects.rst文件。

networking-onos项目Github地址:https://github.com/openstack/networking-onos。

networking-onos项目Review地址:https://review.openstack.org/#/q/onos,n,z。

在这里,我将networking-onos安装在了CentOS平台上,源码目录为/usr/lib/python2.7/site-packages/networking_onos。该目录下,主要有common、plugins、tests这三个文件夹。下面我们将以此分别展开分析。

一.networking_onos/common

该目录下主要包括了config.py、utils.py这2个模块,用于定义一些公共的库。

1)common/config.py

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

from oslo_config import cfg

ONOS_DRIVER_OPTS = [

cfg.StrOpt('url_path',

default='',

help=_('ONOS ReST interface URL')),

cfg.StrOpt('username',

default='',

help=_('Username for authentication.')),

cfg.StrOpt('password',

default='',

secret=True,# do not expose value in the logs

help=_('Password for authentication.'))

]

cfg.CONF.register_opts(ONOS_DRIVER_OPTS, "onos")

分析:

该文件中的代码,无外乎是使用openstack的config这个公共库,用于配置文件的管理和命令行的解析;cfg模块的主要作用有两个,一个是对配置文件进行解析,一个是对命令行的参数进行解析。其数据类型有:StrOpt、ListOpt、DictOpt、IntOpt、FloatOpt。

在这里,它用于解析ml2_conf.ini等文件中的内容,具体用于解析列表中的ONOS和Neutron集成的username、password、url_path这三种信息。

最后,一行代码使用oslo.cfg 模块中的cfg.CONF全局变量中的register_opts()方法注册我们需要解析的配置项。

2)common/utils.py

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

def send_msg(onos_path, onos_auth, msg_type, entity_path, entity=None):

"""Send message to the ONOS controller."""

path = '/'.join([onos_path, entity_path])

hdr = {'Content-Type': 'application/json'}

body = jsonutils.dumps(entity, indent=2) if entity else None

LOG.debug("Sending MSG_TYPE (%(msg)s) URL (%(path)s) "

"OBJECT (%(entity)s) BODY (%(body)s)",

{'msg': msg_type, 'path': path,

'entity': entity, 'body': body})

req = requests.request(method=msg_type, url=path,

headers=hdr, data=body,

auth=onos_auth)

# Let's raise voice for an error

req.raise_for_status()

def safe_delete_from_dict(dict, keys):

"""Ignore key errors when deleting from a dictionary."""

for key in keys:

dict.pop(key, None)

分析:

该模块中,主要定义了send_msg和safe_delete_from_dict这2个函数。前者主要用于将onos_path, onos_auth, msg_type, entity_path这些信息发送给onos controller。而后者,则用于当从字典中删除key-value键值时,忽略关键错误。

二.networking_onos/plugins

这里,我们需要注意的是,networking-onos集成neutron的plugin,从架构上分为了ML2、L3这二层。如下图所示:

1)ml2/driver.py

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

from oslo_config import cfg

from oslo_log import helpers as log_helpers

from oslo_log import log as logging

from neutron.common import constants as n_const

from neutron.extensions import portbindings

from neutron.plugins.common import constants

from neutron.plugins.ml2 import driver_api as api

from networking_onos.common import config# noqa

from networking_onos.common import utils as onos_utils

LOG = logging.getLogger(__name__)

class ONOSMechanismDriver(api.MechanismDriver):

…………..

分析:

Networking-onos的ML2 driver,总共分别从oslo公共库、neutron、networking_onos这三个地方,导入了诸如config、log这些模块来处理诸如配置文件、命令行参数、日志管理这些事儿。以及使用neutron和networking_onos库中的extensions、plugins、ml2、config这些模块。

在该模块中,使用了一个继承自api.MechanismDriver父类的ONOSMechanismDriver的类,用于实现Neutron中的ML2 Driver。除此之外,使用了一个@log_helpers.log_method_call装饰器,主要而言,该模块通过扩展core plugin api来实现自己定义的方法或资源操作。

其中定义的方法,主要实现了Neutron ML2中的network、subnet、port这几类核心资源。其功能如下所示:

  • Network

create_network

update_network

delete_network

  • Subnet

create_subnet

update_subnet

delete_subnet

  • Port

create_port

update_port

delete_port

bind_port

最后的,check_segment函数用于检查ONOS MechanismDriver中的segment是否是有效的,其定义的NETWORK_TYPE有:local、gre、vxlan、vlan。

当然,ml2目录下的README文件,也是很有必要一读的。

2)l3/driver.py

Shell

1

2

3

4

5

6

class ONOSL3Plugin(db_base_plugin_v2.NeutronDbPluginV2,

extraroute_db.ExtraRoute_db_mixin,

l3_gwmode_db.L3_NAT_db_mixin,

l3_agentschedulers_db.L3AgentSchedulerDbMixin,

onos_router.ONOSRouter,

onos_fip.ONOSFloatingIP):

该模块中,定义了一个继承自许多父类的名为ONOSL3Plugin的类,用于实现L3层网络服务中的,诸如neutron db、路由器db、NAT db、l3 db等数据模型的操作。

该类的核心是实现L3层的 Router Service Plugin。用于提供router和floatingip资源,以及管理相关的request/response。

无外乎,这里实现了L3层网络服务中的如下一些资源:

  • Router

create_router

update_router

delete_router

  • floatingip

create_floatingip

update_floatingip

delete_floatingip

add_router_interface

remove_router_interface

该模块中,还定义了一个setup_rpc的函数,用于远程过程调用和其他的api、service进行消息通信。我们知道,Neutron中的Router,有网关臂和接口臂两种,网关臂用于设置网关和Public_network关联;而接口臂则用于添加接口,关联租户/用户创建的租户网络(Private_network),对应于模块中的add_router_interface方法。

需要注意的是,router和floating_ip这两类L3资源的代码,均在同级目录下有具体实现。

3)l3/floating_ip.py

该模块,用于实现ONOS的L3 Floating IP Service。其继承自Object基类的ONOSFloatingIP类,用于将包括msg_type、entity_path、entity 在内的Neutron的L3 Floating IP消息发送给ONOS Controller。

4)l3/router.py

该模块实现、原理同上类似,用于实现ONOS L3 Router Service。返回一个包含subnet_id、port_id、router_id、tenant_id在内的router_dict字典数据结构。

5)l3/ README

如果要了解相关的L3实现信息,该文件同样值得一读。

三.networking_onos/tests

该目录下,分别定义的是ML2、L3层的Mock单元测试模块。如下。

1)ml2/ test_driver.py

无疑,该模块中使用了python中的单元测试模块——mock。Mock用于在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便于测试的测试方法。

代码测试只针对指定函数的内部代码。如果测试代码需要依赖于其他的代码片段,在某种不幸的情形下,即使被测试的函数没有变化,这部分内嵌代码的修改仍然可能破坏原有的测试。Mock 方法就是用于把测试与测试边界以外的对象隔离开。

该模块中,fake了ML2网络服务中的如下一些资源:

Network:

network_uuid、network_object

Subnet:

subnet_uuid、subnet_object

Port:

port_uuid、port_object

其中ONOSMechanismDriverTestCase类的set_test_config方法,fake了连接onos controller所必需的一些信息。同时,分别使用网络、子网、端口的delete、update、delete方法,进行单元测试。此外,还定义了验证segment(network_types)、端口绑定这些方法。

2)l3/test_driver.py

L3层的单元测试,同ML2层的单元测试模块在实现和原理上是一样的。首先会fake一些必要的数据,如tenant_id、router_uuid、router_object(即创建router的必要数据)、network_id、floating_ip、port_id等之类的数据。

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

class ONOSL3PluginTestCase(base.BaseTestCase,

test_neutron_extensions.ExtensionTestCase,

onos_driver.ONOSL3Plugin):

def setUp(self):

super(ONOSL3PluginTestCase, self).setUp()

self._setUpExtension(

'neutron.extensions.l3.RouterPluginBase', None,

l3.RESOURCE_ATTRIBUTE_MAP, l3.L3, None,

allow_pagination=True, allow_sorting=True,

supported_extension_aliases=['router'],

use_quota=True)

self.instance = self.plugin.return_value

在继承自BaseTestCase、ExtensionTestCase和ONOSL3Plugin这三个父类的ONOSL3PluginTestCase类中,_test_send_msg方法分别使用了REST API框架中的POST、PUT、DELETE这三类资源操作。

Router、floating_ip的两类L3层资源的创建、更新、删除操作;以及Router和floating_ip相互之间的操作,譬如,路由器管理浮动网络、租户网络等。

小结

本次分析只是粗粒度的做了个讲解,不能算精细。但我们相信这是一个不错的开始,通过此番梳理,我们懂得了如下一些知识点:一是如何开发一个全新的服务Plugin及其Driver(与为一个已有的Plugin,添加Driver有所不同);二是如何去写一个neutron环境中的单元测试。

在不久的将来,多智时代一定会彻底走入我们的生活,有兴趣入行未来前沿产业的朋友,可以收藏多智时代,及时获取人工智能、大数据、云计算和物联网的前沿资讯和基础知识,让我们一起携手,引领人工智能的未来!

网络服务 数据模型 数据结构
0

聚焦多智时代,引领智能变革

© 多智时代(www.duozhishidai.com)版权所有 / 工信部备案 豫ICP备15012664号