From da3de52c507544c84463a037acac3b2b24a37fe0 Mon Sep 17 00:00:00 2001 From: Erik Colnick Date: Wed, 11 Nov 2015 04:44:42 -0700 Subject: [PATCH] Fix dvr_local_router.floating_ip_added_dist failure after agent restart If DVR is enabled and an l3-agent is restarted, associating a floatingip to an existing vm on the compute node where the l3-agent was restarted will fail. This commit fixes the floating_ip_added_dist method in dvr_local_router.py so that self.rtr_fip_subnet will be created if it is 'None' prior to the attempt to call the get_name() method on it. Change-Id: I860ee3522275f62f393e66853e53ef387598983d CLoses-Bug: #1515341 --- neutron/agent/l3/dvr_local_router.py | 3 +++ .../unit/agent/l3/test_dvr_local_router.py | 24 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py index e02ae7362..8dd789ed3 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -89,6 +89,9 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): priority=rule_pr) #Add routing rule in fip namespace fip_ns_name = self.fip_ns.get_name() + if self.rtr_fip_subnet is None: + self.rtr_fip_subnet = self.fip_ns.local_subnets.allocate( + self.router_id) rtr_2_fip, _ = self.rtr_fip_subnet.get_pair() device = ip_lib.IPDevice(fip_2_rtr_name, namespace=fip_ns_name) device.route.add_route(fip_cidr, str(rtr_2_fip.ip)) diff --git a/neutron/tests/unit/agent/l3/test_dvr_local_router.py b/neutron/tests/unit/agent/l3/test_dvr_local_router.py index 8cb1fb429..fb7baf3fa 100644 --- a/neutron/tests/unit/agent/l3/test_dvr_local_router.py +++ b/neutron/tests/unit/agent/l3/test_dvr_local_router.py @@ -194,14 +194,27 @@ class TestDvrRouterOperations(base.BaseTestCase): 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') + 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 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(ip='192.168.0.1', table=16, priority=FIP_PRI) + ri.fip_ns.local_subnets.allocate.assert_not_called() self.assertEqual(1, ri.dist_fip_count) + + # Validate that fip_ns.local_subnets is called when + # rtr_fip_subnet is None + ri.rtr_fip_subnet = None + ri.floating_ip_added_dist(fip, ip_cidr) + mIPRule().rule.add.assert_called_with(ip='192.168.0.1', + table=16, + priority=FIP_PRI) + ri.fip_ns.local_subnets.allocate.assert_called_once_with(ri.router_id) # TODO(mrsmith): add more asserts @mock.patch.object(ip_lib, 'IPWrapper') @@ -232,15 +245,19 @@ class TestDvrRouterOperations(base.BaseTestCase): ri.fip_ns.agent_gateway_port = agent_gw_port s = lla.LinkLocalAddressPair('169.254.30.42/31') ri.rtr_fip_subnet = s + ri.fip_ns.local_subnets = mock.Mock() ri.floating_ip_removed_dist(fip_cidr) mIPRule().rule.delete.assert_called_with( ip=str(netaddr.IPNetwork(fip_cidr).ip), table=16, priority=FIP_PRI) mIPDevice().route.delete_route.assert_called_with(fip_cidr, str(s.ip)) self.assertFalse(ri.fip_ns.unsubscribe.called) + ri.fip_ns.local_subnets.allocate.assert_not_called() ri.dist_fip_count = 1 - ri.rtr_fip_subnet = lla.LinkLocalAddressPair('15.1.2.3/32') - _, fip_to_rtr = ri.rtr_fip_subnet.get_pair() + s1 = lla.LinkLocalAddressPair('15.1.2.3/32') + ri.rtr_fip_subnet = None + ri.fip_ns.local_subnets.allocate.return_value = s1 + _, fip_to_rtr = s1.get_pair() fip_ns = ri.fip_ns ri.floating_ip_removed_dist(fip_cidr) self.assertTrue(fip_ns.destroyed) @@ -249,6 +266,7 @@ class TestDvrRouterOperations(base.BaseTestCase): mIPDevice().route.delete_gateway.assert_called_once_with( str(fip_to_rtr.ip), table=16) fip_ns.unsubscribe.assert_called_once_with(ri.router_id) + ri.fip_ns.local_subnets.allocate.assert_called_once_with(ri.router_id) def _test_add_floating_ip(self, ri, fip, is_failure): ri._add_fip_addr_to_device = mock.Mock(return_value=is_failure) -- 2.45.2