diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py index f7434eba8ca..a3b5e34bd1f 100644 --- a/neutron/agent/l3_agent.py +++ b/neutron/agent/l3_agent.py @@ -1150,6 +1150,12 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, if ri.router['distributed']: self.floating_ip_removed_dist(ri, ip_cidr) + def _get_router_cidrs(self, ri, device): + if ri.is_ha: + return set(self._ha_get_existing_cidrs(ri, device.name)) + else: + return set([addr['cidr'] for addr in device.addr.list()]) + def process_router_floating_ip_addresses(self, ri, ex_gw_port): """Configure IP addresses on router's external gateway interface. @@ -1166,7 +1172,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, device = ip_lib.IPDevice(interface_name, self.root_helper, namespace=ri.ns_name) - existing_cidrs = set([addr['cidr'] for addr in device.addr.list()]) + existing_cidrs = self._get_router_cidrs(ri, device) new_cidrs = set() # Loop once to ensure that floating ips are configured. diff --git a/neutron/agent/l3_ha_agent.py b/neutron/agent/l3_ha_agent.py index adecf191e8c..75f5658bf2e 100644 --- a/neutron/agent/l3_ha_agent.py +++ b/neutron/agent/l3_ha_agent.py @@ -179,6 +179,10 @@ class AgentMixin(object): instance = ri.keepalived_manager.config.get_instance(ri.ha_vr_id) instance.remove_vips_vroutes_by_interface(interface) + def _ha_get_existing_cidrs(self, ri, interface_name): + instance = ri.keepalived_manager.config.get_instance(ri.ha_vr_id) + return instance.get_existing_vip_ip_addresses(interface_name) + def _add_keepalived_notifiers(self, ri): callback = self._get_metadata_proxy_callback(ri.router_id) pm = self._get_metadata_proxy_process_manager(ri.router_id, ri.ns_name) diff --git a/neutron/agent/linux/keepalived.py b/neutron/agent/linux/keepalived.py index 401a922ac45..12dac4d4af8 100644 --- a/neutron/agent/linux/keepalived.py +++ b/neutron/agent/linux/keepalived.py @@ -179,6 +179,10 @@ class KeepalivedInstance(object): self.vips = [vip for vip in self.vips if vip.ip_address != ip_address] + def get_existing_vip_ip_addresses(self, interface_name): + return [vip.ip_address for vip in self.vips + if vip.interface_name == interface_name] + def _build_track_interface_config(self): return itertools.chain( [' track_interface {'], diff --git a/neutron/tests/unit/agent/linux/test_keepalived.py b/neutron/tests/unit/agent/linux/test_keepalived.py index 5dfe0dc0fdf..c29ee2dd6a2 100644 --- a/neutron/tests/unit/agent/linux/test_keepalived.py +++ b/neutron/tests/unit/agent/linux/test_keepalived.py @@ -187,6 +187,12 @@ vrrp_instance VR_2 { config.reset() self.assertEqual('', config.get_config_str()) + def test_get_existing_vip_ip_addresses_returns_list(self): + config = self._get_config() + instance = config.get_instance(1) + current_vips = sorted(instance.get_existing_vip_ip_addresses('eth2')) + self.assertEqual(['192.168.2.0/24', '192.168.3.0/24'], current_vips) + class KeepalivedStateExceptionTestCase(base.BaseTestCase): def test_state_exception(self): diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 2d298a750bd..87172969fd2 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -1144,6 +1144,27 @@ class TestBasicRouterOperations(base.BaseTestCase): ) self._test_process_router_floating_ip_addresses_add(ri, agent) + def test_get_router_cidrs_returns_cidrs(self): + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + ri = mock.MagicMock() + ri.is_ha = False + addresses = ['15.1.2.2/24', '15.1.2.3/32'] + device = mock.MagicMock() + device.addr.list.return_value = [{'cidr': addresses[0]}, + {'cidr': addresses[1]}] + self.assertEqual(set(addresses), agent._get_router_cidrs(ri, device)) + + def test_get_router_cidrs_returns_ha_cidrs(self): + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + ri = mock.MagicMock() + ri.is_ha = True + device = mock.MagicMock() + device.name.return_value = 'eth2' + addresses = ['15.1.2.2/24', '15.1.2.3/32'] + agent._ha_get_existing_cidrs = mock.MagicMock() + agent._ha_get_existing_cidrs.return_value = addresses + self.assertEqual(set(addresses), agent._get_router_cidrs(ri, device)) + # TODO(mrsmith): refactor for DVR cases @mock.patch('neutron.agent.linux.ip_lib.IPDevice') def test_process_router_floating_ip_addresses_remove(self, IPDevice):