]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-network: wait for the link is activated
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 27 Jan 2022 22:02:00 +0000 (07:02 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 27 Jan 2022 22:02:03 +0000 (07:02 +0900)
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.

test/test-network/systemd-networkd-tests.py

index e7a84c7a98e1d20d3993e30193b044e17b9dbc0d..0b17a58d065494e9c8106c51aae559674634794b 100755 (executable)
@@ -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: