博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(2)理解neutron ml2---network创建流程源码解析
阅读量:5076 次
发布时间:2019-06-12

本文共 6055 字,大约阅读时间需要 20 分钟。

Neutron的整体架构分为三层。
Server —> plugin —>agent
 
启动server之后neutron会将请求路径和对应的处理函数进行映射。
具体的处理函数由plugin来提供,plugin做的事情有两个:
 
1)在数据库中创建资源
2)发送rpc请求到具体的agent
 
所有的plugin提供统一的接口,包括核心资源的增删改查。
neutron原生提供ml2这一plugin,ml2plugin分为类型驱动和机制驱动。
 
下面从创建network的角度来看一下neutron的整个调用过程。
 
Ml2 plugin里实现了create_network。
/neutron/neutron/plugins/ml2/plugin.py
@utils.transaction_guard@db_api.retry_if_session_inactive()def create_network(self, context, network):    result, mech_context = self._create_network_db(context, network)    kwargs = {
'context': context, 'network': result} registry.notify(resources.NETWORK, events.AFTER_CREATE, self, **kwargs) try: self.mechanism_manager.create_network_postcommit(mech_context) except ml2_exc.MechanismDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("mechanism_manager.create_network_postcommit " "failed, deleting network '%s'"), result['id']) self.delete_network(context, result['id']) return result
其中比较重要的一个函数是 self._create_network_db,也就是在数据库中创建network。
neutron的核心设计理念就是将资源模型存放在数据库内,然后根据数据库的数据调用agent来做相应的网络配置。
下面看一下_create_network_db的内部实现:
def _create_network_db(self, context, network):    net_data = network[attributes.NETWORK]    tenant_id = net_data['tenant_id']    session = context.session    with session.begin(subtransactions=True):        self._ensure_default_security_group(context, tenant_id)        net_db = self.create_network_db(context, network)        result = self._make_network_dict(net_db, process_extensions=False,                                         context=context)        self.extension_manager.process_create_network(context, net_data,                                                      result)        self._process_l3_create(context, result, net_data)        net_data['id'] = result['id']        self.type_manager.create_network_segments(context, net_data,                                                  tenant_id)        self.type_manager.extend_network_dict_provider(context, result)        # Update the transparent vlan if configured        if utils.is_extension_supported(self, 'vlan-transparent'):            vlt = vlantransparent.get_vlan_transparent(net_data)            net_db['vlan_transparent'] = vlt            result['vlan_transparent'] = vlt        mech_context = driver_context.NetworkContext(self, context,                                                     result)        self.mechanism_manager.create_network_precommit(mech_context)        result[api.MTU] = self._get_network_mtu(result)        ...    self._apply_dict_extend_functions('networks', result, net_db)    return result, mech_context
其中重要的有两步:
 
1)self._process_l3_create(context, result, net_data)
2)self.type_manager.create_network_segments(context, net_data,  tenant_id)

self._process_l3_create

_process_l3_create从字面上来看是用来处理l3的创建,l3指的是三层网络,三层网络是通过
路由器来实现,路由器存在于网络节点。属于不同subnet的虚拟机想要互通必须通过router。
如果一个虚拟机希望联通外网,比如,访问www.google.com,则路由器必须连接了外网网关信息。
在neutron中被称为external_gateway_info。如下图所示,是一个连接了外部网关的路由器。

在服务启动的时候会从配置文件读取出来,并存到数据库中,查看一下ml2_vlan_allocations表,得到如下结果。

MariaDB [neutron]> select * from ml2_vlan_allocations;
+------------------+---------+-----------+
| physical_network | vlan_id | allocated |
+------------------+---------+-----------+
| physnet2         |    1000 |         0 |
| physnet2         |    1001 |         0 |
| physnet2         |    1002 |         0 |
| physnet2         |    1003 |         0 |
| physnet2         |    1004 |         0 |
| physnet2         |    1005 |         0 |
| physnet2         |    1006 |         0 |
| physnet2         |    1007 |         0 |
| physnet2         |    1008 |         0 |
| physnet2         |    1009 |         0 |
| physnet2         |    1010 |         0 |
| physnet2         |    1011 |         0 |
| physnet2         |    1012 |         0 |
| physnet2         |    1013 |         0 |
| physnet2         |    1014 |         0 |
| physnet2         |    1015 |         0 |
| physnet2         |    1016 |         0 |
| physnet2         |    1017 |         0 |
| physnet2         |    1018 |         0 |
| physnet2         |    1019 |         0 |
| physnet2         |    1020 |         0 |
| physnet2         |    1021 |         0 |
| physnet2         |    1022 |         0 |
| physnet2         |    1023 |         0 |
| physnet2         |    1024 |         0 |
| physnet2         |    1025 |         0 |
| physnet2         |    1026 |         0 |
| physnet2         |    1027 |         0 |
| physnet2         |    1028 |         0 |
| physnet2         |    1029 |         0 |
| physnet2         |    1030 |         0 |
+------------------+---------+-----------+
 
 self._add_network_segment(context, network_id, segment)最终会调用ml2/manages.py 里面的函数。
def _allocate_segment(self, session, network_type):    driver = self.drivers.get(network_type)    return driver.obj.allocate_tenant_segment(session)
而这个函数又会调用driver(VxLAN, Vlan, GRE等)的allocate_tenant_segment函数,来分配对应的segment。
在这里manages.py扮演一个调度者的角色,所有driver的方法调用都使用manages.py进行了一次封装。
plugins想要调用driver里的方法,要通过manages.py里定义的方法,manages.py内部包含了两个重要的manager。
 
class TypeManager(stevedore.named.NamedExtensionManager)
class MechanismManager(stevedore.named.NamedExtensionManager)
 
这两个manager把所有的机制驱动和类型驱动都封装了起来。并提供如下函数供plugin调用:
def _call_on_drivers(self, method_name, context,                     continue_on_failure=False, raise_db_retriable=False):    """Helper method for calling a method across all mechanism drivers.    """    errors = []    for driver in self.ordered_mech_drivers:        try:            getattr(driver.obj, method_name)(context)        except Exception as e:            if raise_db_retriable and db_api.is_retriable(e):                with excutils.save_and_reraise_exception():                    LOG.debug("DB exception raised by Mechanism driver "                              "'%(name)s' in %(method)s",                              {
'name': driver.name, 'method': method_name}, exc_info=e) LOG.exception( _LE("Mechanism driver '%(name)s' failed in %(method)s"), {
'name': driver.name, 'method': method_name} ) errors.append(e) if not continue_on_failure: break if errors: raise ml2_exc.MechanismDriverError( method=method_name, errors=errors )
那么想要调用驱动的方法,只要调用这个函数即可。
 
类型驱动和机制驱动也定义了抽象api 在neutron/plugins/ml2/driver_api.py内部。
 
@six.add_metaclass(abc.ABCMeta)
class TypeDriver(object)
 
@six.add_metaclass(abc.ABCMeta)
class MechanismDriver(object)
 
以上就是network创建流程的源码解析
 
 
 
 
 

 

转载于:https://www.cnblogs.com/zhouqi0505/p/10526340.html

你可能感兴趣的文章
160802、1.06s删除10w条重复记录只保留一条(mysql)及linux删除乱码文件
查看>>
辛德勒的救赎——再谈辛德勒名单
查看>>
浅析Android中的消息机制
查看>>
JAVA异常
查看>>
MySQL中间件
查看>>
sphinx 增量索引与主索引使用测试
查看>>
双向一对一
查看>>
Jrain'Lのvueblog
查看>>
ASP.NET WebAPI 07 路由
查看>>
《BI那点儿事》数据挖掘初探
查看>>
TotoiseSVN的基本使用方法
查看>>
2015.03.12,外语,读书笔记-《Word Power Made Easy》 10 “如何讨论交谈习惯”学习笔记 SESSION 24...
查看>>
Scala数组
查看>>
C使用FILE指针文件操作
查看>>
laravel 中MySQL临时表使用
查看>>
优化listview列表速度
查看>>
仿《雷霆战机》飞行射击手游开发--游戏的入口
查看>>
提示框插件SweetAlert
查看>>
用户试用体验报告
查看>>
we just reminded you about the Air Jordan 11 “Bred” release
查看>>