diff --git a/lisa/tools/chrony.py b/lisa/tools/chrony.py index 34cdf01d30..fe62147451 100644 --- a/lisa/tools/chrony.py +++ b/lisa/tools/chrony.py @@ -26,9 +26,7 @@ class Chrony(Tool): # Leap status : Normal - __leap_status_pattern = re.compile( - r"([\w\W]*?)Leap status.*:.*Normal$", re.MULTILINE - ) + __leap_status_pattern = re.compile(r"Leap status\s*:\s*Normal") __no_server_set = "Number of sources = 0" __service_not_ready = "503 No such source" @@ -69,7 +67,7 @@ def restart(self) -> None: def check_tracking(self) -> None: cmd_result = self.run("tracking", force_run=True, sudo=True) cmd_result.assert_exit_code() - if not self.__leap_status_pattern.match(cmd_result.stdout): + if not self.__leap_status_pattern.search(cmd_result.stdout): raise LisaException( f"Leap status of {self.command} tracking is not expected," " please check the service status of chrony." diff --git a/lisa/tools/dhclient.py b/lisa/tools/dhclient.py index a4c1978b3a..1c49f6c40a 100644 --- a/lisa/tools/dhclient.py +++ b/lisa/tools/dhclient.py @@ -5,7 +5,7 @@ from lisa.base_tools import Cat from lisa.executable import Tool -from lisa.operating_system import Debian, Fedora, Redhat, Suse +from lisa.operating_system import CBLMariner, Debian, Fedora, Redhat, Suse from lisa.util import LisaException, UnsupportedDistroException, find_group_in_lines from .ls import Ls @@ -71,10 +71,32 @@ def get_timeout(self) -> int: if group and not group["default"]: value = int(group["number"]) is_default_value = False - elif isinstance(self.node.os, Fedora): - # the default value in fedora is 300 + elif isinstance(self.node.os, (Fedora, CBLMariner)): + # Fedora and AZL4+ use NetworkManager for DHCP; default timeout is 300. + # CBLMariner < 4 is not supported here and raises below. + if isinstance(self.node.os, CBLMariner) and ( + self.node.os.information.version.major < 4 + ): + raise UnsupportedDistroException( + os=self.node.os, + message=( + "CBLMariner < 4 (AZL2/3) uses dhcpcd rather than " + "NetworkManager, so this NetworkManager-based timeout " + "lookup does not apply. To add support, read the timeout " + "from the dhcpcd configuration (e.g. /etc/dhcpcd.conf) " + "instead." + ), + ) value = 300 - result = self.node.execute("NetworkManager --print-config", sudo=True) + result = self.node.execute( + "NetworkManager --print-config", + sudo=True, + expected_exit_code=0, + expected_exit_code_failure_message=( + "Failed to read DHCP timeout from NetworkManager. " + "Ensure NetworkManager is installed and accessible." + ), + ) group = find_group_in_lines(result.stdout, self._fedora_pattern) if group and value != int(group["number"]): value = int(group["number"]) diff --git a/lisa/tools/kdump.py b/lisa/tools/kdump.py index 8aa0c1891b..af0c510309 100644 --- a/lisa/tools/kdump.py +++ b/lisa/tools/kdump.py @@ -226,6 +226,8 @@ def create(cls, node: "Node", *args: Any, **kwargs: Any) -> Tool: elif isinstance(node.os, Suse): return KdumpSuse(node) elif isinstance(node.os, CBLMariner): + if node.os.information.version.major >= 4: + return KdumpFedora(node) return KdumpCBLMariner(node) elif type(node.os) is Fedora: return KdumpFedora(node) @@ -585,7 +587,7 @@ def command(self) -> str: return "kdumpctl" def _install(self) -> bool: - assert isinstance(self.node.os, Fedora) + assert isinstance(self.node.os, (Fedora, CBLMariner)) self.node.os.install_packages("kdump-utils") return self._check_exists() diff --git a/lisa/tools/kill.py b/lisa/tools/kill.py index e26cbbb470..15fe0dc355 100644 --- a/lisa/tools/kill.py +++ b/lisa/tools/kill.py @@ -6,6 +6,7 @@ from lisa.util import LisaException from lisa.util.constants import SIGKILL +from .pgrep import Pgrep from .pidof import Pidof @@ -21,17 +22,19 @@ def can_install(self) -> bool: def by_name( self, process_name: str, signum: int = SIGKILL, ignore_not_exist: bool = False ) -> None: - # attempt kill by name first - kill_by_name = self.run( - f"-s {signum} {process_name}", sudo=True, shell=True, force_run=True - ) - if kill_by_name.exit_code == 0: + # Prefer pidof for exact-name matching to avoid regex side-effects, + # then fall back to pgrep for processes started via sudo/shell wrappers. + pids = self.node.tools[Pidof].get_pids(process_name, sudo=True) + if pids: + for pid in pids: + self.by_pid(pid, signum, ignore_not_exist) return - # fallback to kill by pid if first attempt fails for some reason - pids = self.node.tools[Pidof].get_pids(process_name, sudo=True) - for pid in pids: - self.by_pid(pid, signum, ignore_not_exist) + # Fallback: try pgrep in case pidof missed it (e.g. wrapper processes) + processes = self.node.tools[Pgrep].get_processes(process_name) + if processes: + for proc in processes: + self.by_pid(proc.id, signum, ignore_not_exist) else: self._log.debug( f"Kill for {process_name} did not find any processes to kill." diff --git a/lisa/tools/modprobe.py b/lisa/tools/modprobe.py index 7b8a0b2cb1..3ebcca169e 100644 --- a/lisa/tools/modprobe.py +++ b/lisa/tools/modprobe.py @@ -242,6 +242,11 @@ def reload( "\nTrying to reconnect to the remote node in 2 sec..." ) time.sleep(2) + # Reset the stale SSH transport so the next retry establishes + # a fresh connection. Without this, the retry loop keeps + # reusing the broken session and every attempt fails with + # "cannot connect to TCP port 22". + self.node.close() self._log.debug( f"Time taken to reload {mod_name}: {timer.elapsed(False)} seconds"