def generate_dvr_router_info(self, enable_ha=False, enable_snat=False, agent=None, extra_routes=False, **kwargs): if not agent: agent = self.agent router = l3_test_common.prepare_router_data( enable_snat=enable_snat, enable_floating_ip=True, enable_ha=enable_ha, extra_routes=extra_routes, num_internal_ports=2, **kwargs) internal_ports = router.get(l3_constants.INTERFACE_KEY, []) router['distributed'] = True router['gw_port_host'] = agent.conf.host router['gw_port'][portbindings.HOST_ID] = agent.conf.host floating_ip = router['_floatingips'][0] floating_ip['floating_network_id'] = router['gw_port']['network_id'] floating_ip['host'] = agent.conf.host floating_ip['port_id'] = internal_ports[0]['id'] floating_ip['status'] = 'ACTIVE' self._add_snat_port_info_to_router(router, internal_ports) # FIP has a dependency on external gateway. So we need to create # the snat_port info and fip_agent_gw_port_info irrespective of # the agent type the dvr supports. The namespace creation is # dependent on the agent_type. external_gw_port = router['gw_port'] self._add_fip_agent_gw_port_info_to_router(router, external_gw_port) return router
def test_get_floating_agent_gw_interfaces(self): fake_network_id = _uuid() subnet_id = _uuid() agent_gateway_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(), portbindings.HOST_ID: 'myhost', 'device_owner': lib_constants.DEVICE_OWNER_AGENT_GW, 'network_id': fake_network_id, 'mac_address': 'ca:fe:de:ad:be:ef'}] ) router = l3_test_common.prepare_router_data(enable_snat=True) router[n_const.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port router['distributed'] = True agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) self.assertEqual( agent_gateway_port[0], ri.get_floating_agent_gw_interface(fake_network_id))
def generate_router_info(self, enable_ha, ip_version=constants.IP_VERSION_4, extra_routes=True, enable_fip=True, enable_snat=True, num_internal_ports=1, dual_stack=False, enable_gw=True, v6_ext_gw_with_sub=True, enable_pf_floating_ip=False, qos_policy_id=None): if ip_version == constants.IP_VERSION_6 and not dual_stack: enable_snat = False enable_fip = False extra_routes = False return l3_test_common.prepare_router_data(ip_version=ip_version, enable_snat=enable_snat, num_internal_ports=( num_internal_ports), enable_floating_ip=( enable_fip), enable_ha=enable_ha, extra_routes=extra_routes, dual_stack=dual_stack, enable_gw=enable_gw, v6_ext_gw_with_sub=( v6_ext_gw_with_sub), enable_pf_floating_ip=( enable_pf_floating_ip), qos_policy_id=qos_policy_id)
def test__set_subnet_arp_info(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) router['distributed'] = True self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) ports = ri.router.get(lib_constants.INTERFACE_KEY, []) subnet_id = l3_test_common.get_subnet_id(ports[0]) test_ports = [{'mac_address': '00:11:22:33:44:55', 'device_owner': lib_constants.DEVICE_OWNER_DHCP, 'fixed_ips': [{'ip_address': '1.2.3.4', 'prefixlen': 24, 'subnet_id': subnet_id}]}] self.plugin_api.get_ports_by_subnet.return_value = test_ports # Test basic case ports[0]['subnets'] = [{'id': subnet_id, 'cidr': '1.2.3.0/24'}] with mock.patch.object(ri, '_process_arp_cache_for_internal_port') as parp: ri._set_subnet_arp_info(subnet_id) self.assertEqual(1, parp.call_count) self.mock_ip_dev.neigh.add.assert_called_once_with( '1.2.3.4', '00:11:22:33:44:55') # Test negative case router['distributed'] = False ri._set_subnet_arp_info(subnet_id) self.mock_ip_dev.neigh.add.never_called()
def test_process_router_dist_floating_ip_add(self): fake_floatingips = {'floatingips': [ {'id': _uuid(), 'host': HOSTNAME, 'floating_ip_address': '15.1.2.3', 'fixed_ip_address': '192.168.0.1', 'floating_network_id': mock.sentinel.ext_net_id, 'port_id': _uuid()}, {'id': _uuid(), 'host': 'some-other-host', 'floating_ip_address': '15.1.2.4', 'fixed_ip_address': '192.168.0.10', 'floating_network_id': mock.sentinel.ext_net_id, 'port_id': _uuid()}]} router = l3_test_common.prepare_router_data(enable_snat=True) router[lib_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips'] router['distributed'] = True agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) ri.iptables_manager.ipv4['nat'] = mock.MagicMock() ri.dist_fip_count = 0 fip_ns = agent.get_fip_ns(mock.sentinel.ext_net_id) subnet_id = _uuid() fip_ns.agent_gateway_port = ( {'fixed_ips': [{'ip_address': '20.0.0.30', 'subnet_id': subnet_id}], 'subnets': [{'id': subnet_id, 'cidr': '20.0.0.0/24', 'gateway_ip': '20.0.0.1'}], 'id': _uuid(), 'network_id': _uuid(), 'mac_address': 'ca:fe:de:ad:be:ef'} )
def test__set_subnet_arp_info(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) router['distributed'] = True ri = dvr_router.DvrLocalRouter( agent, HOSTNAME, router['id'], router, **self.ri_kwargs) ports = ri.router.get(l3_constants.INTERFACE_KEY, []) subnet_id = l3_test_common.get_subnet_id(ports[0]) test_ports = [{'mac_address': '00:11:22:33:44:55', 'device_owner': 'network:dhcp', 'fixed_ips': [{'ip_address': '1.2.3.4', 'prefixlen': 24, 'subnet_id': subnet_id}]}] self.plugin_api.get_ports_by_subnet.return_value = test_ports # Test basic case ports[0]['subnets'] = [{'id': subnet_id, 'cidr': '1.2.3.0/24'}] ri._set_subnet_arp_info(subnet_id) self.mock_ip_dev.neigh.add.assert_called_once_with( '1.2.3.4', '00:11:22:33:44:55') # Test negative case router['distributed'] = False ri._set_subnet_arp_info(subnet_id) self.mock_ip_dev.neigh.add.never_called()
def test_add_centralized_floatingip(self, super_add_centralized_floatingip): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.conf.agent_mode = lib_constants.L3_AGENT_MODE_DVR_SNAT router = l3_test_common.prepare_router_data(num_internal_ports=2) router['gw_port_host'] = HOSTNAME self.mock_driver.unplug.reset_mock() self._set_ri_kwargs(agent, router['id'], router) fip = {'id': _uuid()} fip_cidr = '11.22.33.44/24' ri = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs) ri.is_router_master = mock.Mock(return_value=False) ri._add_vip = mock.Mock() interface_name = ri.get_snat_external_device_interface_name( ri.get_ex_gw_port()) ri.add_centralized_floatingip(fip, fip_cidr) ri._add_vip.assert_called_once_with(fip_cidr, interface_name) super_add_centralized_floatingip.assert_not_called() ri1 = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs) ri1.is_router_master = mock.Mock(return_value=True) ri1._add_vip = mock.Mock() interface_name = ri1.get_snat_external_device_interface_name( ri1.get_ex_gw_port()) ri1.add_centralized_floatingip(fip, fip_cidr) ri1._add_vip.assert_called_once_with(fip_cidr, interface_name) super_add_centralized_floatingip.assert_called_once_with(fip, fip_cidr)
def _setup_test_for_arp_entry_cache(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) router['distributed'] = True self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) subnet_id = l3_test_common.get_subnet_id( ri.router[lib_constants.INTERFACE_KEY][0]) return ri, subnet_id
def test_add_arp_entry_no_routerinfo(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) subnet_id = l3_test_common.get_subnet_id( router[lib_constants.INTERFACE_KEY][0]) arp_table = {'ip_address': '1.7.23.11', 'mac_address': '00:11:22:33:44:55', 'subnet_id': subnet_id} payload = {'arp_table': arp_table, 'router_id': router['id']} agent.add_arp_entry(None, payload)
def test_external_gateway_removed_ext_gw_port_and_fip(self): self.conf.set_override('state_path', '/tmp') agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.conf.agent_mode = 'dvr' router = l3_test_common.prepare_router_data(num_internal_ports=2) router['gw_port_host'] = HOSTNAME self.mock_driver.unplug.reset_mock() external_net_id = router['gw_port']['network_id'] ri = dvr_router.DvrLocalRouter( agent, HOSTNAME, router['id'], router, **self.ri_kwargs) ri.remove_floating_ip = mock.Mock() agent._fetch_external_net_id = mock.Mock(return_value=external_net_id) ri.ex_gw_port = ri.router['gw_port'] del ri.router['gw_port'] ri.fip_ns = None nat = ri.iptables_manager.ipv4['nat'] nat.clear_rules_by_tag = mock.Mock() nat.add_rule = mock.Mock() ri.fip_ns = agent.get_fip_ns(external_net_id) subnet_id = _uuid() ri.fip_ns.agent_gateway_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': external_net_id, 'mac_address': 'ca:fe:de:ad:be:ef'} vm_floating_ip = '19.4.4.2' ri.floating_ips_dict[vm_floating_ip] = FIP_PRI ri.dist_fip_count = 1 ri.rtr_fip_subnet = ri.fip_ns.local_subnets.allocate(ri.router_id) _, fip_to_rtr = ri.rtr_fip_subnet.get_pair() self.mock_ip.get_devices.return_value = [ l3_test_common.FakeDev(ri.fip_ns.get_ext_device_name(_uuid()))] self.mock_ip_dev.addr.list.return_value = [ {'cidr': vm_floating_ip + '/32'}, {'cidr': '19.4.4.1/24'}] self.device_exists.return_value = True ri.external_gateway_removed( ri.ex_gw_port, ri.get_external_device_name(ri.ex_gw_port['id'])) ri.remove_floating_ip.assert_called_once_with(self.mock_ip_dev, '19.4.4.2/32')
def test_ipv6_router_advts_after_router_state_change(self): # Schedule router to l3 agent, and then add router gateway. Verify # that router gw interface is configured to receive Router Advts. router_info = l3_test_common.prepare_router_data( enable_snat=True, enable_ha=True, dual_stack=True, enable_gw=False) router = self.manage_router(self.agent, router_info) common_utils.wait_until_true(lambda: router.ha_state == 'master') _ext_dev_name, ex_port = l3_test_common.prepare_ext_gw_test( mock.Mock(), router) router_info['gw_port'] = ex_port router.process(self.agent) self._assert_ipv6_accept_ra(router)
def test_add_arp_entry(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) router['distributed'] = True subnet_id = l3_test_common.get_subnet_id( router[lib_constants.INTERFACE_KEY][0]) arp_table = {'ip_address': '1.7.23.11', 'mac_address': '00:11:22:33:44:55', 'subnet_id': subnet_id} payload = {'arp_table': arp_table, 'router_id': router['id']} agent._router_added(router['id'], router) agent.add_arp_entry(None, payload) agent.router_deleted(None, router['id']) self.mock_ip_dev.neigh.add.assert_called_once_with( '1.7.23.11', '00:11:22:33:44:55')
def test_handle_snat_rule_for_centralized_fip( self, _add_snat_rules, _handle_router_snat_rules): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.conf.agent_mode = lib_constants.L3_AGENT_MODE_DVR_SNAT self.mock_driver.unplug.reset_mock() router = l3_test_common.prepare_router_data(enable_floating_ip=True) router['gw_port_host'] = HOSTNAME self._set_ri_kwargs(agent, router['id'], router) ri = dvr_edge_rtr.DvrEdgeRouter(HOSTNAME, **self.ri_kwargs) ri.snat_iptables_manager = mock.MagicMock() ipv4_nat = ri.snat_iptables_manager.ipv4['nat'] interface_name, ex_gw_port = l3_test_common.prepare_ext_gw_test(self, ri) ri._handle_router_snat_rules(ex_gw_port, interface_name) ipv4_nat.add_rule.assert_called_once_with('snat', '-j $float-snat')
def generate_router_info(self, enable_ha, ip_version=4, extra_routes=True, enable_fip=True, enable_snat=True, dual_stack=False, v6_ext_gw_with_sub=True): if ip_version == 6 and not dual_stack: enable_snat = False enable_fip = False extra_routes = False return l3_test_common.prepare_router_data(ip_version=ip_version, enable_snat=enable_snat, enable_floating_ip=enable_fip, enable_ha=enable_ha, extra_routes=extra_routes, dual_stack=dual_stack, v6_ext_gw_with_sub=( v6_ext_gw_with_sub))
def test_dvr_router_add_internal_network_set_arp_cache(self): # Check that, when the router is set up and there are # existing ports on the uplinked subnet, the ARP # cache is properly populated. self.agent.conf.agent_mode = "dvr_snat" router_info = l3_test_common.prepare_router_data() router_info["distributed"] = True expected_neighbor = "35.4.1.10" port_data = { "fixed_ips": [{"ip_address": expected_neighbor}], "mac_address": "fa:3e:aa:bb:cc:dd", "device_owner": DEVICE_OWNER_COMPUTE, } self.agent.plugin_rpc.get_ports_by_subnet.return_value = [port_data] router1 = self.manage_router(self.agent, router_info) internal_device = router1.get_internal_device_name(router_info["_interfaces"][0]["id"]) neighbors = ip_lib.IPDevice(internal_device, router1.ns_name).neigh self.assertEqual(expected_neighbor, neighbors.show(ip_version=4).split()[0])
def _test_ext_gw_updated_dvr_agent_mode(self, host, agent_mode, expected_call_count): router = l3_test_common.prepare_router_data(num_internal_ports=2) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) interface_name, ex_gw_port = l3_test_common.prepare_ext_gw_test(self, ri) ri._external_gateway_added = mock.Mock() # test agent mode = dvr (compute node) router['gw_port_host'] = host agent.conf.agent_mode = agent_mode ri.external_gateway_updated(ex_gw_port, interface_name) # no gateway should be added on dvr node self.assertEqual(expected_call_count, ri._external_gateway_added.call_count)
def _test_ipv6_router_advts_and_fwd_helper(self, state, enable_v6_gw, expected_ra, expected_forwarding): # Schedule router to l3 agent, and then add router gateway. Verify # that router gw interface is configured to receive Router Advts and # IPv6 forwarding is enabled. router_info = l3_test_common.prepare_router_data( enable_snat=True, enable_ha=True, dual_stack=True, enable_gw=False) router = self.manage_router(self.agent, router_info) common_utils.wait_until_true(lambda: router.ha_state == 'master') if state == 'backup': self.fail_ha_router(router) common_utils.wait_until_true(lambda: router.ha_state == 'backup') _ext_dev_name, ex_port = l3_test_common.prepare_ext_gw_test( mock.Mock(), router, dual_stack=enable_v6_gw) router_info['gw_port'] = ex_port router.process() self._assert_ipv6_accept_ra(router, expected_ra) self._assert_ipv6_forwarding(router, expected_forwarding)
def generate_router_info(self, enable_ha, ip_version=4, extra_routes=True, enable_fip=True, enable_snat=True, num_internal_ports=1, dual_stack=False, v6_ext_gw_with_sub=True): if ip_version == 6 and not dual_stack: enable_snat = False enable_fip = False extra_routes = False return l3_test_common.prepare_router_data( ip_version=ip_version, enable_snat=enable_snat, num_internal_ports=(num_internal_ports), enable_floating_ip=enable_fip, enable_ha=enable_ha, extra_routes=extra_routes, dual_stack=dual_stack, v6_ext_gw_with_sub=(v6_ext_gw_with_sub))
def test_remove_centralized_floatingip( self, super_remove_centralized_floatingip): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.conf.agent_mode = lib_constants.L3_AGENT_MODE_DVR_SNAT router = l3_test_common.prepare_router_data(num_internal_ports=2) router['gw_port_host'] = HOSTNAME self.mock_driver.unplug.reset_mock() self._set_ri_kwargs(agent, router['id'], router) fip_cidr = '11.22.33.44/24' ri = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs) ri.is_router_master = mock.Mock(return_value=False) ri._remove_vip = mock.Mock() ri.remove_centralized_floatingip(fip_cidr) ri._remove_vip.assert_called_once_with(fip_cidr) super_remove_centralized_floatingip.assert_not_called() ri1 = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs) ri1.is_router_master = mock.Mock(return_value=True) ri1._remove_vip = mock.Mock() ri1.remove_centralized_floatingip(fip_cidr) ri1._remove_vip.assert_called_once_with(fip_cidr) super_remove_centralized_floatingip.assert_called_once_with(fip_cidr)
def generate_dvr_router_info(self, enable_ha=False, enable_snat=False, enable_gw=True, agent=None, extra_routes=False, **kwargs): if not agent: agent = self.agent router = l3_test_common.prepare_router_data(enable_snat=enable_snat, enable_floating_ip=True, enable_ha=enable_ha, extra_routes=extra_routes, num_internal_ports=2, enable_gw=enable_gw, **kwargs) internal_ports = router.get(l3_constants.INTERFACE_KEY, []) router['distributed'] = True router['gw_port_host'] = agent.conf.host floating_ip = router['_floatingips'][0] floating_ip['host'] = agent.conf.host if enable_gw: external_gw_port = router['gw_port'] router['gw_port'][portbindings.HOST_ID] = agent.conf.host floating_ip['floating_network_id'] = external_gw_port['network_id'] floating_ip['port_id'] = internal_ports[0]['id'] floating_ip['status'] = 'ACTIVE' self._add_snat_port_info_to_router(router, internal_ports) # FIP has a dependency on external gateway. So we need to create # the snat_port info and fip_agent_gw_port_info irrespective of # the agent type the dvr supports. The namespace creation is # dependent on the agent_type. self._add_fip_agent_gw_port_info_to_router(router, external_gw_port) return router
def _test_ipv6_router_advts_and_fwd_helper(self, state, enable_v6_gw, expected_ra, expected_forwarding): # Schedule router to l3 agent, and then add router gateway. Verify # that router gw interface is configured to receive Router Advts and # IPv6 forwarding is enabled. router_info = l3_test_common.prepare_router_data(enable_snat=True, enable_ha=True, dual_stack=True, enable_gw=False) router = self.manage_router(self.agent, router_info) common_utils.wait_until_true(lambda: router.ha_state == 'master') if state == 'backup': self.fail_ha_router(router) common_utils.wait_until_true(lambda: router.ha_state == 'backup') _ext_dev_name, ex_port = l3_test_common.prepare_ext_gw_test( mock.Mock(), router, dual_stack=enable_v6_gw) router_info['gw_port'] = ex_port router.process() self._assert_ipv6_accept_ra(router, expected_ra) # As router is going first to master and than to backup mode, # ipv6_forwarding should be enabled on "all" interface always after # that transition self._assert_ipv6_forwarding(router, expected_forwarding, True)
def test_external_gateway_removed_ext_gw_port_and_fip(self): self.conf.set_override('state_path', '/tmp') agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.conf.agent_mode = 'dvr' router = l3_test_common.prepare_router_data(num_internal_ports=2) router['gw_port_host'] = HOSTNAME self.mock_driver.unplug.reset_mock() external_net_id = router['gw_port']['network_id'] ri = dvr_router.DvrLocalRouter(agent, HOSTNAME, router['id'], router, **self.ri_kwargs) ri.remove_floating_ip = mock.Mock() agent._fetch_external_net_id = mock.Mock(return_value=external_net_id) ri.ex_gw_port = ri.router['gw_port'] del ri.router['gw_port'] ri.fip_ns = None nat = ri.iptables_manager.ipv4['nat'] nat.clear_rules_by_tag = mock.Mock() nat.add_rule = mock.Mock() ri.fip_ns = agent.get_fip_ns(external_net_id) subnet_id = _uuid() ri.fip_ns.agent_gateway_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': external_net_id, 'mac_address': 'ca:fe:de:ad:be:ef' } vm_floating_ip = '19.4.4.2' ri.floating_ips_dict[vm_floating_ip] = FIP_PRI ri.dist_fip_count = 1 ri.rtr_fip_subnet = ri.fip_ns.local_subnets.allocate(ri.router_id) _, fip_to_rtr = ri.rtr_fip_subnet.get_pair() self.mock_ip.get_devices.return_value = [ l3_test_common.FakeDev(ri.fip_ns.get_ext_device_name(_uuid())) ] self.mock_ip_dev.addr.list.return_value = [{ 'cidr': vm_floating_ip + '/32' }, { 'cidr': '19.4.4.1/24' }] self.device_exists.return_value = True ri.external_gateway_removed( ri.ex_gw_port, ri.get_external_device_name(ri.ex_gw_port['id'])) ri.remove_floating_ip.assert_called_once_with(self.mock_ip_dev, '19.4.4.2/32')
def test__set_subnet_arp_info(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = l3_test_common.prepare_router_data(num_internal_ports=2) router['distributed'] = True self._set_ri_kwargs(agent, router['id'], router) ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs) ports = ri.router.get(lib_constants.INTERFACE_KEY, []) subnet_id = l3_test_common.get_subnet_id(ports[0]) ri.router['_snat_router_interfaces'] = [{ 'mac_address': 'fa:16:3e:80:8d:80', 'fixed_ips': [{ 'subnet_id': subnet_id, 'ip_address': '1.2.3.10' }] }] test_ports = [{ 'mac_address': '00:11:22:33:44:55', 'device_owner': lib_constants.DEVICE_OWNER_DHCP, 'fixed_ips': [{ 'ip_address': '1.2.3.4', 'prefixlen': 24, 'subnet_id': subnet_id }], 'allowed_address_pairs': [{ 'ip_address': '10.20.30.40', 'mac_address': '00:11:22:33:44:55' }] }, { 'mac_address': '11:22:33:44:55:66', 'device_owner': lib_constants.DEVICE_OWNER_LOADBALANCER, 'fixed_ips': [{ 'ip_address': '1.2.3.5', 'prefixlen': 24, 'subnet_id': subnet_id }] }, { 'mac_address': '22:33:44:55:66:77', 'device_owner': lib_constants.DEVICE_OWNER_LOADBALANCERV2, 'fixed_ips': [{ 'ip_address': '1.2.3.6', 'prefixlen': 24, 'subnet_id': subnet_id }] }] self.plugin_api.get_ports_by_subnet.return_value = test_ports # Test basic case ports[0]['subnets'] = [{'id': subnet_id, 'cidr': '1.2.3.0/24'}] with mock.patch.object(ri, '_process_arp_cache_for_internal_port') as parp: ri._set_subnet_arp_info(subnet_id) self.assertEqual(1, parp.call_count) self.mock_ip_dev.neigh.add.assert_has_calls([ mock.call('1.2.3.4', '00:11:22:33:44:55'), mock.call('10.20.30.40', '00:11:22:33:44:55'), mock.call('1.2.3.10', 'fa:16:3e:80:8d:80') ]) # Test negative case router['distributed'] = False ri._set_subnet_arp_info(subnet_id) self.mock_ip_dev.neigh.add.never_called()