From a43b7cf3abb0a04e73e526aea971463856f0d7eb Mon Sep 17 00:00:00 2001 From: Sridar Kandaswamy Date: Sun, 9 Mar 2014 23:31:28 -0700 Subject: [PATCH] Fix KeyError except on router_info in FW Agent The workflow of creating a firewall when a router without any i/f is present in that tenant causes a KeyError on the FWAgent. The issue occurs as such routers are present in the list of routers returned by get_routers() but are not populated in the router_info dict. Adding a check before accessing the dict to prevent the exception. When an i/f is added to such routers - _router_added processing in the l3agent will populate the router_info dict and the FWAgent also picks this up in that context. Change-Id: I5ea22e88a46e62372a0462e9cb958a08dd9f4c7d Closes-Bug: #1289643 --- .../agents/l3reference/firewall_l3_agent.py | 4 +++ .../l3reference/test_firewall_l3_agent.py | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/neutron/services/firewall/agents/l3reference/firewall_l3_agent.py b/neutron/services/firewall/agents/l3reference/firewall_l3_agent.py index f3158c2805..a3646c6bbf 100644 --- a/neutron/services/firewall/agents/l3reference/firewall_l3_agent.py +++ b/neutron/services/firewall/agents/l3reference/firewall_l3_agent.py @@ -97,6 +97,10 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin): router_info_list = [] # Pick up namespaces for Tenant Routers for rid in router_ids: + # for routers without an interface - get_routers returns + # the router - but this is not yet populated in router_info + if rid not in self.router_info: + continue if self.router_info[rid].use_namespaces: router_ns = self.router_info[rid].ns_name() if router_ns in local_ns_list: diff --git a/neutron/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.py b/neutron/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.py index 9d7f4079b8..0034381056 100644 --- a/neutron/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.py +++ b/neutron/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.py @@ -360,3 +360,33 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase): def test_get_router_info_list_tenant_without_namespace_router_with(self): self._get_router_info_list_without_namespace_helper( router_use_namespaces=True) + + def _get_router_info_list_router_without_router_info_helper(self, + rtr_with_ri): + self.conf.set_override('use_namespaces', True) + # ri.router with associated router_info (ri) + # rtr2 has no router_info + ri = self._prepare_router_data(use_namespaces=True) + rtr2 = {'id': str(uuid.uuid4()), 'tenant_id': ri.router['tenant_id']} + routers = [rtr2] + self.api.router_info = {} + ri_expected = [] + if rtr_with_ri: + self.api.router_info[ri.router_id] = ri + routers.append(ri.router) + ri_expected.append(ri) + with mock.patch.object(ip_lib.IPWrapper, + 'get_namespaces') as mock_get_namespaces: + mock_get_namespaces.return_value = ri.ns_name() + router_info_list = self.api._get_router_info_list_for_tenant( + routers, + ri.router['tenant_id']) + self.assertEqual(ri_expected, router_info_list) + + def test_get_router_info_list_router_without_router_info(self): + self._get_router_info_list_router_without_router_info_helper( + rtr_with_ri=False) + + def test_get_router_info_list_two_routers_one_without_router_info(self): + self._get_router_info_list_router_without_router_info_helper( + rtr_with_ri=True)