def test_north_south_traffic(self): # This function creates an external network which is connected to # central_external_bridge and spawns an external_vm on it. # The external_vm is configured with the gateway_ip (both v4 & v6 # addresses) of external subnet. Later, it creates a tenant router, # a tenant network and two tenant subnets (v4 and v6). The tenant # router is associated with tenant network and external network to # provide north-south connectivity to the VMs. # We validate the following in this testcase. # 1. SNAT support: using ping from tenant VM to external_vm # 2. Floating IP support: using ping from external_vm to VM floating ip # 3. IPv6 ext connectivity: using ping6 from tenant vm to external_vm. tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) external_vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_external_bridge, common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) # Create an IPv6 subnet in the external network v6network = self.useFixture( ip_network.ExclusiveIPNetwork( "2001:db8:1234::1", "2001:db8:1234::10", "64")).network ext_v6sub = self.safe_client.create_subnet( tenant_id, ext_net['id'], v6network) router = self.safe_client.create_router(tenant_id, external_network=ext_net['id']) # Configure the gateway_ip of external v6subnet on the external_vm. external_vm.ipv6_cidr = common_utils.ip_to_cidr( ext_v6sub['gateway_ip'], 64) # Configure an IPv6 downstream route to the v6Address of router gw port for fixed_ip in router['external_gateway_info']['external_fixed_ips']: if netaddr.IPNetwork(fixed_ip['ip_address']).version == 6: external_vm.set_default_gateway(fixed_ip['ip_address']) vm = self._create_net_subnet_and_vm( tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'], self.environment.hosts[1], router) # ping external vm to test snat vm.block_until_ping(external_vm.ip) fip = self.safe_client.create_floatingip( tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id']) # ping floating ip from external vm external_vm.block_until_ping(fip['floating_ip_address']) # Verify VM is able to reach the router interface. vm.block_until_ping(vm.gateway_ipv6) # Verify north-south connectivity using ping6 to external_vm. vm.block_until_ping(external_vm.ipv6)
def _snat_redirect_modify(self, gateway, sn_port, sn_int, is_add): """Adds or removes rules and routes for SNAT redirection.""" try: ns_ipr = ip_lib.IPRule(namespace=self.ns_name) ns_ipd = ip_lib.IPDevice(sn_int, namespace=self.ns_name) if is_add: ns_ipwrapr = ip_lib.IPWrapper(namespace=self.ns_name) for port_fixed_ip in sn_port["fixed_ips"]: # Find the first gateway IP address matching this IP version port_ip_addr = port_fixed_ip["ip_address"] port_ip_vers = netaddr.IPAddress(port_ip_addr).version for gw_fixed_ip in gateway["fixed_ips"]: gw_ip_addr = gw_fixed_ip["ip_address"] if netaddr.IPAddress(gw_ip_addr).version == port_ip_vers: sn_port_cidr = common_utils.ip_to_cidr(port_ip_addr, port_fixed_ip["prefixlen"]) snat_idx = self._get_snat_idx(sn_port_cidr) if is_add: ns_ipd.route.add_gateway(gw_ip_addr, table=snat_idx) ns_ipr.rule.add(sn_port_cidr, snat_idx, snat_idx) ns_ipwrapr.netns.execute(["sysctl", "-w", "net.ipv4.conf.%s.send_redirects=0" % sn_int]) else: self._snat_delete_device_gateway(ns_ipd, gw_ip_addr, snat_idx) ns_ipr.rule.delete(sn_port_cidr, snat_idx, snat_idx) break except Exception: if is_add: exc = _LE("DVR: error adding redirection logic") else: exc = _LE("DVR: removed snat failed") LOG.exception(exc)
def test_ha_router_restart_agents_no_packet_lost(self): tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) router = self.safe_client.create_router(tenant_id, ha=True, external_network=ext_net['id']) external_vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_external_bridge, common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) common_utils.wait_until_true( lambda: len(self.client.list_l3_agent_hosting_routers( router['id'])['agents']) == 2, timeout=90) common_utils.wait_until_true( functools.partial( self._is_ha_router_active_on_one_agent, router['id']), timeout=90) router_ip = router['external_gateway_info'][ 'external_fixed_ips'][0]['ip_address'] l3_agents = [host.agents['l3'] for host in self.environment.hosts] self._assert_ping_during_agents_restart( l3_agents, external_vm.namespace, [router_ip], count=60)
def add(self, device, cidr): table = device.route.table(self.name) cidr = netaddr.IPNetwork(cidr) # Get the network cidr (e.g. 192.168.5.135/23 -> 192.168.4.0/23) net = utils.ip_to_cidr(cidr.network, cidr.prefixlen) self._keep.add((net, device.name)) table.add_onlink_route(net)
def test_floating_ip_added_dist(self, mIPRule, mIPDevice, mock_adv_notif): router = mock.MagicMock() ri = self._create_router(router) ext_net_id = _uuid() subnet_id = _uuid() agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30', 'prefixlen': 24, 'subnet_id': subnet_id}], 'subnets': [{'id': subnet_id, 'cidr': '20.0.0.0/24', 'gateway_ip': '20.0.0.1'}], 'id': _uuid(), 'network_id': ext_net_id, 'mac_address': 'ca:fe:de:ad:be:ef'} fip = {'id': _uuid(), 'host': HOSTNAME, 'floating_ip_address': '15.1.2.3', 'fixed_ip_address': '192.168.0.1', 'floating_network_id': ext_net_id, 'port_id': _uuid()} ri.fip_ns = mock.Mock() ri.fip_ns.agent_gateway_port = agent_gw_port ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI ri.rtr_fip_subnet = lla.LinkLocalAddressPair('169.254.30.42/31') ri.dist_fip_count = 0 ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) ri.floating_ip_added_dist(fip, ip_cidr) mIPRule().rule.add.assert_called_with('192.168.0.1', 16, FIP_PRI) self.assertEqual(1, ri.dist_fip_count)
def _ip_prefix_arg(self, direction, ip_prefix): if not(ip_prefix): return [] args = ['-%s' % direction, '%s' % utils.ip_to_cidr(ip_prefix)] return args
def _list_floating_ip_cidrs(self): # Compute a list of addresses this router is supposed to have. # This avoids unnecessarily removing those addresses and # causing a momentarily network outage. floating_ips = self.get_floating_ips() return [common_utils.ip_to_cidr(ip['floating_ip_address']) for ip in floating_ips]
def test_get_ip_addresses(self): namespace = 'ns_test-' + uuidutils.generate_uuid() priv_ip_lib.create_netns(namespace) self.addCleanup(self._remove_ns, namespace) interfaces = { '20': {'cidr': '192.168.10.20/24', 'scope': 'link', 'add_broadcast': True}, '30': {'cidr': '2001::1/64', 'scope': 'global', 'add_broadcast': False}} for int_name, int_parameters in interfaces.items(): priv_ip_lib.create_interface(int_name, namespace, 'dummy', index=int(int_name)) ip_lib.add_ip_address( int_parameters['cidr'], int_name, namespace, int_parameters['scope'], int_parameters['add_broadcast']) ip_addresses = priv_ip_lib.get_ip_addresses(namespace) for ip_address in ip_addresses: int_name = str(ip_address['index']) ip = _get_attr(ip_address, 'IFA_ADDRESS') mask = ip_address['prefixlen'] cidr = common_utils.ip_to_cidr(ip, mask) self.assertEqual(interfaces[int_name]['cidr'], cidr) self.assertEqual(interfaces[int_name]['scope'], ip_lib.IP_ADDRESS_SCOPE[ip_address['scope']])
def test_snat_and_floatingip(self): # This function creates external network and boots an extrenal vm # on it with gateway ip and connected to central_external_bridge. # Later it creates a tenant vm on tenant network, with tenant router # connected to tenant network and external network. # To test snat and floatingip, try ping between tenant and external vms tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) external_vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_external_bridge, common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) router = self.safe_client.create_router(tenant_id, external_network=ext_net['id']) vm = self._create_net_subnet_and_vm( tenant_id, '20.0.0.0/24', self.environment.hosts[1], router) # ping external vm to test snat vm.block_until_ping(external_vm.ip) fip = self.safe_client.create_floatingip( tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id']) # ping floating ip from external vm external_vm.block_until_ping(fip['floating_ip_address'])
def add_floating_ip(self, fip, interface_name, device): if not self._add_fip_addr_to_device(fip, device): return l3_constants.FLOATINGIP_STATUS_ERROR # Special Handling for DVR - update FIP namespace ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) self.floating_ip_added_dist(fip, ip_cidr) return l3_constants.FLOATINGIP_STATUS_ACTIVE
def _list_centralized_floating_ip_cidrs(self): # Compute a list of addresses this gw is supposed to have. # This avoids unnecessarily removing those addresses and # causing a momentarily network outage. floating_ips = self.get_floating_ips() return [common_utils.ip_to_cidr(ip['floating_ip_address']) for ip in floating_ips if ip.get(lib_constants.DVR_SNAT_BOUND)]
def connect_to_internal_network_via_tunneling(self): veth_1, veth_2 = self.useFixture( net_helpers.VethFixture()).ports # NOTE: This sets an IP address on the host's root namespace # which is cleaned up when the device is deleted. veth_1.addr.add(common_utils.ip_to_cidr(self.local_ip, 32)) veth_1.link.set_up() veth_2.link.set_up()
def _configure_port_for_rabbitmq(self): self.env_desc.network_range = self._get_network_range() if not self.env_desc.network_range: return "127.0.0.1" rabbitmq_ip = str(self.env_desc.network_range[1]) rabbitmq_port = ip_lib.IPDevice(self.central_data_bridge.br_name) rabbitmq_port.addr.add(common_utils.ip_to_cidr(rabbitmq_ip, 24)) rabbitmq_port.link.set_up() return rabbitmq_ip
def _get_gw_ips_cidr(self): gw_cidrs = set() ex_gw_port = self.get_ex_gw_port() if ex_gw_port: for ip_addr in ex_gw_port['fixed_ips']: ex_gw_ip = ip_addr['ip_address'] addr = netaddr.IPAddress(ex_gw_ip) if addr.version == lib_constants.IP_VERSION_4: gw_cidrs.add(common_utils.ip_to_cidr(ex_gw_ip)) return gw_cidrs
def get_expected_keepalive_configuration(self, router): router_id = router.router_id ha_device_name = router.get_ha_device_name() ha_device_cidr = self._port_first_ip_cidr(router.ha_port) external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) external_device_name = router.get_external_device_name( external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[l3_constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') return """vrrp_instance VR_1 { state BACKUP interface %(ha_device_name)s virtual_router_id 1 priority 50 nopreempt advert_int 2 track_interface { %(ha_device_name)s } virtual_ipaddress { 169.254.0.1/24 dev %(ha_device_name)s } virtual_ipaddress_excluded { %(floating_ip_cidr)s dev %(external_device_name)s %(external_device_cidr)s dev %(external_device_name)s %(internal_device_cidr)s dev %(internal_device_name)s %(ex_port_ipv6)s dev %(external_device_name)s scope link %(int_port_ipv6)s dev %(internal_device_name)s scope link } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(external_device_name)s 8.8.8.0/24 via 19.4.4.4 } }""" % { 'router_id': router_id, 'ha_device_name': ha_device_name, 'ha_device_cidr': ha_device_cidr, 'external_device_name': external_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6 }
def _create_external_vm(self, network, subnet): vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_bridge, common_utils.ip_to_cidr(subnet['gateway_ip'], 24))) # NOTE(slaweq): as ext_net is 'vlan' network type external_vm needs to # send packets with proper vlan also vm.bridge.set_db_attribute( "Port", vm.port.name, "tag", network.get("provider:segmentation_id")) return vm
def _internal_network_updated(self, port, subnet_id, prefix, old_prefix, updated_cidrs): interface_name = self.get_internal_device_name(port["id"]) if prefix != l3_constants.PROVISIONAL_IPV6_PD_PREFIX: fixed_ips = port["fixed_ips"] for fixed_ip in fixed_ips: if fixed_ip["subnet_id"] == subnet_id: v6addr = common_utils.ip_to_cidr(fixed_ip["ip_address"], fixed_ip.get("prefixlen")) if v6addr not in updated_cidrs: self.driver.add_ipv6_addr(interface_name, v6addr, self.ns_name) else: self.driver.delete_ipv6_addr_with_prefix(interface_name, old_prefix, self.ns_name)
def _add_fip_addr_to_device(self, fip, device): """Configures the floating ip address on the device. """ try: ip_cidr = common_utils.ip_to_cidr(fip["floating_ip_address"]) device.addr.add(ip_cidr) return True except RuntimeError: # any exception occurred here should cause the floating IP # to be set in error state LOG.warn(_LW("Unable to configure IP address for " "floating IP: %s"), fip["id"])
def external_gateway_removed(self, ex_gw_port, interface_name): LOG.debug("External gateway removed: port(%s), interface(%s)", ex_gw_port, interface_name) device = ip_lib.IPDevice(interface_name, namespace=self.ns_name) for ip_addr in ex_gw_port['fixed_ips']: self.remove_external_gateway_ip(device, common_utils.ip_to_cidr( ip_addr['ip_address'], ip_addr['prefixlen'])) self.driver.unplug(interface_name, bridge=self.agent_conf.external_network_bridge, namespace=self.ns_name, prefix=EXTERNAL_DEV_PREFIX)
def _ip_prefix_arg(self, direction, ip_prefix): #NOTE (nati) : source_group_id is converted to list of source_ # ip_prefix in server side if ip_prefix: if '/' not in ip_prefix: # we need to convert it into a prefix to match iptables ip_prefix = c_utils.ip_to_cidr(ip_prefix) elif ip_prefix.endswith('/0'): # an allow for every address is not a constraint so # iptables drops it return [] return ['-%s' % direction, ip_prefix] return []
def process_floating_ip_addresses(self, interface_name): """Configure IP addresses on router's external gateway interface. Ensures addresses for existing floating IPs and cleans up those that should not longer be configured. """ fip_statuses = {} if interface_name is None: LOG.debug('No Interface for floating IPs router: %s', self.router['id']) return fip_statuses device = ip_lib.IPDevice(interface_name, namespace=self.ns_name) existing_cidrs = self.get_router_cidrs(device) new_cidrs = set() gw_cidrs = self._get_gw_ips_cidr() floating_ips = self.get_floating_ips() # Loop once to ensure that floating ips are configured. for fip in floating_ips: fip_ip = fip['floating_ip_address'] ip_cidr = common_utils.ip_to_cidr(fip_ip) new_cidrs.add(ip_cidr) fip_statuses[fip['id']] = lib_constants.FLOATINGIP_STATUS_ACTIVE if ip_cidr not in existing_cidrs: fip_statuses[fip['id']] = self.add_floating_ip( fip, interface_name, device) LOG.debug('Floating ip %(id)s added, status %(status)s', {'id': fip['id'], 'status': fip_statuses.get(fip['id'])}) elif (fip_ip in self.fip_map and self.fip_map[fip_ip] != fip['fixed_ip_address']): LOG.debug("Floating IP was moved from fixed IP " "%(old)s to %(new)s", {'old': self.fip_map[fip_ip], 'new': fip['fixed_ip_address']}) fip_statuses[fip['id']] = self.move_floating_ip(fip) elif fip_statuses[fip['id']] == fip['status']: # mark the status as not changed. we can't remove it because # that's how the caller determines that it was removed fip_statuses[fip['id']] = FLOATINGIP_STATUS_NOCHANGE fips_to_remove = ( ip_cidr for ip_cidr in existing_cidrs - new_cidrs - gw_cidrs if common_utils.is_cidr_host(ip_cidr)) for ip_cidr in fips_to_remove: LOG.debug("Removing floating ip %s from interface %s in " "namespace %s", ip_cidr, interface_name, self.ns_name) self.remove_floating_ip(device, ip_cidr) return fip_statuses
def test_floating_ip_added_dist(self, mock_add_ip_rule, mIPDevice, mock_adv_notif): router = mock.MagicMock() ri = self._create_router(router) ri.ex_gw_port = ri.router['gw_port'] ext_net_id = _uuid() subnet_id = _uuid() agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30', 'prefixlen': 24, 'subnet_id': subnet_id}], 'subnets': [{'id': subnet_id, 'cidr': '20.0.0.0/24', 'gateway_ip': '20.0.0.1'}], 'id': _uuid(), 'network_id': ext_net_id, 'mac_address': 'ca:fe:de:ad:be:ef'} fip = {'id': _uuid(), 'host': HOSTNAME, 'floating_ip_address': '15.1.2.3', 'fixed_ip_address': '192.168.0.1', 'floating_network_id': ext_net_id, 'port_id': _uuid()} ri.fip_ns = mock.Mock() ri.fip_ns.agent_gateway_port = agent_gw_port ri.create_dvr_external_gateway_on_agent(ri.ex_gw_port) ri._check_rtr_2_fip_connect = mock.Mock() ri.connect_rtr_2_fip() self.assertTrue(ri.rtr_fip_connect) ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI subnet = lla.LinkLocalAddressPair('169.254.30.42/31') ri.rtr_fip_subnet = subnet ri.fip_ns.local_subnets = mock.Mock() ri.fip_ns.local_subnets.allocate.return_value = subnet ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) ri.floating_ip_added_dist(fip, ip_cidr) mock_add_ip_rule.assert_called_with( namespace=ri.router_namespace.name, ip='192.168.0.1', table=16, priority=FIP_PRI) ri.fip_ns.local_subnets.allocate.assert_not_called() # Validate that fip_ns.local_subnets is called when # ri.rtr_fip_subnet is None ri.rtr_fip_subnet = None ri.floating_ip_added_dist(fip, ip_cidr) mock_add_ip_rule.assert_called_with( namespace=ri.router_namespace.name, ip='192.168.0.1', table=16, priority=FIP_PRI) ri.fip_ns.local_subnets.allocate.assert_called_once_with(ri.router_id)
def _setup_spoof_filter_chain(self, port, table, mac_ip_pairs, rules): if mac_ip_pairs: chain_name = self._port_chain_name(port, SPOOF_FILTER) table.add_chain(chain_name) for mac, ip in mac_ip_pairs: if ip is None: # If fixed_ips is [] this rule will be added to the end # of the list after the allowed_address_pair rules. table.add_rule(chain_name, "-m mac --mac-source %s -j RETURN" % mac.upper(), comment=ic.PAIR_ALLOW) else: # we need to convert it into a prefix to match iptables ip = c_utils.ip_to_cidr(ip) table.add_rule( chain_name, "-s %s -m mac --mac-source %s -j RETURN" % (ip, mac.upper()), comment=ic.PAIR_ALLOW ) table.add_rule(chain_name, "-j DROP", comment=ic.PAIR_DROP) rules.append("-j $%s" % chain_name)
def _test_gateway_ip_changed(self): tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) external_vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_bridge, common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) router = self.safe_client.create_router(tenant_id, external_network=ext_net['id']) vm = self._create_net_subnet_and_vm( tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'], self.environment.hosts[1], router) # ping external vm to test snat vm.block_until_ping(external_vm.ip) fip = self.safe_client.create_floatingip( tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id']) # ping floating ip from external vm external_vm.block_until_ping(fip['floating_ip_address']) # ping router gateway IP old_gw_ip = router['external_gateway_info'][ 'external_fixed_ips'][0]['ip_address'] external_vm.block_until_ping(old_gw_ip) gateway_port = self.safe_client.list_ports( device_id=router['id'], device_owner=constants.DEVICE_OWNER_ROUTER_GW)[0] ip_1 = str(netaddr.IPNetwork( ext_sub['gateway_ip']).next(100)).split('/')[0] ip_2 = str(netaddr.IPNetwork( ext_sub['gateway_ip']).next(101)).split('/')[0] self.safe_client.update_port(gateway_port['id'], fixed_ips=[ {'ip_address': ip_1}, {'ip_address': ip_2}]) # ping router gateway new IPs external_vm.block_until_ping(ip_1) external_vm.block_until_ping(ip_2) # ping router old gateway IP, should fail now external_vm.block_until_no_ping(old_gw_ip)
def process_floating_ip_addresses(self, interface_name): """Configure IP addresses on router's external gateway interface. Ensures addresses for existing floating IPs and cleans up those that should not longer be configured. """ fip_statuses = {} if interface_name is None: LOG.debug("No Interface for floating IPs router: %s", self.router["id"]) return fip_statuses device = ip_lib.IPDevice(interface_name, namespace=self.ns_name) existing_cidrs = self.get_router_cidrs(device) new_cidrs = set() floating_ips = self.get_floating_ips() # Loop once to ensure that floating ips are configured. for fip in floating_ips: fip_ip = fip["floating_ip_address"] ip_cidr = common_utils.ip_to_cidr(fip_ip) new_cidrs.add(ip_cidr) fip_statuses[fip["id"]] = l3_constants.FLOATINGIP_STATUS_ACTIVE if ip_cidr not in existing_cidrs: fip_statuses[fip["id"]] = self.add_floating_ip(fip, interface_name, device) LOG.debug( "Floating ip %(id)s added, status %(status)s", {"id": fip["id"], "status": fip_statuses.get(fip["id"])}, ) # mark the status as not changed. we can't remove it because # that's how the caller determines that it was removed if fip_statuses[fip["id"]] == fip["status"]: fip_statuses[fip["id"]] = FLOATINGIP_STATUS_NOCHANGE fips_to_remove = (ip_cidr for ip_cidr in existing_cidrs - new_cidrs if common_utils.is_cidr_host(ip_cidr)) for ip_cidr in fips_to_remove: LOG.debug( "Removing floating ip %s from interface %s in " "namespace %s", ip_cidr, interface_name, self.ns_name ) self.remove_floating_ip(device, ip_cidr) return fip_statuses
def _snat_redirect_modify(self, gateway, sn_port, sn_int, is_add): """Adds or removes rules and routes for SNAT redirection.""" try: ns_ipr = ip_lib.IPRule(namespace=self.ns_name) ns_ipd = ip_lib.IPDevice(sn_int, namespace=self.ns_name) if is_add: ns_ipwrapr = ip_lib.IPWrapper(namespace=self.ns_name) for port_fixed_ip in sn_port['fixed_ips']: # Iterate and find the gateway IP address matching # the IP version port_ip_addr = port_fixed_ip['ip_address'] port_ip_vers = netaddr.IPAddress(port_ip_addr).version for gw_fixed_ip in gateway['fixed_ips']: gw_ip_addr = gw_fixed_ip['ip_address'] if netaddr.IPAddress(gw_ip_addr).version == port_ip_vers: sn_port_cidr = common_utils.ip_to_cidr( port_ip_addr, port_fixed_ip['prefixlen']) snat_idx = self._get_snat_idx(sn_port_cidr) if is_add: ns_ipd.route.add_gateway(gw_ip_addr, table=snat_idx) ns_ipr.rule.add(ip=sn_port_cidr, table=snat_idx, priority=snat_idx) ns_ipwrapr.netns.execute( ['sysctl', '-w', 'net.ipv4.conf.%s.send_redirects=0' % sn_int]) else: self._delete_gateway_device_if_exists(ns_ipd, gw_ip_addr, snat_idx) ns_ipr.rule.delete(ip=sn_port_cidr, table=snat_idx, priority=snat_idx) except Exception: if is_add: exc = _LE('DVR: error adding redirection logic') else: exc = _LE('DVR: snat remove failed to clear the rule ' 'and device') LOG.exception(exc)
def get_router_cidrs(self, device): """As no floatingip will be set on the rfp device. Get floatingip from the route of fip namespace. """ if not self.fip_ns: return set() fip_ns_name = self.fip_ns.get_name() fip_2_rtr_name = self.fip_ns.get_int_device_name(self.router_id) device = ip_lib.IPDevice(fip_2_rtr_name, namespace=fip_ns_name) if not device.exists(): return set() if self.rtr_fip_subnet is None: self.rtr_fip_subnet = self.fip_ns.local_subnets.allocate( self.router_id) rtr_2_fip, _fip_2_rtr = self.rtr_fip_subnet.get_pair() exist_routes = device.route.list_routes( lib_constants.IP_VERSION_4, via=str(rtr_2_fip.ip)) return {common_utils.ip_to_cidr(route['cidr']) for route in exist_routes}
def external_gateway_updated(self, ri, ex_gw_port, interface_name): preserve_ips = [] if ri.router['distributed']: if (self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT and self.get_gw_port_host(ri.router) == self.host): ns_name = self.get_snat_ns_name(ri.router['id']) else: # no centralized SNAT gateway for this node/agent LOG.debug("not hosting snat for router: %s", ri.router['id']) return else: ns_name = ri.ns_name floating_ips = ri.get_floating_ips() preserve_ips = [common_utils.ip_to_cidr(ip['floating_ip_address']) for ip in floating_ips] self._external_gateway_added(ri, ex_gw_port, interface_name, ns_name, preserve_ips) if ri.is_ha: ri._ha_external_gateway_updated(ex_gw_port, interface_name)
def test_ha_router_restart_agents_no_packet_lost(self): tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) router = self.safe_client.create_router(tenant_id, ha=True, external_network=ext_net['id']) external_vm = self.useFixture( machine_fixtures.FakeMachine( self.environment.central_bridge, common_utils.ip_to_cidr(ext_sub['gateway_ip'], 24))) common_utils.wait_until_true( lambda: len(self.client.list_l3_agent_hosting_routers( router['id'])['agents']) == 2, timeout=90) common_utils.wait_until_true( functools.partial( self._is_ha_router_active_on_one_agent, router['id']), timeout=90) router_ip = router['external_gateway_info'][ 'external_fixed_ips'][0]['ip_address'] # Let's check first if connectivity from external_vm to router's # external gateway IP is possible before we restart agents external_vm.block_until_ping(router_ip) l3_agents = [host.agents['l3'] for host in self.environment.hosts] l3_standby_agents = self._get_l3_agents_with_ha_state( l3_agents, router['id'], 'standby') l3_active_agents = self._get_l3_agents_with_ha_state( l3_agents, router['id'], 'active') self._assert_ping_during_agents_restart( l3_standby_agents, external_vm.namespace, [router_ip], count=60) self._assert_ping_during_agents_restart( l3_active_agents, external_vm.namespace, [router_ip], count=60)
def sync_port_forwarding_fip(self, context, routers): if not routers: return router_ids = [router.get('id') for router in routers] router_pf_fip_set = collections.defaultdict(set) fip_pfs = collections.defaultdict(set) router_fip = collections.defaultdict(set) item_pf_fields = pf.PortForwarding.get_port_forwarding_obj_by_routers( context, router_ids) for router_id, fip_addr, pf_id, fip_id in item_pf_fields: router_pf_fip_set[router_id].add(utils.ip_to_cidr(fip_addr, 32)) fip_pfs[fip_id].add(pf_id) router_fip[router_id].add(fip_id) for router in routers: if router['id'] in router_fip: router['port_forwardings_fip_set'] = router_pf_fip_set[ router['id']] router['fip_managed_by_port_forwardings'] = router_fip[ router['id']]
def add_floating_ip(self, fip, interface_name, device): fip_ip = fip['floating_ip_address'] ip_cidr = common_utils.ip_to_cidr(fip_ip) self._add_vip(ip_cidr, interface_name)
def add_floating_ip(self, fip, interface_name, device): # Special Handling for DVR - update FIP namespace ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) return self.floating_ip_added_dist(fip, ip_cidr)
def get_expected_keepalive_configuration(self, router): ha_device_name = router.get_ha_device_name() external_port = router.get_ex_gw_port() ex_port_ipv6 = ip_lib.get_ipv6_lladdr(external_port['mac_address']) ex_device_name = router.get_external_device_name( external_port['id']) external_device_cidr = self._port_first_ip_cidr(external_port) internal_port = router.router[constants.INTERFACE_KEY][0] int_port_ipv6 = ip_lib.get_ipv6_lladdr(internal_port['mac_address']) internal_device_name = router.get_internal_device_name( internal_port['id']) internal_device_cidr = self._port_first_ip_cidr(internal_port) floating_ip_cidr = common_utils.ip_to_cidr( router.get_floating_ips()[0]['floating_ip_address']) default_gateway_ip = external_port['subnets'][0].get('gateway_ip') extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr') return textwrap.dedent("""\ global_defs { notification_email_from %(email_from)s router_id %(router_id)s } vrrp_instance VR_1 { state BACKUP interface %(ha_device_name)s virtual_router_id 1 priority 50 garp_master_delay 60 nopreempt advert_int 2 track_interface { %(ha_device_name)s } virtual_ipaddress { 169.254.0.1/24 dev %(ha_device_name)s } virtual_ipaddress_excluded { %(floating_ip_cidr)s dev %(ex_device_name)s %(external_device_cidr)s dev %(ex_device_name)s %(internal_device_cidr)s dev %(internal_device_name)s %(ex_port_ipv6)s dev %(ex_device_name)s scope link %(int_port_ipv6)s dev %(internal_device_name)s scope link } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(ex_device_name)s 8.8.8.0/24 via 19.4.4.4 %(extra_subnet_cidr)s dev %(ex_device_name)s scope link } }""") % { 'email_from': keepalived.KEEPALIVED_EMAIL_FROM, 'router_id': keepalived.KEEPALIVED_ROUTER_ID, 'ha_device_name': ha_device_name, 'ex_device_name': ex_device_name, 'external_device_cidr': external_device_cidr, 'internal_device_name': internal_device_name, 'internal_device_cidr': internal_device_cidr, 'floating_ip_cidr': floating_ip_cidr, 'default_gateway_ip': default_gateway_ip, 'int_port_ipv6': int_port_ipv6, 'ex_port_ipv6': ex_port_ipv6, 'extra_subnet_cidr': extra_subnet_cidr, }
def migrate_centralized_floating_ip(self, fip, interface_name, device): # Remove the centralized fip first and then add fip to the host ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) self.floating_ip_removed_dist(ip_cidr) # Now add the floating_ip to the current host self.floating_ip_added_dist(fip, ip_cidr)
def test_ip_to_cidr_ipv6_prefix(self): self.assertEqual('::1/64', utils.ip_to_cidr('::1', 64))
def test_north_south_traffic(self): # This function creates an external network which is connected to # central_bridge and spawns an external_vm on it. # The external_vm is configured with the gateway_ip (both v4 & v6 # addresses) of external subnet. Later, it creates a tenant router, # a tenant network and two tenant subnets (v4 and v6). The tenant # router is associated with tenant network and external network to # provide north-south connectivity to the VMs. # We validate the following in this testcase. # 1. SNAT support: using ping from tenant VM to external_vm # 2. Floating IP support: using ping from external_vm to VM floating ip # 3. IPv6 ext connectivity: using ping6 from tenant vm to external_vm. tenant_id = uuidutils.generate_uuid() ext_net, ext_sub = self._create_external_network_and_subnet(tenant_id) external_vm = self._create_external_vm(ext_net, ext_sub) # Create an IPv6 subnet in the external network v6network = self.useFixture( ip_network.ExclusiveIPNetwork( "2001:db8:1234::1", "2001:db8:1234::10", "64")).network ext_v6sub = self.safe_client.create_subnet( tenant_id, ext_net['id'], v6network) router = self.safe_client.create_router(tenant_id, external_network=ext_net['id']) # Configure the gateway_ip of external v6subnet on the external_vm. external_vm.ipv6_cidr = common_utils.ip_to_cidr( ext_v6sub['gateway_ip'], 64) # Configure an IPv6 downstream route to the v6Address of router gw port for fixed_ip in router['external_gateway_info']['external_fixed_ips']: if netaddr.IPNetwork(fixed_ip['ip_address']).version == 6: external_vm.set_default_gateway(fixed_ip['ip_address']) vm = self._create_net_subnet_and_vm( tenant_id, ['20.0.0.0/24', '2001:db8:aaaa::/64'], self.environment.hosts[1], router) # ping external vm to test snat vm.block_until_ping(external_vm.ip) fip = self.safe_client.create_floatingip( tenant_id, ext_net['id'], vm.ip, vm.neutron_port['id']) # ping floating ip from external vm external_vm.block_until_ping(fip['floating_ip_address']) # Verify VM is able to reach the router interface. vm.block_until_ping(vm.gateway_ipv6) # Verify north-south connectivity using ping6 to external_vm. vm.block_until_ping(external_vm.ipv6) # Now let's remove and create again phys bridge and check connectivity # once again br_phys = self.environment.hosts[0].br_phys br_phys.destroy() br_phys.create() self.environment.hosts[0].connect_to_central_network_via_vlans( br_phys) # ping floating ip from external vm external_vm.block_until_ping(fip['floating_ip_address']) # Verify VM is able to reach the router interface. vm.block_until_ping(vm.gateway_ipv6) # Verify north-south connectivity using ping6 to external_vm. vm.block_until_ping(external_vm.ipv6)
def test_ip_to_cidr_ipv6_default(self): self.assertEqual('::1/128', utils.ip_to_cidr('::1'))
def test_ip_to_cidr_ipv4_netaddr(self): ip_address = netaddr.IPAddress('15.1.2.3') self.assertEqual('15.1.2.3/32', utils.ip_to_cidr(ip_address))
def add_floating_ip(self, fip, interface_name, device): fip_ip = fip['floating_ip_address'] ip_cidr = common_utils.ip_to_cidr(fip_ip) self._add_vip(ip_cidr, interface_name) return n_consts.FLOATINGIP_STATUS_ACTIVE
def test_floating_ip_added_dist(self, mock_add_ip_rule, mIPDevice, mock_adv_notif): router = mock.MagicMock() ri = self._create_router(router) ri.ex_gw_port = ri.router['gw_port'] ext_net_id = _uuid() subnet_id = _uuid() agent_gw_port = { 'fixed_ips': [{ 'ip_address': '20.0.0.30', 'prefixlen': 24, 'subnet_id': subnet_id }], 'subnets': [{ 'id': subnet_id, 'cidr': '20.0.0.0/24', 'gateway_ip': '20.0.0.1' }], 'id': _uuid(), 'network_id': ext_net_id, 'mac_address': 'ca:fe:de:ad:be:ef' } fip = { 'id': _uuid(), 'host': HOSTNAME, 'floating_ip_address': '15.1.2.3', 'fixed_ip_address': '192.168.0.1', 'floating_network_id': ext_net_id, 'port_id': _uuid() } ri.fip_ns = mock.Mock() ri.fip_ns.agent_gateway_port = agent_gw_port ri.create_dvr_external_gateway_on_agent(ri.ex_gw_port) ri._check_rtr_2_fip_connect = mock.Mock() ri.connect_rtr_2_fip() self.assertTrue(ri.rtr_fip_connect) ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI subnet = lla.LinkLocalAddressPair('169.254.30.42/31') ri.rtr_fip_subnet = subnet ri.fip_ns.local_subnets = mock.Mock() ri.fip_ns.local_subnets.allocate.return_value = subnet ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) ri.floating_ip_added_dist(fip, ip_cidr) mock_add_ip_rule.assert_called_with(namespace=ri.router_namespace.name, ip='192.168.0.1', table=16, priority=FIP_PRI) ri.fip_ns.local_subnets.allocate.assert_not_called() # Validate that fip_ns.local_subnets is called when # ri.rtr_fip_subnet is None ri.rtr_fip_subnet = None ri.floating_ip_added_dist(fip, ip_cidr) mock_add_ip_rule.assert_called_with(namespace=ri.router_namespace.name, ip='192.168.0.1', table=16, priority=FIP_PRI) ri.fip_ns.local_subnets.allocate.assert_called_once_with(ri.router_id)
def test_ip_to_cidr_ipv4_prefix(self): self.assertEqual('15.1.2.3/24', utils.ip_to_cidr('15.1.2.3', 24))
def connect_namespace_to_control_network(self): self.host_port = self._connect_ovs_port( common_utils.ip_to_cidr(self.local_ip, 24)) self.host_port.link.set_up()
def _port_first_ip_cidr(port): fixed_ip = port['fixed_ips'][0] return common_utils.ip_to_cidr(fixed_ip['ip_address'], fixed_ip['prefixlen'])
def add_floating_ip(self, fip, interface_name, device): # Special Handling for DVR - update FIP namespace ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address']) self.floating_ip_added_dist(fip, ip_cidr) return l3_constants.FLOATINGIP_STATUS_ACTIVE
def _ip_prefix_arg(self, direction, ip_prefix): if not (ip_prefix): return [] args = ['-%s' % direction, '%s' % utils.ip_to_cidr(ip_prefix)] return args
def connect_namespace_to_control_network(self): LOG.info('%s(): caller(): %s', log_utils.get_fname(1), log_utils.get_fname(2)) self.host_port = self._connect_ovs_port( common_utils.ip_to_cidr(self.local_ip, 24) ) self.host_port.link.set_up()
def test_ip_to_cidr_ipv4_default(self): self.assertEqual('15.1.2.3/32', utils.ip_to_cidr('15.1.2.3'))