From 44c3ee8cb2bc9adb6f4f95ba3f6be4c3abe344df Mon Sep 17 00:00:00 2001 From: Saverio Proto Date: Mon, 27 Mar 2017 16:39:16 +0200 Subject: [PATCH] Dont try to apply iptables rules in a endless loop If the namespace does not exist the current behavior is to try to apply the iptables rules forever in a endless loop. This fills up the logs on the network node and leads to outage. Change-Id: I628b18a66f9478d7349fa1817431aae2f62ee105 Related-bug: #1623664 Related-bug: #1573073 (cherry picked from commit 3889b0f214fbb1d32531395cff232cf57daf7b17) --- neutron/agent/linux/iptables_manager.py | 16 +++++++++++++++- .../unit/agent/linux/test_iptables_manager.py | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py index a7678909847..3f12e1a6f69 100644 --- a/neutron/agent/linux/iptables_manager.py +++ b/neutron/agent/linux/iptables_manager.py @@ -33,6 +33,7 @@ import six from neutron._i18n import _, _LE, _LW from neutron.agent.common import config +from neutron.agent.linux import ip_lib from neutron.agent.linux import iptables_comments as ic from neutron.agent.linux import utils as linux_utils from neutron.common import exceptions as n_exc @@ -471,7 +472,20 @@ class IptablesManager(object): args = ['%s-save' % (cmd,)] if self.namespace: args = ['ip', 'netns', 'exec', self.namespace] + args - save_output = self.execute(args, run_as_root=True) + try: + save_output = self.execute(args, run_as_root=True) + except RuntimeError: + # We could be racing with a cron job deleting namespaces. + # It is useless to try to apply iptables rules over and + # over again in a endless loop if the namespace does not + # exist. + with excutils.save_and_reraise_exception() as ctx: + if (self.namespace and not + ip_lib.IPWrapper().netns.exists(self.namespace)): + ctx.reraise = False + LOG.error(_LE("Namespace %s was deleted during " + "IPTables operations."), self.namespace) + return [] all_lines = save_output.split('\n') commands = [] # Traverse tables in sorted order for predictable dump output diff --git a/neutron/tests/unit/agent/linux/test_iptables_manager.py b/neutron/tests/unit/agent/linux/test_iptables_manager.py index cb0d8289e50..2d243f06948 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_manager.py +++ b/neutron/tests/unit/agent/linux/test_iptables_manager.py @@ -982,6 +982,20 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): {'wrap': True, 'top': False, 'rule': '-j DROP', 'chain': 'nonexistent'}) + def test_iptables__apply_synchronized_no_namespace(self): + self.execute.side_effect = RuntimeError + # no namespace set so should raise + self.assertRaises(RuntimeError, + self.iptables._apply_synchronized) + self.iptables.namespace = 'test' + with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand.exists', + return_value=True): + self.assertRaises(RuntimeError, + self.iptables._apply_synchronized) + with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand.exists', + return_value=False): + self.assertEqual([], self.iptables._apply_synchronized()) + def test_iptables_failure_with_no_failing_line_number(self): with mock.patch.object(iptables_manager, "LOG") as log: # generate Runtime errors on iptables-restore calls