From f353f8533397249d0bcef658a4e6fcd5fffdd856 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 17 Oct 2026 20:55:32 +0200 Subject: wlb: T9472: report the initial state of every interface On start the health daemon forces a state change so the hook learns the initial state of the WAN interfaces. The flag doing so was reset after the first interface, every other interface was only reported once its state actually changed. The flag is now reset after all interfaces have been checked. The existing hook smoketest relied on the old behaviour: it now keeps all hook events and no longer reads a file left over from an earlier run. --- smoketest/scripts/cli/test_load-balancing_wan.py | 35 +++++++++++++++++++++++- src/helpers/vyos-load-balancer.py | 4 ++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/smoketest/scripts/cli/test_load-balancing_wan.py b/smoketest/scripts/cli/test_load-balancing_wan.py index ed3970abc..5c67778e3 100755 --- a/smoketest/scripts/cli/test_load-balancing_wan.py +++ b/smoketest/scripts/cli/test_load-balancing_wan.py @@ -390,9 +390,13 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): ifname=$WLB_INTERFACE_NAME state=$WLB_INTERFACE_STATE -echo "$ifname - $state" > {hook_output_path} +echo "$ifname - $state" >> {hook_output_path} """ + # the hook reports every interface on start, keep all events and + # drop the ones of earlier runs + call(f'sudo rm -f {hook_output_path}') + self.addCleanup(call, f'sudo rm -f {hook_output_path} {hook_path}') write_file(hook_path, hook_script) chmod_755(hook_path) @@ -848,6 +852,35 @@ printf 'WLB_INTERFACE_NAME=%s WLB_SCRIPT_IFACE=%s\\n' \\ self.cli_set(test + ['ttl-limit', '3']) self.cli_commit() self.lab_wait_status(failed) + def test_hook_initial_state_all_interfaces(self): + # the initial state was only reported to the hook for the first + # interface + tmpdir = tempfile.TemporaryDirectory() + self.addCleanup(tmpdir.cleanup) + hook = os.path.join(tmpdir.name, 'hook.sh') + log = os.path.join(tmpdir.name, 'hook.log') + # the hook runs without PATH + write_file(hook, f'#!/bin/sh\n/bin/echo "$WLB_INTERFACE_NAME $WLB_INTERFACE_STATE" >> {log}\n') + chmod_755(hook) + chmod_755(tmpdir.name) + + isps = ['eth231', 'eth232'] + self.lab_setup('eth230', isps) + for index, ifname in enumerate(isps, start=1): + self.lab_health(ifname, index) + self.cli_set(base_path + ['wan', 'rule', '10', 'interface', ifname]) + self.cli_set(base_path + ['wan', 'rule', '10', 'inbound-interface', 'eth230']) + self.cli_set(base_path + ['wan', 'hook', hook]) + self.cli_commit() + + def reported(): + if not os.path.exists(log): + return set() + with open(log) as f: + return set(f.read().splitlines()) + + found, last = self.wait_for_result(reported, {'eth231 ACTIVE', 'eth232 ACTIVE'}, timeout=20) + self.assertTrue(found, msg=f'hook reported {last}') if __name__ == '__main__': unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) diff --git a/src/helpers/vyos-load-balancer.py b/src/helpers/vyos-load-balancer.py index d289f1c7f..38ba8d87b 100755 --- a/src/helpers/vyos-load-balancer.py +++ b/src/helpers/vyos-load-balancer.py @@ -375,7 +375,6 @@ if __name__ == '__main__': #Force state changed to trigger the first write if init == True: state['state_changed'] = True - init = False if state['state_changed']: state['if_addr'] = get_ipv4_address(ifname) @@ -386,6 +385,9 @@ if __name__ == '__main__': restore_default_route(lb, ifname) + # every interface reports its initial state + init = False + if any(state['state_changed'] for ifname, state in lb['health_state'].items()): if not nftables_update(lb): break -- cgit v1.2.3