Port Binding操作源码解读

一 类ML2Plugin中的处理
Plugin主要把握进行Port Binding的时机主要有下面3个:
1 port创建时,即create_port()执行时,如果已经提供了足够的信息,则需要第一时间进行bind。
2 由于update_port()导致端口信息变化时也需要重新bind端口。
3 Agent通过RPC从Plugin获取port信息时,也会尝试bind端口,这样会避免在获取信息的过程中,由于其他进程更新了port但是并没有bind而导致Agent不能获取最新的bind信息。
下面源码是第1种情况。
#neutron/plugins/ml2/plugin.py
    def create_port(self, context, port):
        attrs = port['port']
        attrs['status'] = const.PORT_STATUS_DOWN
        session = context.session
        with session.begin(subtransactions=True):
            #在数据库创建binding信息,设置port_id,设置vif_type为"unbound"
            binding = db.add_port_binding(session, result['id'])
            mech_context = driver_context.PortContext(self, context, result,
                                                      network, binding)
            new_host_port = self._get_host_port_if_changed(mech_context, attrs)
            #从传递过来的RESTful请求参数中获取host、vnic等信息,
            #并查询数据库是否已经有相应条目存在,如果没有
            #或者有但是这里获取的信息不一致,则将vif_type设置为"unbound"
            self._process_port_binding(mech_context, attrs)
            result[addr_pair.ADDRESS_PAIRS] = (
                self._process_create_allowed_address_pairs(
                    context, result,
                    attrs.get(addr_pair.ADDRESS_PAIRS)))
            self._process_port_create_extra_dhcp_opts(context, result,
                                                      dhcp_opts)
            self.mechanism_manager.create_port_precommit(mech_context)
        try:
            #如果需要且能够绑定,则进行bind
            bound_context = self._bind_port_if_needed(mech_context)
        return bound_context._port
至于update_port(),Port Binding的处理逻辑与create_port()相同,它们进行端口bind时数据库session已经结束,这么做的原因是,有些Driver可能需要在绑定过程中进行RPC通信,此时应避免持有数据库transaction,但是如此一来就可能会导致bind端口时引起竞争。
上面代码中_bind_port_if_needed()的目的就是处理这种竞争,它的基本思路是:如果将binding信息进行数据库提交的时候,另一个进程已经提交了binding信息则使用另外一个进程的结果,如果另外一个进程仅仅是改变了binding的信息但是还没有提交,则尝试将新的binding信息提交到数据库。
二 Mechanism Manager的处理
Mechanism Manager的处理逻辑很简单,仅仅是实现bind_port()方法:依次尝试调用每一个注册的Mechanism Driver,直到成功bind。
#neutron/plugins/ml2/managers.py
    def bind_port(self, context):
        binding = context._binding
        #依次尝试调用每一个注册的Mechanism Driver
        for driver in self.ordered_mech_drivers:
            try:
                #非常直接的调用每一个注册的Mechanim Driver
                driver.obj.bind_port(context)
                if binding.segment:
                         #bind成功
                    binding.driver = driver.name
                    return
三 Mechanism Driver的处理
以Linux Bridge Driver为例进行说明。
#neutron/plugins/ml2/drivers/mech_agent.py
class AgentMechanismDriverBase(api.MechanismDriver):
def bind_port(self, context):
        vnic_type = context.current.get(portbindings.VNIC_TYPE,
                                        portbindings.VNIC_NORMAL)
        if vnic_type not in self.supported_vnic_types:
            return
        for agent in context.host_agents(self.agent_type):
            LOG.debug(_("Checking agent: %s"), agent)
            if agent['alive']:
                for segment in context.network.network_segments:
                    if self.try_to_bind_segment_for_agent(context, segment,
                                                          agent):
                        return
AgentMechanismDriverBase实现了公用的bind_port()方法。
它的基本执行逻辑是:
寻找port所在host的所有该Driver的Agent(对于Linux Bridge Driver来说仅有一个),并确保Agent处于live状态,然后通过具体Driver对每个Segment进行逐一检查,如果此Segment能够提供符合条件的port,则返回binding信息给Ml2Plugin。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值