diff --git a/neutron/agent/l3/dvr_fip_ns.py b/neutron/agent/l3/dvr_fip_ns.py index f4a4f4c7eb3..776ca9e8d74 100644 --- a/neutron/agent/l3/dvr_fip_ns.py +++ b/neutron/agent/l3/dvr_fip_ns.py @@ -230,7 +230,8 @@ class FipNamespace(namespaces.Namespace): ipd.route.add_gateway(gw_ip) def _add_cidr_to_device(self, device, ip_cidr): - device.addr.add(ip_cidr, add_broadcast=False) + if not device.addr.list(to=ip_cidr): + device.addr.add(ip_cidr, add_broadcast=False) def create_rtr_2_fip_link(self, ri): """Create interface between router and Floating IP namespace.""" @@ -244,14 +245,13 @@ class FipNamespace(namespaces.Namespace): ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id) rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair() rtr_2_fip_dev = ip_lib.IPDevice(rtr_2_fip_name, namespace=ri.ns_name) + fip_2_rtr_dev = ip_lib.IPDevice(fip_2_rtr_name, namespace=fip_ns_name) if not rtr_2_fip_dev.exists(): ip_wrapper = ip_lib.IPWrapper(namespace=ri.ns_name) rtr_2_fip_dev, fip_2_rtr_dev = ip_wrapper.add_veth(rtr_2_fip_name, fip_2_rtr_name, fip_ns_name) - self._add_cidr_to_device(rtr_2_fip_dev, str(rtr_2_fip)) - self._add_cidr_to_device(fip_2_rtr_dev, str(fip_2_rtr)) mtu = (self.agent_conf.network_device_mtu or ri.get_ex_gw_port().get('mtu')) if mtu: @@ -260,6 +260,9 @@ class FipNamespace(namespaces.Namespace): rtr_2_fip_dev.link.set_up() fip_2_rtr_dev.link.set_up() + self._add_cidr_to_device(rtr_2_fip_dev, str(rtr_2_fip)) + self._add_cidr_to_device(fip_2_rtr_dev, str(fip_2_rtr)) + # add default route for the link local interface rtr_2_fip_dev.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL) diff --git a/neutron/tests/unit/agent/l3/test_dvr_fip_ns.py b/neutron/tests/unit/agent/l3/test_dvr_fip_ns.py index 5bdb8771d38..e7d160e1016 100644 --- a/neutron/tests/unit/agent/l3/test_dvr_fip_ns.py +++ b/neutron/tests/unit/agent/l3/test_dvr_fip_ns.py @@ -218,7 +218,8 @@ class TestDvrFipNs(base.BaseTestCase): @mock.patch.object(ip_lib, 'IPWrapper') @mock.patch.object(ip_lib, 'IPDevice') - def _test_create_rtr_2_fip_link(self, dev_exists, IPDevice, IPWrapper): + def _test_create_rtr_2_fip_link(self, dev_exists, addr_exists, + IPDevice, IPWrapper): ri = mock.Mock() ri.router_id = _uuid() ri.rtr_fip_subnet = None @@ -231,11 +232,13 @@ class TestDvrFipNs(base.BaseTestCase): self.fip_ns.local_subnets = allocator = mock.Mock() pair = lla.LinkLocalAddressPair('169.254.31.28/31') allocator.allocate.return_value = pair + addr_pair = pair.get_pair() ip_wrapper = IPWrapper() self.conf.network_device_mtu = 2000 ip_wrapper.add_veth.return_value = (IPDevice(), IPDevice()) device = IPDevice() device.exists.return_value = dev_exists + device.addr.list.return_value = addr_exists self.fip_ns.create_rtr_2_fip_link(ri) @@ -248,14 +251,23 @@ class TestDvrFipNs(base.BaseTestCase): self.assertEqual(2, device.link.set_mtu.call_count) self.assertEqual(2, device.link.set_up.call_count) + if not addr_exists: + expected = [mock.call(str(addr_pair[0]), add_broadcast=False), + mock.call(str(addr_pair[1]), add_broadcast=False)] + device.addr.add.assert_has_calls(expected) + self.assertEqual(2, device.addr.add.call_count) + device.route.add_gateway.assert_called_once_with( '169.254.31.29', table=16) def test_create_rtr_2_fip_link(self): - self._test_create_rtr_2_fip_link(False) + self._test_create_rtr_2_fip_link(False, False) def test_create_rtr_2_fip_link_already_exists(self): - self._test_create_rtr_2_fip_link(True) + self._test_create_rtr_2_fip_link(True, False) + + def test_create_rtr_2_fip_link_and_addr_already_exist(self): + self._test_create_rtr_2_fip_link(True, True) @mock.patch.object(ip_lib, 'IPDevice') def _test_scan_fip_ports(self, ri, ip_list, IPDevice):