test-network: wait for the link is activated

This fixes the following race:
1. when a dummy interface is created, it is initially down state,
2. hence, wait_operstate() may pass before the link is activated,
3. and the ip command bring up the interface before the activation,
4. and networkd activates, that is, brings down the interface,
5. thus, next wait_operstate() timedout, as it waits for the interface up.

To fix the race, let's wait the link is activated, before enter the loop
of wait_operstate().

Fixes #22267.
This commit is contained in:
Yu Watanabe
2022-01-28 07:02:03 +09:00
parent b67f3d73b0
commit cfbdc4387f
@@ -594,6 +594,21 @@ class Utilities():
def check_link_attr(self, *args):
self.assertEqual(read_link_attr(*args[:-1]), args[-1]);
def wait_activated(self, link, state='down', timeout=20, fail_assert=True):
# wait for the interface is activated.
invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
needle = f'{link}: Bringing link {state}'
flag = state.upper()
for iteration in range(timeout+1):
output = check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)
if needle in output and flag in check_output(f'ip link show {link}'):
return True
if iteration < timeout:
time.sleep(1)
if fail_assert:
self.fail(f'Timed out waiting for {link} activated.')
return False
def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
"""Wait for the link to reach the specified operstate and/or setup state.
@@ -3067,6 +3082,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
expect_up = initial_up
next_up = not expect_up
if test.endswith('down'):
self.wait_activated('test1')
for iteration in range(4):
with self.subTest(iteration=iteration, expect_up=expect_up):
operstate = 'routable' if expect_up else 'off'
@@ -3104,6 +3122,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
copy_unit_to_networkd_unit_path(*units, dropins=False)
start_networkd()
if policy.endswith('down'):
self.wait_activated('test1')
if policy.endswith('down') or policy == 'manual':
self.wait_operstate('test1', 'off', setup_state='configuring')
else: