def _test_external_gateway_action(self, action): router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) internal_cidrs = ['100.0.1.0/24', '200.74.0.0/16'] ex_gw_port = { 'fixed_ips': [{ 'ip_address': '20.0.0.30', 'subnet_id': _uuid() }], 'subnet': { 'gateway_ip': '20.0.0.1' }, 'id': _uuid(), 'network_id': _uuid(), 'mac_address': 'ca:fe:de:ad:be:ef', 'ip_cidr': '20.0.0.30/24' } interface_name = agent.get_external_device_name(ex_gw_port['id']) if action == 'add': self.device_exists.return_value = False ri.router = mock.Mock() ri.router.get.return_value = [{ 'floating_ip_address': '192.168.1.34' }] agent.external_gateway_added(ri, ex_gw_port, interface_name, internal_cidrs) self.assertEqual(self.mock_driver.plug.call_count, 1) self.assertEqual(self.mock_driver.init_l3.call_count, 1) self.send_arp.assert_called_once_with(ri, interface_name, '20.0.0.30') kwargs = { 'preserve_ips': ['192.168.1.34/32'], 'namespace': 'qrouter-' + router_id } self.mock_driver.init_l3.assert_called_with( interface_name, ['20.0.0.30/24'], **kwargs) elif action == 'remove': self.device_exists.return_value = True agent.external_gateway_removed(ri, ex_gw_port, interface_name, internal_cidrs) self.assertEqual(self.mock_driver.unplug.call_count, 1) else: raise Exception("Invalid action %s" % action)
def test_router_removed(self): self.plugin_api.get_external_network_id.return_value = None mock.patch( 'neutron.agent.linux.iptables_manager.IptablesManager').start() router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) ri.router = { 'id': _uuid(), 'admin_state_up': True, 'routes': [], 'external_gateway_info': {}} device = mock.Mock() self.agent.router_info = {router_id: ri} self.agent.devices = [device] self.agent._router_removed(router_id) device.destroy_router.assert_called_once_with(router_id)
def test_router_info_create_with_router(self): id = _uuid() ex_gw_port = {'id': _uuid(), 'network_id': _uuid(), 'fixed_ips': [{'ip_address': '19.4.4.4', 'subnet_id': _uuid()}], 'subnet': {'cidr': '19.4.4.0/24', 'gateway_ip': '19.4.4.1'}} router = { 'id': _uuid(), 'enable_snat': True, 'routes': [], 'gw_port': ex_gw_port} ri = l3_agent.RouterInfo(id, self.conf.root_helper, self.conf.use_namespaces, router) self.assertTrue(ri.ns_name().endswith(id)) self.assertEqual(ri.router, router)
def _test_external_gateway_action(self, action): router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) internal_cidrs = ['100.0.1.0/24', '200.74.0.0/16'] ex_gw_port = { 'fixed_ips': [{ 'ip_address': '20.0.0.30', 'subnet_id': _uuid() }], 'subnet': { 'gateway_ip': '20.0.0.1' }, 'id': _uuid(), 'network_id': _uuid(), 'mac_address': 'ca:fe:de:ad:be:ef', 'ip_cidr': '20.0.0.30/24' } interface_name = agent.get_external_device_name(ex_gw_port['id']) if action == 'add': self.device_exists.return_value = False agent.external_gateway_added(ri, ex_gw_port, interface_name, internal_cidrs) self.assertEqual(self.mock_driver.plug.call_count, 1) self.assertEqual(self.mock_driver.init_l3.call_count, 1) arping_cmd = [ 'arping', '-A', '-U', '-I', interface_name, '-c', self.conf.send_arp_for_ha, '20.0.0.30' ] if self.conf.use_namespaces: self.mock_ip.netns.execute.assert_any_call( arping_cmd, check_exit_code=True) else: self.utils_exec.assert_any_call( check_exit_code=True, root_helper=self.conf.root_helper) elif action == 'remove': self.device_exists.return_value = True agent.external_gateway_removed(ri, ex_gw_port, interface_name, internal_cidrs) self.assertEqual(self.mock_driver.unplug.call_count, 1) else: raise Exception("Invalid action %s" % action)
def _test_arping(self, namespace): if not namespace: self.conf.set_override('use_namespaces', False) router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) floating_ip = '20.0.0.101' interface_name = agent.get_external_device_name(router_id) agent._arping(ri, interface_name, floating_ip) arping_cmd = [ 'arping', '-A', '-I', interface_name, '-c', self.conf.send_arp_for_ha, floating_ip ] self.mock_ip.netns.execute.assert_any_call(arping_cmd, check_exit_code=True)
def test_process_router_interface_removed(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = self._prepare_router_data(num_internal_ports=2) ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) # Process with NAT agent.process_router(ri) orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:] # Add an interface and reprocess del router[l3_constants.INTERFACE_KEY][1] # Reassign the router object to RouterInfo ri.router = router agent.process_router(ri) # For some reason set logic does not work well with # IpTablesRule instances nat_rules_delta = [r for r in orig_nat_rules if r not in ri.iptables_manager.ipv4['nat'].rules] self.assertEqual(len(nat_rules_delta), 1) self._verify_snat_rules(nat_rules_delta, router, negate=True)
def test_process_router_snat_enabled(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = self._prepare_router_data(enable_snat=False) ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) # Process without NAT agent.process_router(ri) orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:] # Reprocess with NAT router['enable_snat'] = True # Reassign the router object to RouterInfo ri.router = router agent.process_router(ri) # For some reason set logic does not work well with # IpTablesRule instances nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules if r not in orig_nat_rules] self.assertEqual(len(nat_rules_delta), 2) self._verify_snat_rules(nat_rules_delta, router)
def test_process_router_interface_added(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = self._prepare_router_data() ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) agent.external_gateway_added = mock.Mock() # Process with NAT agent.process_router(ri) orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:] # Add an interface and reprocess router[l3_constants.INTERFACE_KEY].append({ 'id': _uuid(), 'network_id': _uuid(), 'admin_state_up': True, 'fixed_ips': [{ 'ip_address': '35.4.1.4', 'subnet_id': _uuid() }], 'mac_address': 'ca:fe:de:ad:be:ef', 'subnet': { 'cidr': '35.4.1.0/24', 'gateway_ip': '35.4.1.1' } }) # Reassign the router object to RouterInfo ri.router = router agent.process_router(ri) # For some reason set logic does not work well with # IpTablesRule instances nat_rules_delta = [ r for r in ri.iptables_manager.ipv4['nat'].rules if r not in orig_nat_rules ] self.assertEqual(len(nat_rules_delta), 1) self._verify_snat_rules(nat_rules_delta, router) self.send_arp.assert_called_once()
def _test_routes_updated(self, namespace=True): if not namespace: self.conf.set_override('use_namespaces', False) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) ri.router = {} fake_old_routes = [] fake_new_routes = [{'destination': "110.100.31.0/24", 'nexthop': "10.100.10.30"}, {'destination': "110.100.30.0/24", 'nexthop': "10.100.10.30"}] ri.routes = fake_old_routes ri.router['routes'] = fake_new_routes agent.routes_updated(ri) expected = [['ip', 'route', 'replace', 'to', '110.100.30.0/24', 'via', '10.100.10.30'], ['ip', 'route', 'replace', 'to', '110.100.31.0/24', 'via', '10.100.10.30']] self._check_agent_method_called(agent, expected, namespace) fake_new_routes = [{'destination': "110.100.30.0/24", 'nexthop': "10.100.10.30"}] ri.router['routes'] = fake_new_routes agent.routes_updated(ri) expected = [['ip', 'route', 'delete', 'to', '110.100.31.0/24', 'via', '10.100.10.30']] self._check_agent_method_called(agent, expected, namespace) fake_new_routes = [] ri.router['routes'] = fake_new_routes agent.routes_updated(ri) expected = [['ip', 'route', 'delete', 'to', '110.100.30.0/24', 'via', '10.100.10.30']] self._check_agent_method_called(agent, expected, namespace)
def _test_internal_network_action(self, action): port_id = _uuid() router_id = _uuid() network_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) cidr = '99.0.1.9/24' mac = 'ca:fe:de:ad:be:ef' if action == 'add': self.device_exists.return_value = False agent.internal_network_added(ri, network_id, port_id, cidr, mac) self.assertEqual(self.mock_driver.plug.call_count, 1) self.assertEqual(self.mock_driver.init_l3.call_count, 1) elif action == 'remove': self.device_exists.return_value = True agent.internal_network_removed(ri, port_id, cidr) self.assertEqual(self.mock_driver.unplug.call_count, 1) else: raise Exception("Invalid action %s" % action)
def _test_routing_table_update(self, namespace): if not namespace: self.conf.set_override('use_namespaces', False) router_id = _uuid() ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, self.conf.use_namespaces, None) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) fake_route1 = {'destination': '135.207.0.0/16', 'nexthop': '1.2.3.4'} fake_route2 = { 'destination': '135.207.111.111/32', 'nexthop': '1.2.3.4' } agent._update_routing_table(ri, 'replace', fake_route1) expected = [[ 'ip', 'route', 'replace', 'to', '135.207.0.0/16', 'via', '1.2.3.4' ]] self._check_agent_method_called(agent, expected, namespace) agent._update_routing_table(ri, 'delete', fake_route1) expected = [[ 'ip', 'route', 'delete', 'to', '135.207.0.0/16', 'via', '1.2.3.4' ]] self._check_agent_method_called(agent, expected, namespace) agent._update_routing_table(ri, 'replace', fake_route2) expected = [[ 'ip', 'route', 'replace', 'to', '135.207.111.111/32', 'via', '1.2.3.4' ]] self._check_agent_method_called(agent, expected, namespace) agent._update_routing_table(ri, 'delete', fake_route2) expected = [[ 'ip', 'route', 'delete', 'to', '135.207.111.111/32', 'via', '1.2.3.4' ]] self._check_agent_method_called(agent, expected, namespace)
def _prepare_router_data(self, enable_snat=None): router_id = _uuid() ex_gw_port = {'id': _uuid(), 'network_id': _uuid(), 'fixed_ips': [{'ip_address': '172.24.4.2', 'subnet_id': _uuid()}], 'subnet': {'cidr': '172.24.4.0/24', 'gateway_ip': '172.24.4.1'}, 'ip_cidr': '172.24.4.226/28'} int_ports = [] router = { 'id': router_id, l3_constants.INTERFACE_KEY: int_ports, 'routes': [], 'gw_port': ex_gw_port} if enable_snat is not None: router['enable_snat'] = enable_snat ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) return ri
def test_process_router(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent.process_router_floating_ips = mock.Mock() router = self._prepare_router_data() fake_floatingips1 = {'floatingips': [ {'id': _uuid(), 'floating_ip_address': '8.8.8.8', 'fixed_ip_address': '7.7.7.7', 'port_id': _uuid()}]} ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) agent.process_router(ri) ex_gw_port = agent._get_ex_gw_port(ri) agent.process_router_floating_ips.assert_called_with(ri, ex_gw_port) agent.process_router_floating_ips.reset_mock() # remap floating IP to a new fixed ip fake_floatingips2 = copy.deepcopy(fake_floatingips1) fake_floatingips2['floatingips'][0]['fixed_ip_address'] = '7.7.7.8' router[l3_constants.FLOATINGIP_KEY] = fake_floatingips2['floatingips'] agent.process_router(ri) ex_gw_port = agent._get_ex_gw_port(ri) agent.process_router_floating_ips.assert_called_with(ri, ex_gw_port) agent.process_router_floating_ips.reset_mock() # remove just the floating ips del router[l3_constants.FLOATINGIP_KEY] agent.process_router(ri) ex_gw_port = agent._get_ex_gw_port(ri) agent.process_router_floating_ips.assert_called_with(ri, ex_gw_port) agent.process_router_floating_ips.reset_mock() # now no ports so state is torn down del router[l3_constants.INTERFACE_KEY] del router['gw_port'] agent.process_router(ri) self.send_arp.assert_called_once() self.assertFalse(agent.process_router_floating_ips.called)
def test_handle_router_snat_rules_add_rules(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) ri = l3_agent.RouterInfo(_uuid(), self.conf.root_helper, self.conf.use_namespaces, None) ex_gw_port = {'fixed_ips': [{'ip_address': '192.168.1.4'}]} internal_cidrs = ['10.0.0.0/24'] agent._handle_router_snat_rules(ri, ex_gw_port, internal_cidrs, "iface", "add_rules") nat_rules = map(str, ri.iptables_manager.ipv4['nat'].rules) wrap_name = ri.iptables_manager.wrap_name jump_float_rule = "-A %s-snat -j %s-float-snat" % (wrap_name, wrap_name) internal_net_rule = ("-A %s-snat -s %s -j SNAT --to-source %s") % ( wrap_name, internal_cidrs[0], ex_gw_port['fixed_ips'][0]['ip_address']) self.assertIn(jump_float_rule, nat_rules) self.assertIn(internal_net_rule, nat_rules) self.assertThat(nat_rules.index(jump_float_rule), matchers.LessThan(nat_rules.index(internal_net_rule)))
def test_process_router_floatingip_disabled(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) with mock.patch.object( agent.plugin_rpc, 'update_floatingip_statuses') as mock_update_fip_status: fip_id = _uuid() router = self._prepare_router_data(num_internal_ports=1) router[l3_constants.FLOATINGIP_KEY] = [{ 'id': fip_id, 'floating_ip_address': '8.8.8.8', 'fixed_ip_address': '7.7.7.7', 'port_id': router[l3_constants.INTERFACE_KEY][0]['id'] }] ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) agent.external_gateway_added = mock.Mock() agent.process_router(ri) # Assess the call for putting the floating IP up was performed mock_update_fip_status.assert_called_once_with( mock.ANY, ri.router_id, {fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE}) mock_update_fip_status.reset_mock() # Process the router again, this time without floating IPs router[l3_constants.FLOATINGIP_KEY] = [] ri.router = router agent.process_router(ri) # Assess the call for putting the floating IP up was performed mock_update_fip_status.assert_called_once_with( mock.ANY, ri.router_id, {fip_id: l3_constants.FLOATINGIP_STATUS_DOWN})
def test_process_router_internal_network_added_unexpected_error(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) router = self._prepare_router_data() ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper, self.conf.use_namespaces, router=router) with mock.patch.object( l3_agent.L3NATAgent, 'internal_network_added') as internal_network_added: # raise RuntimeError to simulate that an unexpected exception # occurrs internal_network_added.side_effect = RuntimeError self.assertRaises(RuntimeError, agent.process_router, ri) self.assertNotIn( router[l3_constants.INTERFACE_KEY][0], ri.internal_ports) # The unexpected exception has been fixed manually internal_network_added.side_effect = None # _sync_routers_task finds out that _rpc_loop failed to process the # router last time, it will retry in the next run. agent.process_router(ri) # We were able to add the port to ri.internal_ports self.assertIn( router[l3_constants.INTERFACE_KEY][0], ri.internal_ports)
def test_spawn_metadata_proxy(self): router_id = _uuid() metadata_port = 8080 ip_class_path = 'neutron.agent.linux.ip_lib.IPWrapper' cfg.CONF.set_override('metadata_port', metadata_port) cfg.CONF.set_override('log_file', 'test.log') cfg.CONF.set_override('debug', True) router_info = l3_agent.RouterInfo( router_id, cfg.CONF.root_helper, cfg.CONF.use_namespaces, None ) self.external_process_p.stop() try: with mock.patch(ip_class_path) as ip_mock: self.agent._spawn_metadata_proxy(router_info) ip_mock.assert_has_calls([ mock.call( 'sudo', 'qrouter-' + router_id ), mock.call().netns.execute([ 'neutron-ns-metadata-proxy', mock.ANY, mock.ANY, '--router_id=%s' % router_id, mock.ANY, '--metadata_port=%s' % metadata_port, '--debug', '--log-file=neutron-ns-metadata-proxy-%s.log' % router_id ]) ]) finally: self.external_process_p.start()
def test_router_info_create(self): id = _uuid() ri = l3_agent.RouterInfo(id, self.conf.root_helper, self.conf.use_namespaces, None) self.assertTrue(ri.ns_name().endswith(id))
def _router_added(self, router_id, router): LOG.debug(_("_router_added: %s"), router_id) ri = l3_agent.RouterInfo(router_id, self.root_helper, self.conf.use_namespaces, router) self.router_info[router_id] = ri super(vArmourL3NATAgent, self).process_router_add(ri)
def _prepare_router_data(self, use_namespaces): router = {'id': str(uuid.uuid4()), 'tenant_id': str(uuid.uuid4())} return l3_agent.RouterInfo(router['id'], self.conf.root_helper, use_namespaces, router=router)
def _prepare_router_data(self): router = {'id': str(uuid.uuid4()), 'tenant_id': str(uuid.uuid4())} ns = "ns-" + router['id'] return l3_agent.RouterInfo(router['id'], self.conf.root_helper, router=router, ns_name=ns)