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 3889b0f214
)
This commit is contained in:
parent
3134048102
commit
44c3ee8cb2
@ -33,6 +33,7 @@ import six
|
|||||||
|
|
||||||
from neutron._i18n import _, _LE, _LW
|
from neutron._i18n import _, _LE, _LW
|
||||||
from neutron.agent.common import config
|
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 iptables_comments as ic
|
||||||
from neutron.agent.linux import utils as linux_utils
|
from neutron.agent.linux import utils as linux_utils
|
||||||
from neutron.common import exceptions as n_exc
|
from neutron.common import exceptions as n_exc
|
||||||
@ -471,7 +472,20 @@ class IptablesManager(object):
|
|||||||
args = ['%s-save' % (cmd,)]
|
args = ['%s-save' % (cmd,)]
|
||||||
if self.namespace:
|
if self.namespace:
|
||||||
args = ['ip', 'netns', 'exec', self.namespace] + args
|
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')
|
all_lines = save_output.split('\n')
|
||||||
commands = []
|
commands = []
|
||||||
# Traverse tables in sorted order for predictable dump output
|
# Traverse tables in sorted order for predictable dump output
|
||||||
|
@ -982,6 +982,20 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
|
|||||||
{'wrap': True, 'top': False, 'rule': '-j DROP',
|
{'wrap': True, 'top': False, 'rule': '-j DROP',
|
||||||
'chain': 'nonexistent'})
|
'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):
|
def test_iptables_failure_with_no_failing_line_number(self):
|
||||||
with mock.patch.object(iptables_manager, "LOG") as log:
|
with mock.patch.object(iptables_manager, "LOG") as log:
|
||||||
# generate Runtime errors on iptables-restore calls
|
# generate Runtime errors on iptables-restore calls
|
||||||
|
Loading…
Reference in New Issue
Block a user