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

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

port是neutron的核心资源之一,port的主要目的是承载Mac地址和ip地址。
有了Mac和ip地址虚拟机才能够实现彼此之间的通信。当然port不一定是
仅仅给虚拟机使用,也可能将port绑定在路由器上。一个port一定是属于一个
networks的,但是一个port有可能属于多个subnets,属于多个subnets意味着
一个网卡可以有多个ip地址,在创建虚拟机绑定网络的时候可以指定挂载的网卡
和对应的fixed_ip。
 
网卡创建的代码依然是放在了plugin.py这个文件里
/neutron/plugins/ml2/plugin.py
@utils.transaction_guard@db_api.retry_if_session_inactive()def create_port(self, context, port):    result, mech_context = self._create_port_db(context, port)    # notify any plugin that is interested in port create events    kwargs = {
'context': context, 'port': result} registry.notify(resources.PORT, events.AFTER_CREATE, self, **kwargs) try: self.mechanism_manager.create_port_postcommit(mech_context) except ml2_exc.MechanismDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("mechanism_manager.create_port_postcommit " "failed, deleting port '%s'"), result['id']) self.delete_port(context, result['id'], l3_port_check=False) self.notify_security_groups_member_updated(context, result) try: bound_context = self._bind_port_if_needed(mech_context) except os_db_exception.DBDeadlock: # bind port can deadlock in normal operation so we just cleanup # the port and let the API retry with excutils.save_and_reraise_exception(): LOG.debug("_bind_port_if_needed deadlock, deleting port %s", result['id']) self.delete_port(context, result['id']) except ml2_exc.MechanismDriverError: with excutils.save_and_reraise_exception(): LOG.error(_LE("_bind_port_if_needed " "failed, deleting port '%s'"), result['id']) self.delete_port(context, result['id'], l3_port_check=False) return bound_context.current

其中最重要的是上面四个步骤,最最重要的是_create_port_db这个函数。

def _create_port_db(self, context, port):    attrs = port[attributes.PORT]    if not attrs.get('status'):        attrs['status'] = const.PORT_STATUS_DOWN    session = context.session    with session.begin(subtransactions=True):        dhcp_opts = attrs.get(edo_ext.EXTRADHCPOPTS, [])        port_db = self.create_port_db(context, port)        result = self._make_port_dict(port_db, process_extensions=False)        self.extension_manager.process_create_port(context, attrs, result)        self._portsec_ext_port_create_processing(context, result, port)        # sgids must be got after portsec checked with security group        sgids = self._get_security_groups_on_port(context, port)        self._process_port_create_security_group(context, result, sgids)        network = self.get_network(context, result['network_id'])        binding = db.add_port_binding(session, result['id'])        mech_context = driver_context.PortContext(self, context, result,                                                  network, binding, None)        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)        self._setup_dhcp_agent_provisioning_component(context, result)    self._apply_dict_extend_functions('ports', result, port_db)    return result, mech_context

如上图所示_create_port_db做了很多和安全组以及port_binding相关的工作:主要是将port,security_group, port_binding等相关数据存入数据库,从中可以总结出ml2关于数据库
操作的逻辑,涉及数据存储到数据库的工作都会放在_create_xxx_db(xxx代表subnet, port, network等)函数内部进行操作。比如这里的创建_create_port_db。
db.add_port_binding(session, result['id']) 这句话处理port_binding相关的入库工作。具体代码如下所示:
def add_port_binding(session, port_id):    with session.begin(subtransactions=True):        record = models.PortBinding(            port_id=port_id,            vif_type=portbindings.VIF_TYPE_UNBOUND)        session.add(record)        return record
 
create_port_db则处理的是port本身的入库逻辑。port的创建有一个比较重要的逻辑就是分配ip地址,ip地址和mac地址是port这个资源模型所要承载的最终要的两个数据。

 下面看一下分配ip地址的代码:

def allocate_ips_for_port_and_store(self, context, port, port_id):    # Make a copy of port dict to prevent changing    # incoming dict by adding 'id' to it.    # Deepcopy doesn't work correctly in this case, because copy of    # ATTR_NOT_SPECIFIED object happens. Address of copied object doesn't    # match original object, so 'is' check fails    port_copy = {
'port': port['port'].copy()} port_copy['port']['id'] = port_id network_id = port_copy['port']['network_id'] ips = [] try: ips = self._allocate_ips_for_port(context, port_copy) for ip in ips: ip_address = ip['ip_address'] subnet_id = ip['subnet_id'] IpamPluggableBackend._store_ip_allocation( context, ip_address, network_id, subnet_id, port_id) return ips except Exception: with excutils.save_and_reraise_exception(): if ips: ipam_driver = driver.Pool.get_instance(None, context) if not ipam_driver.needs_rollback(): return LOG.debug("An exception occurred during port creation. " "Reverting IP allocation") self._safe_rollback(self._ipam_deallocate_ips, context, ipam_driver, port_copy['port'], ips, revert_on_fail=False)

 

 

 

 

 

 

 

 
 

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

你可能感兴趣的文章
C#类、接口、虚方法和抽象方法
查看>>
SpringBoot使用@Value从yml文件取值为空--注入静态变量
查看>>
Windows下Memcached的安装配置方法
查看>>
平台设备驱动之平台驱动
查看>>
C++关键字作用总结
查看>>
Codeforces Round #330 (Div. 2)B. Pasha and Phone 容斥
查看>>
HDU 1536 S-Nim SG博弈
查看>>
laravel学习之路5缓存
查看>>
51Nod 1085 背包问题
查看>>
WindowsPhone App如何扩展能够使用的内存
查看>>
串口调适
查看>>
Outlook 2010开机自启动
查看>>
验证IP地址格式是否正确的js函数
查看>>
python学习12-反射 判断函数与方法(转载)
查看>>
浅谈四种软件架构演进史
查看>>
链表-LeetCode19删除链表中的第N个节点
查看>>
更新页面缓存OutputCache
查看>>
C# TCP通信
查看>>
C# 远程调用实现案例
查看>>
c#调用存储过程两种方法
查看>>