【Nova】nova-network网络模型之flatdhcp网络-代码学习3
来源:互联网 发布:淘宝一元起拍在哪里 编辑:程序博客网 时间:2024/05/22 08:17
上一篇讲解了创建虚拟机实例时,nova-network所做的工作,那么这篇讲解下绑定浮动IP时的工作:
在为实例绑定浮动IP时,nova-api会通过rpc调用对应主机nova-network的associate_floating_ip API
# -----------------------------------------------# l3 nova/network/linux_net.py backend# -----------------------------------------------# 浮动IP的转发规则def floating_forward_rules(floating_ip, fixed_ip, device): rules = [] # 源地址是fixed_ip的数据包进行SNAT修改其源地址为floating_ip rule = '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip) if device: # 指定了device的情况下, 需要添加以下2条规则: # 1.源地址是fixed_ip, 目的地址是fixed_ip的数据包修改其源地址为floating_ip # 2.源地址是fixed_ip, 出口网卡是device的数据包修改其源地址为floating_ip rules.append(('float-snat', rule + ' -d %s' % fixed_ip)) rules.append(('float-snat', rule + ' -o %s' % device)) else: rules.append(('float-snat', rule)) # PREROUTING链: 目的地址为floating_ip的数据包进行DNAT修改其目的地址为fixed_ip rules.append( ('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip))) # OUTPUT链: 目的地址为floating_ip的数据包进行DNAT修改其目的地址为fixed_ip rules.append( ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip))) # POSTROUTING链: 源地址是fixed_ip的处于--ctstate DNAT状态的数据包进行SNAT修改其源地址为floating_ip rules.append(('POSTROUTING', '-s %s -m conntrack --ctstate DNAT -j SNAT ' '--to-source %s' % (fixed_ip, floating_ip))) return rules# 浮动IP的ebtables规则def floating_ebtables_rules(fixed_ip, network): # 保证只有进入网桥的流量才被桥接 return (['PREROUTING --logical-in %s -p ipv4 --ip-src %s ' '! --ip-dst %s -j redirect --redirect-target ACCEPT' % (network['bridge'], fixed_ip, network['cidr'])], 'nat') def ensure_floating_forward(floating_ip, fixed_ip, device, network): regex = '.*\s+%s(/32|\s+|$)' % floating_ip # 通过正则表达式来移除之前已存在的nat表规则, 对每个浮动IP, 要保证规则不能重复 num_rules = iptables_manager.ipv4['nat'].remove_rules_regex(regex) if num_rules: msg = _('Removed %(num)d duplicate rules for floating ip %(float)s') LOG.warn(msg % {'num': num_rules, 'float': floating_ip}) for chain, rule in floating_forward_rules(floating_ip, fixed_ip, device): # 将浮动IP转发规则逐条添加至iptables的nat表中 iptables_manager.ipv4['nat'].add_rule(chain, rule) # 使规则生效 iptables_manager.apply() # 如果device不是网络的网桥设备, 这里传递的是public_interface, 即外部网络网卡 if device != network['bridge']: # 添加浮动IP相关的规则到ebtables的nat表 ensure_ebtables_rules(*floating_ebtables_rules(fixed_ip, network)) def bind_floating_ip(floating_ip, device): # 让floating_ip成为public_interface的辅助IP _execute('ip', 'addr', 'add', str(floating_ip) + '/32', 'dev', device, run_as_root=True, check_exit_code=[0, 2, 254]) if CONF.send_arp_for_ha and CONF.send_arp_for_ha_count > 0: # 通过发送ARP包以保证HA send_arp_for_ip(floating_ip, device, CONF.send_arp_for_ha_count)# -----------------------------------------------# l3 nova/network/linux_net.py backend end# -----------------------------------------------class LinuxNetL3(L3Driver): def add_floating_ip(self, floating_ip, fixed_ip, l3_interface_id, network=None): # 添加浮动IP的规则到iptables和ebtables的nat表 linux_net.ensure_floating_forward(floating_ip, fixed_ip, l3_interface_id, network) # 让l3_interface_id绑定floating_ip linux_net.bind_floating_ip(floating_ip, l3_interface_id) class FloatingIP(object): def _floating_ip_owned_by_project(self, context, floating_ip): # 如果是管理员, 由于管理员对所有资源有权限, 那么直接返回 if context.is_admin: return # 如果浮动IP的所属的project_id不等于上下文的project_id, # 那么说明对此浮动IP没有操作权限, 抛出异常 if floating_ip.project_id != context.project_id: if floating_ip.project_id is None: LOG.warn(_('Address |%(address)s| is not allocated'), {'address': floating_ip.address}) raise exception.NotAuthorized() else: LOG.warn(_('Address |%(address)s| is not allocated to your ' 'project |%(project)s|'), {'address': floating_ip.address, 'project': context.project_id}) raise exception.NotAuthorized() def _associate_floating_ip(self, context, floating_address, fixed_address, interface, instance_uuid): interface = CONF.public_interface or interface # 为了进行同步, 这里使用了文件锁 @utils.synchronized(unicode(floating_address)) def do_associate(): # 通过nova-conductor或者直接访问数据库来进行绑定操作; # 这里只是将浮动IP与固定IP、实例进行了数据库关联 floating = floating_ip_obj.FloatingIP.associate(context, floating_address, fixed_address, self.host) # 这里写的不太严谨, 因为返回的floating可能为None fixed = floating.fixed_ip if not fixed: # 如果floating关联的fixed_ip为空, 说明之前floating已经绑定了该fixed_address, # 然后直接返回即可, 注:这里是一定返回值约定, return try: # 通过l3网络驱动来实现绑定工作的下半部分 self.l3driver.add_floating_ip(floating_address, fixed_address, interface, fixed['network']) except processutils.ProcessExecutionError as e: # 异常处理 with excutils.save_and_reraise_exception() as exc_ctxt: try: floating_ip_obj.FloatingIP.disassociate( context, floating_address) except Exception: LOG.warn(_('Failed to disassociated floating ' 'address: %s'), floating_address) pass if "Cannot find device" in str(e): try: LOG.error(_('Interface %s not found'), interface) except Exception: pass raise exception.NoFloatingIpInterface( interface=interface) payload = dict(project_id=context.project_id, instance_id=instance_uuid, floating_ip=floating_address) self.notifier.info(context, 'network.floating_ip.associate', payload) # 进行绑定工作 do_associate() @messaging.expected_exceptions(exception.FloatingIpNotFoundForAddress) def associate_floating_ip(self, context, floating_address, fixed_address, affect_auto_assigned=False): # 获取floating_address对应的数据库floating_ip对象 floating_ip = floating_ip_obj.FloatingIP.get_by_address( context, floating_address) # 如果affect_auto_assigned为False且floating_ip.auto_assigned为True, # 那么直接返回 if not affect_auto_assigned and floating_ip.auto_assigned: return # 检验是否有权限操作此浮动IP self._floating_ip_owned_by_project(context, floating_ip) orig_instance_uuid = None # 如果此浮动IP已关联了固定IP if floating_ip.fixed_ip_id: fixed_ip = floating_ip.fixed_ip if str(fixed_ip.address) == fixed_address: # 如果关联的固定IP就是此次要绑定的fixed_address, # 那么就不用做任何操作了 return orig_instance_uuid = fixed_ip.instance_uuid # 如果关联的固定IP不是此次要绑定的fixed_address, # 那么需要先对浮动IP进行解绑工作 self.disassociate_floating_ip(context, floating_address) fixed_ip = fixed_ip_obj.FixedIP.get_by_address(context, fixed_address) network = network_obj.Network.get_by_id(context.elevated(), fixed_ip.network_id) # 如果是multi_host, 那么此次操作的目标主机就是实例所在的主机; # 反之就是网络的host if network.multi_host: instance = instance_obj.Instance.get_by_uuid( context, fixed_ip.instance_uuid) host = instance.host else: host = network.host interface = floating_ip.interface if host == self.host: # 如果目标主机就是自己, 那么直接进行绑定即可 self._associate_floating_ip(context, floating_address, fixed_address, interface, fixed_ip.instance_uuid) else: # 如果目标主机不是自己, 那么通过rpc调用目标主机的_associate_floating_ip RpcAPI来 # 进行绑定工作, 可想而知, 这个RpcAPI也是调用的_associate_floating_ip这个本地方法 self.network_rpcapi._associate_floating_ip(context, floating_address, fixed_address, interface, host, fixed_ip.instance_uuid) return orig_instance_uuid
阅读全文
0 0
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习3
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习1
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习2
- 【Nova】nova-network网络模型之flatdhcp网络
- 【Nova】nova-network网络模型之flat网络-代码学习
- 【Nova】nova-network网络模型之vlan网络-代码学习
- 【Nova】nova-network网络模型之flat网络
- 【Nova】nova-network网络模型之vlan网络
- 【nova】【nova-network】nova-network在FlatDHCP模型下给VM分配多网卡
- nova-network网络模式
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- 【openstack】FlatDHCP模式单nova-network主机部署示例
- FlatDHCP模式单nova-network主机部署示例
- 【Nova】nova-compute代码学习3-创建虚拟机
- 【Nova】nova-compute代码学习2-状态机
- 大文件sql导到本地数据库
- POJ
- LTE物理层理解-预编码(Precoding)和码本(Codebook)
- 流程的Python 第十章:序列的修改、散列和切片
- 写了一个pca9633的iic驱动
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习3
- Java中的抽象类和接口
- python单例模式
- tcpdump 简介
- Android基础:API对应的版本号
- 异步IO编程
- 模板方法(template method)c++版本
- HDU
- 计算模型是否与人类对象感知有系统的不同?