From b67f3d73b075346c6e06533111ec8f6b6ac617d7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 06:59:43 +0900 Subject: [PATCH 1/4] test-network: always cleanup the testing environment Previously, if a subtest fail, then the cleanup process does not run, and affects the subsequent tests. --- test/test-network/systemd-networkd-tests.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0233c4dd1f..e7a84c7a98 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3053,7 +3053,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.wait_operstate('test1', 'routable') def _test_activation_policy(self, test): - self.setUp() conffile = '25-activation-policy.network' if test: conffile = f'{conffile}.d/{test}.conf' @@ -3088,15 +3087,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): expect_up = initial_up if always else next_up next_up = not next_up - self.tearDown() - def test_activation_policy(self): for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']: with self.subTest(test=test): + self.setUp() self._test_activation_policy(test) + self.tearDown() def _test_activation_policy_required_for_online(self, policy, required): - self.setUp() conffile = '25-activation-policy.network' units = ['11-dummy.netdev', '12-dummy.netdev', '12-dummy.network', conffile] if policy: @@ -3131,13 +3129,13 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): yesno = 'yes' if expected else 'no' self.assertRegex(output, f'Required For Online: {yesno}') - self.tearDown() - def test_activation_policy_required_for_online(self): for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']: for required in ['yes', 'no', '']: with self.subTest(policy=policy, required=required): + self.setUp() self._test_activation_policy_required_for_online(policy, required) + self.tearDown() def test_domain(self): copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network') From cfbdc4387f97f6c50709c72b924cb53d2128d75c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 07:02:00 +0900 Subject: [PATCH 2/4] 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. --- test/test-network/systemd-networkd-tests.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index e7a84c7a98..0b17a58d06 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -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: From ebb5036ff2e10d965264ff5868ff4af41548ef58 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 07:17:08 +0900 Subject: [PATCH 3/4] test-network: dummy interface is initially down when activation policy is manual --- test/test-network/systemd-networkd-tests.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0b17a58d06..c53092562a 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3075,10 +3075,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): start_networkd() always = test.startswith('always') - if test == 'manual': - initial_up = 'UP' in check_output('ip link show test1') - else: - initial_up = not test.endswith('down') # note: default is up + initial_up = test != 'manual' and not test.endswith('down') # note: default is up expect_up = initial_up next_up = not expect_up From 073ad7ed1f335f5c1c2a910dfb1e44b4be37bad8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 07:29:32 +0900 Subject: [PATCH 4/4] test-network: wait for a while if manual policy is always-{up,down} If wait_operstate() is called super quickly after ip command, then the up/down state may not be changed and propagated to networkd, and wait_operstate() mistakenly pass with the previous state. To avoid such situation, wait for a while to make networkd actually detect the interface brought up/down. --- test/test-network/systemd-networkd-tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index c53092562a..ba16170393 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3101,6 +3101,8 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): check_output('ip link set dev test1 down') expect_up = initial_up if always else next_up next_up = not next_up + if always: + time.sleep(1) def test_activation_policy(self): for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']: