From 9e4b769055d0d4ca136afa0b1865930cc2cec6d7 Mon Sep 17 00:00:00 2001 From: Robert Li Date: Thu, 14 Jan 2016 07:54:29 -0500 Subject: [PATCH] Build socket list right before select call This will make sure the socket list and the interface list are always in sync, and the select call is on the right list of sockets. Co-Authored-By: Dmitry Tantsur Closes-Bug: #1533892 Change-Id: Id6710f4648203b7d476a2a16ea647224baca1bb9 --- ironic_python_agent/netutils.py | 3 +-- ironic_python_agent/tests/unit/test_netutils.py | 9 ++++++++- releasenotes/notes/lldp-loop-fdfa584caf33d847.yaml | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/lldp-loop-fdfa584caf33d847.yaml diff --git a/ironic_python_agent/netutils.py b/ironic_python_agent/netutils.py index ccf73c147..801833a39 100644 --- a/ironic_python_agent/netutils.py +++ b/ironic_python_agent/netutils.py @@ -162,13 +162,12 @@ def _get_lldp_info(interfaces): if not interfaces: return {} - socks = [interface[1] for interface in interfaces] - while interfaces: LOG.info('Waiting on LLDP info for interfaces: %(interfaces)s, ' 'timeout: %(timeout)s', {'interfaces': interfaces, 'timeout': CONF.lldp_timeout}) + socks = [interface[1] for interface in interfaces] # rlist is a list of sockets ready for reading rlist, _, _ = select.select(socks, [], [], CONF.lldp_timeout) if not rlist: diff --git a/ironic_python_agent/tests/unit/test_netutils.py b/ironic_python_agent/tests/unit/test_netutils.py index 2bafff4f7..257a556e4 100644 --- a/ironic_python_agent/tests/unit/test_netutils.py +++ b/ironic_python_agent/tests/unit/test_netutils.py @@ -113,7 +113,8 @@ class TestNetutils(test_base.BaseTestCase): sock_mock.side_effect = [sock1, sock2] select_mock.side_effect = [ - ([sock1, sock2], [], []), + ([sock1], [], []), + ([sock2], [], []), ] lldp_info = netutils.get_lldp_info(interface_names) @@ -131,6 +132,12 @@ class TestNetutils(test_base.BaseTestCase): # 2 interfaces, 2 calls to enter promiscuous mode, 1 to leave self.assertEqual(6, fcntl_mock.call_count) + expected_calls = [ + mock.call([sock1, sock2], [], [], cfg.CONF.lldp_timeout), + mock.call([sock2], [], [], cfg.CONF.lldp_timeout), + ] + self.assertEqual(expected_calls, select_mock.call_args_list) + @mock.patch('fcntl.ioctl') @mock.patch('select.select') @mock.patch('socket.socket') diff --git a/releasenotes/notes/lldp-loop-fdfa584caf33d847.yaml b/releasenotes/notes/lldp-loop-fdfa584caf33d847.yaml new file mode 100644 index 000000000..343f29bd4 --- /dev/null +++ b/releasenotes/notes/lldp-loop-fdfa584caf33d847.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - Fixed incorrect invocation of "select" which could cause LLDP collection + to hang under certain conditions.