From f6102c545e8587acb747af3dca5633143a59c781 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 16 Sep 2026 23:50:12 +0200 Subject: smoketest: T9316: do not race the DHCP client when checking VRF membership test_dhcp_vrf and test_dhcpv6_vrf resolved the DHCP client's PID, then read the VRF's process list and asserted the PID appeared in it. The client re-executes itself at moments of its own choosing, so between those two steps it can come back with a new PID - the process is in the VRF, it simply is not the process we asked about: AssertionError: '13502' not found in '14322 dhclient\n 14324 dhclient-script\n 14485 dhclient...' Observed failing and passing on the same image, so it costs a rerun rather than telling anyone anything. get_process_cmdline() already fights the same race for the /proc read. Resolve the PID and read the VRF's list as one step and retry, so a restart costs a retry instead of a failure. The probe itself was also loose: substring-matching the raw output of "ip vrf pids " lets a PID check be satisfied by the process name column or by a longer PID containing ours. Add vyos.utils.network.get_vrf_pids(), which parses the command's " " lines into (pid, process_name) tuples and returns an empty list for an unknown VRF, and compare the PID field as an int. --- python/vyos/utils/network.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'python') diff --git a/python/vyos/utils/network.py b/python/vyos/utils/network.py index 3a26fe193..e7987c053 100644 --- a/python/vyos/utils/network.py +++ b/python/vyos/utils/network.py @@ -135,6 +135,31 @@ def get_vrf_members(vrf: str) -> list: pass return interfaces +def get_vrf_pids(vrf: str) -> list[tuple[int, str]]: + """ + Get list of processes running inside a given VRF + + "ip vrf pids " prints one " " pair per line: + 44425 dhclient + + :param vrf: str + :return: list of (pid, process_name) tuples + """ + processes = [] + if not interface_exists(vrf): + return processes + try: + output = cmdl(['ip', 'vrf', 'pids', vrf]) + except Exception: + return processes + for line in output.splitlines(): + tmp = line.split(maxsplit=1) + # skip blank lines and any output not of the " " form + if len(tmp) != 2 or not tmp[0].isdigit(): + continue + processes.append((int(tmp[0]), tmp[1].strip())) + return processes + def get_interface_vrf(interface): """ Returns VRF of given interface """ from vyos.utils.dict import dict_search -- cgit v1.2.3