Stop arping when interface gets deleted
It is possible for an interface to be added to a router, have arping get started for it in a thread, then immediately remove the interface, causing arping errors in the l3-agent log. This concurrent deletion should be handled more gracefully by just logging a warning on the first detection and returning early. Change-Id: I615b60561b3b7f8c950d5f412fb4cdf7877b98f7 Closes-bug: #1696893
This commit is contained in:
parent
b6bd475629
commit
739daaa955
|
@ -1080,15 +1080,23 @@ def _arping(ns_name, iface_name, address, count, log_exception):
|
|||
# platforms (>=Ubuntu 14.04), arping exit code can be 1.
|
||||
ip_wrapper.netns.execute(arping_cmd, extra_ok_codes=[1])
|
||||
except Exception as exc:
|
||||
# Since this is spawned in a thread and executed 2 seconds
|
||||
# apart, the interface may have been deleted while we were
|
||||
# sleeping. Downgrade message to a warning and return early.
|
||||
exists = device_exists(iface_name, namespace=ns_name)
|
||||
msg = _("Failed sending gratuitous ARP to %(addr)s on "
|
||||
"%(iface)s in namespace %(ns)s: %(err)s")
|
||||
logger_method = LOG.exception
|
||||
if not log_exception:
|
||||
if not (log_exception or exists):
|
||||
logger_method = LOG.warning
|
||||
logger_method(msg, {'addr': address,
|
||||
'iface': iface_name,
|
||||
'ns': ns_name,
|
||||
'err': exc})
|
||||
if not exists:
|
||||
LOG.warning("Interface %s might have been deleted "
|
||||
"concurrently", iface_name)
|
||||
return
|
||||
|
||||
|
||||
def send_ip_addr_adv_notif(
|
||||
|
|
|
@ -1683,6 +1683,26 @@ class TestArpPing(TestIPCmdBase):
|
|||
ip_wrapper.netns.execute.assert_any_call(arping_cmd,
|
||||
extra_ok_codes=[1])
|
||||
|
||||
@mock.patch.object(ip_lib, 'IPWrapper')
|
||||
@mock.patch('eventlet.spawn_n')
|
||||
def test_send_ipv4_addr_adv_notif_nodev(self, spawn_n, mIPWrapper):
|
||||
spawn_n.side_effect = lambda f: f()
|
||||
ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name)
|
||||
ip_wrapper.netns.execute.side_effect = RuntimeError
|
||||
ARPING_COUNT = 3
|
||||
address = '20.0.0.1'
|
||||
with mock.patch.object(ip_lib, 'device_exists', return_value=False):
|
||||
ip_lib.send_ip_addr_adv_notif(mock.sentinel.ns_name,
|
||||
mock.sentinel.iface_name,
|
||||
address,
|
||||
ARPING_COUNT)
|
||||
|
||||
# should return early with a single call when ENODEV
|
||||
mIPWrapper.assert_has_calls([
|
||||
mock.call(namespace=mock.sentinel.ns_name),
|
||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=mock.ANY)
|
||||
] * 1)
|
||||
|
||||
@mock.patch('eventlet.spawn_n')
|
||||
def test_no_ipv6_addr_notif(self, spawn_n):
|
||||
ipv6_addr = 'fd00::1'
|
||||
|
|
Loading…
Reference in New Issue