【Nova】nova-network网络模型之vlan网络-代码学习
来源:互联网 发布:炫踪网络官网 编辑:程序博客网 时间:2024/05/22 05:11
首先讲解vlan网络下nova-network服务启动之前的准备工作:
通过调用VlanManager的init_host来进行初始化工作,通过分析代码可以看出vlan网络和flatdhcp网络的准备工作其实是大同小异的,最大区别就是创建vlan设备并让网桥与之相连
# -----------------------------------------------# l3 nova/network/linux_net.py backend# -----------------------------------------------# 之前有讲过, 不做赘述, 主要是在iptables的nat表中为虚拟子网创建SNAT规则, 使虚拟机实例可以通过public_interface上网;# 允许虚拟子网下的虚拟机实例通过metadata_host访问元数据服务, 允许虚拟子网下的虚拟机实例互相访问;# 允许虚拟子网下的虚拟机实例访问DMZ等def init_host(ip_range): add_snat_rule(ip_range) rules = [] for snat_range in CONF.force_snat_range: rules.append('PREROUTING -p ipv4 --ip-src %s --ip-dst %s ' '-j redirect --redirect-target ACCEPT' % (ip_range, snat_range)) if rules: ensure_ebtables_rules(rules, 'nat') # 如果metadata_host设置为127.0.0.1,感觉这里没必要? iptables_manager.ipv4['nat'].add_rule('POSTROUTING', '-s %s -d %s/32 -j ACCEPT' % (ip_range, CONF.metadata_host)) for dmz in CONF.dmz_cidr: iptables_manager.ipv4['nat'].add_rule('POSTROUTING', '-s %s -d %s -j ACCEPT' % (ip_range, dmz)) iptables_manager.ipv4['nat'].add_rule('POSTROUTING', '-s %(range)s -d %(range)s ' '-m conntrack ! --ctstate DNAT ' '-j ACCEPT' % {'range': ip_range}) iptables_manager.apply()# 设置网络设备的MTU(最大传输单元)def _set_device_mtu(dev): if CONF.network_device_mtu: # 默认为空 utils.execute('ip', 'link', 'set', dev, 'mtu', CONF.network_device_mtu, run_as_root=True, check_exit_code=[0, 2, 254]class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): @staticmethod @utils.synchronized('lock_vlan', external=True) # 创建vlan设备除非已经存在 def ensure_vlan(vlan_num, bridge_interface, mac_address=None): interface = 'vlan%s' % vlan_num # 判断vlan的网络设备是否存在 if not device_exists(interface): LOG.debug(_('Starting VLAN interface %s'), interface) # 在bridge_interface物理网卡上创建子vlan设备 _execute('ip', 'link', 'add', 'link', bridge_interface, 'name', interface, 'type', 'vlan', 'id', vlan_num, run_as_root=True, check_exit_code=[0, 2, 254]) if mac_address: # 为vlan设备设置MAC地址 _execute('ip', 'link', 'set', interface, 'address', mac_address, run_as_root=True, check_exit_code=[0, 2, 254]) # 启用vlan设备 _execute('ip', 'link', 'set', interface, 'up', run_as_root=True, check_exit_code=[0, 2, 254]) # 设置vlan设备的MTU _set_device_mtu(interface) return interface @staticmethod @utils.synchronized('lock_bridge', external=True) # 创建网桥并连接到interface设备 def ensure_bridge(bridge, interface, net_attrs=None, gateway=True, filtering=True): if not device_exists(bridge): LOG.debug(_('Starting Bridge %s'), bridge) _execute('brctl', 'addbr', bridge, run_as_root=True) _execute('brctl', 'setfd', bridge, 0, run_as_root=True) # _execute('brctl setageing %s 10' % bridge, run_as_root=True) _execute('brctl', 'stp', bridge, 'off', run_as_root=True) _execute('ip', 'link', 'set', bridge, 'up', run_as_root=True) if interface: msg = _('Adding interface %(interface)s to bridge %(bridge)s') LOG.debug(msg, {'interface': interface, 'bridge': bridge}) out, err = _execute('brctl', 'addif', bridge, interface, check_exit_code=False, run_as_root=True) if (err and err != "device %s is already a member of a bridge; " "can't enslave it to bridge %s.\n" % (interface, bridge)): msg = _('Failed to add interface: %s') % err raise exception.NovaException(msg) out, err = _execute('ip', 'link', 'set', interface, 'up', check_exit_code=False, run_as_root=True) old_routes = [] out, err = _execute('ip', 'route', 'show', 'dev', interface) for line in out.split('\n'): fields = line.split() if fields and 'via' in fields: old_routes.append(fields) _execute('ip', 'route', 'del', *fields, run_as_root=True) out, err = _execute('ip', 'addr', 'show', 'dev', interface, 'scope', 'global') for line in out.split('\n'): fields = line.split() if fields and fields[0] == 'inet': if fields[-2] in ('secondary', 'dynamic', ): params = fields[1:-2] else: params = fields[1:-1] _execute(*_ip_bridge_cmd('del', params, fields[-1]), run_as_root=True, check_exit_code=[0, 2, 254]) _execute(*_ip_bridge_cmd('add', params, bridge), run_as_root=True, check_exit_code=[0, 2, 254]) for fields in old_routes: _execute('ip', 'route', 'add', *fields, run_as_root=True) if filtering: ipv4_filter = iptables_manager.ipv4['filter'] if gateway: for rule in get_gateway_rules(bridge): ipv4_filter.add_rule(*rule) else: ipv4_filter.add_rule('FORWARD', ('--in-interface %s -j %s' % (bridge, CONF.iptables_drop_action))) ipv4_filter.add_rule('FORWARD', ('--out-interface %s -j %s' % (bridge, CONF.iptables_drop_action))) @staticmethod # 创建vlan和网桥 def ensure_vlan_bridge(vlan_num, bridge, bridge_interface, net_attrs=None, mac_address=None): # 创建vlan设备 interface = LinuxBridgeInterfaceDriver.ensure_vlan(vlan_num, bridge_interface, mac_address) # 这里创建网桥与FLATDHCP模式是一样的, 只是FLATDHCP模式下网桥直接连接到flat_interface物理网卡上, # 而VLAN模式下网桥连接到vlan_interface物理网卡的子vlan设备上 LinuxBridgeInterfaceDriver.ensure_bridge(bridge, interface, net_attrs) return interface def plug(self, network, mac_address, gateway=True): vlan = network.get('vlan') # VLAN模式下创建的网络的vlan字段为vlan id if vlan is not None: iface = CONF.vlan_interface or network['bridge_interface'] # 创建vlan和网桥 LinuxBridgeInterfaceDriver.ensure_vlan_bridge( vlan, network['bridge'], iface, network, mac_address) # 其实ensure_vlan_bridge就会返回vlan设备名, 所以这里直接获取返回值即可; # 这样获取vlan设备名也不是不可以, 只是以后如果要改vlan设备名的格式, 可能要改几个地方; # 可以看出OpenStack的代码也是有些小问题的, 不过可读性已经算很好的了 iface = 'vlan%s' % vlan else: iface = CONF.flat_interface or network['bridge_interface'] LinuxBridgeInterfaceDriver.ensure_bridge( network['bridge'], iface, network, gateway) if CONF.share_dhcp_address: # 共享同一个DHCP服务地址的情况下, 需要进行适当隔离, 保证DHCP服务只对宿主节点的实例服务 isolate_dhcp_address(iface, network['dhcp_server']) iptables_manager.apply() return network['bridge'] # 通过iptables对访问VPN实例的数据包进行转发def ensure_vpn_forward(public_ip, port, private_ip): # iptables的filter表的FORWARD链: 目的地址是VPN实例的固定IP、协议是udp、目的端口是1194的数据包接收 # 注:OpenVPN的默认端口是1194, 且使用UDP协议 iptables_manager.ipv4['filter'].add_rule('FORWARD', '-d %s -p udp ' '--dport 1194 ' '-j ACCEPT' % private_ip) # iptables的nat表的PREROUTING链: 对目的地址是VPN实例的浮动IP、协议是udp、目的端口是port的数据包进行 # DNAT修改其目的地址和端口为VPN实例的固定IP和1194 iptables_manager.ipv4['nat'].add_rule('PREROUTING', '-d %s -p udp ' '--dport %s -j DNAT --to %s:1194' % (public_ip, port, private_ip)) # iptables的nat表的OUTPUT链: 对目的地址是VPN实例的浮动IP、协议是udp、目的端口是port的数据包进行 # DNAT修改其目的地址和端口为VPN实例的固定IP和1194 iptables_manager.ipv4['nat'].add_rule('OUTPUT', '-d %s -p udp ' '--dport %s -j DNAT --to %s:1194' % (public_ip, port, private_ip)) iptables_manager.apply()# -----------------------------------------------# l3 nova/network/linux_net.py backend end# -----------------------------------------------class LinuxNetL3(L3Driver): def initialize_network(self, cidr): linux_net.init_host(cidr) def initialize(self, **kwargs): # 只允许初始化一次 if self.initialized: return LOG.debug("Initializing linux_net L3 driver") fixed_range = kwargs.get('fixed_range', False) networks = kwargs.get('networks', None) # 调用linux_net backend的init_host方法来初始化每个虚拟子网 if not fixed_range and networks is not None: for network in networks: self.initialize_network(network['cidr']) else: linux_net.init_host() # 为lo回环设备添加元数据服务IP # 通过iptables为元数据服务创建转发规则 linux_net.ensure_metadata_ip() linux_net.metadata_forward() self.initialized = True def initialize_gateway(self, network_ref): mac_address = utils.generate_mac_address() # 创建vlan和网桥 dev = linux_net.plug(network_ref, mac_address, gateway=(network_ref['gateway'] is not None)) # 配置网桥的IP和路由 linux_net.initialize_gateway_device(dev, network_ref) def add_vpn(self, public_ip, port, private_ip): linux_net.ensure_vpn_forward(public_ip, port, private_ip)class NetworkManager(manager.Manager): def init_host(self): # 使用管理员上下文来获取与本主机有关的全部网络 ctxt = context.get_admin_context() for network in network_obj.NetworkList.get_by_host(ctxt, self.host): # 针对每个网络在主机上进行设置工作, 需要子类进行实现 self._setup_network_on_host(ctxt, network) # 这里与FLATDHCP模式下一致, 更新DNS的本地解析文件并优雅地重启DNSmasq if CONF.update_dns_entries: dev = self.driver.get_dev(network) self.driver.update_dns(ctxt, dev, network) class FloatingIP(object): # 初始化主机的浮动IP def init_host_floating_ips(self): admin_context = context.get_admin_context() try: # 获取与本主机有关的全部浮动IP floating_ips = floating_ip_obj.FloatingIPList.get_by_host( admin_context, self.host) except exception.NotFound: return for floating_ip in floating_ips: if floating_ip.fixed_ip_id: try: fixed_ip = floating_ip.fixed_ip except exception.FixedIpNotFound: msg = _('Fixed ip %s not found') % floating_ip.fixed_ip_id LOG.debug(msg) continue interface = CONF.public_interface or floating_ip.interface try: # 这里就是为浮动IP创建转发规则, 并且将浮动IP作为辅助IP添加至public_interface self.l3driver.add_floating_ip(floating_ip.address, fixed_ip.address, interface, fixed_ip.network) except processutils.ProcessExecutionError: LOG.debug(_('Interface %s not found'), interface) raise exception.NoFloatingIpInterface(interface=interface)class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager): SHOULD_CREATE_BRIDGE = True SHOULD_CREATE_VLAN = True DHCP = True required_create_args = ['bridge_interface'] def __init__(self, network_driver=None, *args, **kwargs): super(VlanManager, self).__init__(network_driver=network_driver, *args, **kwargs) # 因为会为每个租户分配一整个子网, 因此不用对固定IP进行配额限制; # 这里的配额管理类是noop的 self.quotas_cls = quotas_obj.QuotasNoOp # 初始化工作入口 def init_host(self): # 获取管理员上下文 ctxt = context.get_admin_context() # 获取与本主机有关的全部网络 networks = network_obj.NetworkList.get_by_host(ctxt, self.host) # 使用l3驱动来初始化每个网络 self.l3driver.initialize(fixed_range=False, networks=networks) # 调用父类的init_host方法 NetworkManager.init_host(self) # 初始化主机的浮动IP self.init_host_floating_ips() @utils.synchronized('setup_network', external=True) def _setup_network_on_host(self, context, network): # VLAN模式下会为每个虚拟子网创建VPN实例(cloudpipe)用于访问子网中的虚拟机实例; # 我们需要给这些VPN实例配置可路由的vpn_ip, 并使用该vpn_ip访问VPN实例 if not network.vpn_public_address: # 当虚拟子网的vpn_public_address为空时, 通过vpn_ip配置选项来对其进行填充并保存进数据库 address = CONF.vpn_ip network.vpn_public_address = address network.save() else: address = network.vpn_public_address # 获取该网络下的DHCP服务地址 network.dhcp_server = self._get_dhcp_ip(context, network) # 使用l3驱动初始化网络, 之前已经做过了 self.l3driver.initialize_network(network.get('cidr')) # 创建vlan和网桥, 并进行初始化工作, 包括配置IP和路由 self.l3driver.initialize_gateway(network) # 如果配置了VPN实例的浮动IP并且linux_net backend有相关的方法, # 那么就在iptables中为VPN实例添加转发规则 if address == CONF.vpn_ip and hasattr(self.driver, "ensure_vpn_forward"): self.l3driver.add_vpn(CONF.vpn_ip, network.vpn_public_port, network.vpn_private_address) if not CONF.fake_network: # fake_network默认False dev = self.driver.get_dev(network) elevated = context.elevated() # 这里与FLATDHCP模式下一致, 更新DHCP服务的数据库文件并优雅地重启; # 如果使用IPv6就更新radvd路由服务的配置文件并重启 self.driver.update_dhcp(elevated, dev, network) if CONF.use_ipv6: self.driver.update_ra(context, dev, network) gateway = utils.get_my_linklocal(dev) network.gateway_v6 = gateway network.save()
vlan网络下分配固定IP和浮动IP与flatdhcp没有太多的区别,就不赘述了
阅读全文
0 0
- 【Nova】nova-network网络模型之vlan网络-代码学习
- 【Nova】nova-network网络模型之flat网络-代码学习
- 【Nova】nova-network网络模型之vlan网络
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习1
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习2
- 【Nova】nova-network网络模型之flatdhcp网络-代码学习3
- 【Nova】nova-network网络模型之flat网络
- 【Nova】nova-network网络模型之flatdhcp网络
- nova-network网络模式
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- openstack 网络架构 nova-network + neutron
- openstack nova -network使用vlan-manager
- 【Nova】nova-compute代码学习2-状态机
- 【Nova】nova-compute代码学习4-防火墙
- 【nova】【nova-network】nova-network在FlatDHCP模型下给VM分配多网卡
- Openstack的网络(nova)
- Mybatis JPA-集成方案+源码解析
- Log4j迁移到LogBack
- GDB调试Android代码——环境搭建及调试过程
- Jquery 中 event学习记录
- 7.25 结构体
- 【Nova】nova-network网络模型之vlan网络-代码学习
- Android7.0 和 Charles 的抓包 出现无法抓包unknown和证书无效
- Android自定义状态栏颜色与APP颜色保持一致
- 文摘收集
- [leetcode]368. Largest Divisible Subset
- mysql中timestamp,datetime,int类型的区别与优劣
- Glide错误java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
- Maven项目jar包出现: invalid LOC header (bad signature)
- CMake can't find Curses