码迷,mamicode.com
首页 > Web开发 > 详细

neutron ml2 network创建流程源码解析

时间:2019-03-13 21:28:10      阅读:746      评论:0      收藏:0      [点我收藏+]

标签:驱动   ensure   fail   dash   comm   begin   理念   实现   服务启动   

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创建流程的源码解析
 
 
 
 
 

 

neutron ml2 network创建流程源码解析

标签:驱动   ensure   fail   dash   comm   begin   理念   实现   服务启动   

原文地址:https://www.cnblogs.com/zhouqi0505/p/10526340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!