From f9d179d210c803d7c9c0cd964eef57791de7c693 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Mon, 13 Jan 2025 14:39:15 -0800 Subject: [PATCH 01/17] Meson: try both 'meson' and 'python3-meson' --- lisa/tools/meson.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index 9ca4d37ee6..852e0323f9 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -30,9 +30,25 @@ def can_install(self) -> bool: def _install(self) -> bool: posix_os: Posix = cast(Posix, self.node.os) # use pip to make sure we install a recent version - if (not posix_os.package_exists("meson")) or posix_os.get_package_information( - "meson", use_cached=False - ) < "0.52.0": + + package_installed = "" + package_available = "" + for pkg in ["meson", "python3-meson"]: + if ( + posix_os.package_exists(pkg) + and posix_os.get_package_information(pkg, use_cached=False) >= "0.52.0" + ): + package_installed = pkg + break + elif posix_os.is_package_in_repo(pkg): + package_available = pkg + break + + if package_installed: + return self._check_exists() + if package_available: + posix_os.install_packages(package_available) + else: username = self.node.tools[Whoami].get_username() self.node.tools[Pip].install_packages("meson", install_to_user=True) # environment variables won't expand even when using shell=True :\ @@ -48,6 +64,7 @@ def _install(self) -> bool: no_info_log=True, no_error_log=True, ) + return self._check_exists() def setup(self, args: str, cwd: PurePath, build_dir: str = "build") -> PurePath: From 08bf094f19d859017f14287d07b6b7b03fa510aa Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Mon, 13 Jan 2025 14:39:42 -0800 Subject: [PATCH 02/17] DPDK: Add needs_reboot option to installer --- microsoft/testsuites/dpdk/common.py | 6 ++++++ microsoft/testsuites/dpdk/dpdktestpmd.py | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/microsoft/testsuites/dpdk/common.py b/microsoft/testsuites/dpdk/common.py index 2a7be6a511..4ab62e9d6b 100644 --- a/microsoft/testsuites/dpdk/common.py +++ b/microsoft/testsuites/dpdk/common.py @@ -39,10 +39,12 @@ def __init__( matcher: Callable[[Posix], bool], packages: Optional[Sequence[Union[str, Tool, Type[Tool]]]] = None, stop_on_match: bool = False, + requires_reboot: bool = False, ) -> None: self.matcher = matcher self.packages = packages self.stop_on_match = stop_on_match + self.requires_reboot = requires_reboot class DependencyInstaller: @@ -65,6 +67,10 @@ def install_required_packages( for requirement in self.requirements: if requirement.matcher(os) and requirement.packages: packages += requirement.packages + if requirement.requires_reboot: + os.install_packages(packages=packages, extra_args=extra_args) + packages = [] + node.reboot() if requirement.stop_on_match: break os.install_packages(packages=packages, extra_args=extra_args) diff --git a/microsoft/testsuites/dpdk/dpdktestpmd.py b/microsoft/testsuites/dpdk/dpdktestpmd.py index 8d5f8629d2..4a51d612af 100644 --- a/microsoft/testsuites/dpdk/dpdktestpmd.py +++ b/microsoft/testsuites/dpdk/dpdktestpmd.py @@ -63,6 +63,7 @@ and bool(x.get_kernel_information().version >= "5.15.0") and x.is_package_in_repo("linux-modules-extra-azure"), packages=["linux-modules-extra-azure"], + requires_reboot=True, ), OsPackageDependencies( matcher=lambda x: isinstance(x, Debian), @@ -226,7 +227,8 @@ def _setup_node(self) -> None: # which breaks when another tool checks for it's existence before building... # like cmake, meson, make, autoconf, etc. self._node.tools[Ninja].install() - self._node.tools[Pip].install_packages("pyelftools") + if not isinstance(self._os, Debian): + self._node.tools[Pip].install_packages("pyelftools") def _uninstall(self) -> None: # undo source installation (thanks ninja) From d34f4be154df865e70528ad37128acedc763f19f Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 14 Jan 2025 08:23:12 -0800 Subject: [PATCH 03/17] Suse: implement _uninstall_packages --- lisa/operating_system.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index f94980dd5f..b96fb466ac 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -2094,6 +2094,35 @@ def _initialize_package_installation(self) -> None: "There are no enabled repositories defined in this image.", ) + def _uninstall_packages( + self, + packages: List[str], + signed: bool = True, + timeout: int = 600, + extra_args: Optional[List[str]] = None, + ) -> None: + add_args = self._process_extra_package_args(extra_args) + command = f"zypper --non-interactive {add_args}" + if not signed: + command += " --no-gpg-checks " + command += f" rm {' '.join(packages)}" + self.wait_running_process("zypper") + install_result = self._node.execute( + command, shell=True, sudo=True, timeout=timeout + ) + if install_result.exit_code in (1, 100): + raise LisaException( + f"Failed to install {packages}. exit_code: {install_result.exit_code}, " + f"stderr: {install_result.stderr}" + ) + elif install_result.exit_code == 0: + self._log.debug(f"{packages} is/are installed successfully.") + else: + self._log.debug( + f"{packages} is/are installed." + " A system reboot or package manager restart might be required." + ) + def _install_packages( self, packages: List[str], From b77c65a3338b97929d72da8b77b729a714b96205 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Wed, 15 Jan 2025 10:52:46 -0800 Subject: [PATCH 04/17] Suse: i guess just 0 --- lisa/operating_system.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index b96fb466ac..aa9f1058f2 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -2110,18 +2110,14 @@ def _uninstall_packages( install_result = self._node.execute( command, shell=True, sudo=True, timeout=timeout ) - if install_result.exit_code in (1, 100): + + if install_result.exit_code == 0: + self._log.debug(f"{packages} is/are removed successfully.") + else: raise LisaException( - f"Failed to install {packages}. exit_code: {install_result.exit_code}, " + f"Failed to remove {packages}. exit_code: {install_result.exit_code}, " f"stderr: {install_result.stderr}" ) - elif install_result.exit_code == 0: - self._log.debug(f"{packages} is/are installed successfully.") - else: - self._log.debug( - f"{packages} is/are installed." - " A system reboot or package manager restart might be required." - ) def _install_packages( self, From f6be10461955ed6047bab05221d8753086c78541 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Thu, 16 Jan 2025 13:47:21 -0800 Subject: [PATCH 05/17] Meson: restructure and comment installation options --- lisa/tools/meson.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index 852e0323f9..ff60169b7d 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -15,13 +15,18 @@ class Meson(Tool): + _minimum_version = "0.52.0" + @property def command(self) -> str: return "meson" def _check_exists(self) -> bool: result = self.node.execute("meson --version", shell=True) - return result.exit_code == 0 and VersionInfo.parse(result.stdout) >= "0.52.0" + return ( + result.exit_code == 0 + and VersionInfo.parse(result.stdout) >= self._minimum_version + ) @property def can_install(self) -> bool: @@ -33,10 +38,17 @@ def _install(self) -> bool: package_installed = "" package_available = "" - for pkg in ["meson", "python3-meson"]: + # packaged as 'meson' on older systems and 'python3-meson' on newer ones, + # since it's actually just a python package. + # So check for both + for pkg in [ + "python3-meson", + "meson", + ]: if ( posix_os.package_exists(pkg) - and posix_os.get_package_information(pkg, use_cached=False) >= "0.52.0" + and posix_os.get_package_information(pkg, use_cached=False) + >= self._minimum_version ): package_installed = pkg break @@ -44,14 +56,22 @@ def _install(self) -> bool: package_available = pkg break + # prefer the packaged version as long as it's the right version if package_installed: return self._check_exists() if package_available: posix_os.install_packages(package_available) - else: + # verify version is correct if it's installed from pkg manager + if posix_os.get_package_information(pkg) < self._minimum_version: + posix_os.uninstall_packages(pkg) + package_available = "" + + # otherwise, install with pip + # this can get weird on some systems since they have started + # returning an error code if you try to use pip without a venv + if not (package_available or package_installed): username = self.node.tools[Whoami].get_username() self.node.tools[Pip].install_packages("meson", install_to_user=True) - # environment variables won't expand even when using shell=True :\ self.node.tools[Ln].create_link( f"/home/{username}/.local/bin/meson", "/usr/bin/meson", force=True ) From 97ba111b638d311affa5845a7b897f99a2d0da97 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Thu, 16 Jan 2025 14:52:13 -0800 Subject: [PATCH 06/17] package_exists: add minimum_version --- lisa/operating_system.py | 15 +++++++++++++-- lisa/tools/meson.py | 10 +++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index aa9f1058f2..5d6a312d2a 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -404,13 +404,24 @@ def uninstall_packages( package_names = self._get_package_list(packages) self._uninstall_packages(package_names, signed, timeout, extra_args) - def package_exists(self, package: Union[str, Tool, Type[Tool]]) -> bool: + def package_exists( + self, + package: Union[str, Tool, Type[Tool]], + minimum_version: Optional[VersionInfo] = None, + ) -> bool: """ Query if a package/tool is installed on the node. Return Value - bool """ package_name = self.__resolve_package_name(package) - return self._package_exists(package_name) + exists = self._package_exists(package_name) + if exists and minimum_version: + return ( + self.get_package_information(package_name=package_name) + >= minimum_version + ) + else: + return exists def is_package_in_repo(self, package: Union[str, Tool, Type[Tool]]) -> bool: """ diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index ff60169b7d..59c2a019f5 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -15,7 +15,7 @@ class Meson(Tool): - _minimum_version = "0.52.0" + _minimum_version = VersionInfo(major=0, minor=52, patch=0) @property def command(self) -> str: @@ -45,11 +45,7 @@ def _install(self) -> bool: "python3-meson", "meson", ]: - if ( - posix_os.package_exists(pkg) - and posix_os.get_package_information(pkg, use_cached=False) - >= self._minimum_version - ): + if posix_os.package_exists(pkg, minimum_version=self._minimum_version): package_installed = pkg break elif posix_os.is_package_in_repo(pkg): @@ -62,7 +58,7 @@ def _install(self) -> bool: if package_available: posix_os.install_packages(package_available) # verify version is correct if it's installed from pkg manager - if posix_os.get_package_information(pkg) < self._minimum_version: + if not posix_os.package_exists(pkg, minimum_version=self._minimum_version): posix_os.uninstall_packages(pkg) package_available = "" From 124c351fa4b7e6c2f7cc6e6bb0c984aa5bf4ca04 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Thu, 16 Jan 2025 14:52:46 -0800 Subject: [PATCH 07/17] rdma-core: check for existence before removal --- microsoft/testsuites/dpdk/rdmacore.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/microsoft/testsuites/dpdk/rdmacore.py b/microsoft/testsuites/dpdk/rdmacore.py index 0a0d650e1b..44e3efb18f 100644 --- a/microsoft/testsuites/dpdk/rdmacore.py +++ b/microsoft/testsuites/dpdk/rdmacore.py @@ -149,7 +149,8 @@ def _check_if_installed(self) -> bool: def _setup_node(self) -> None: if isinstance(self._os, (Debian, Fedora, Suse)): - self._os.uninstall_packages("rdma-core") + if self._os.package_exists("rdma-core"): + self._os.uninstall_packages("rdma-core") if isinstance(self._os, Fedora): self._os.group_install_packages("Development Tools") super()._setup_node() From 370fc4edb7b1c031fcefdcba726bd6fa8a631a0f Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Thu, 16 Jan 2025 14:53:35 -0800 Subject: [PATCH 08/17] Dpdk: move pyelftools to single installation point --- microsoft/testsuites/dpdk/dpdktestpmd.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/microsoft/testsuites/dpdk/dpdktestpmd.py b/microsoft/testsuites/dpdk/dpdktestpmd.py index 4a51d612af..f67f9d645d 100644 --- a/microsoft/testsuites/dpdk/dpdktestpmd.py +++ b/microsoft/testsuites/dpdk/dpdktestpmd.py @@ -106,8 +106,6 @@ "dpkg-dev", "pkg-config", "python3-pip", - "python3-pyelftools", - "python-pyelftools", # 18.04 doesn't need linux-modules-extra-azure # since it will never have MANA support ], @@ -128,7 +126,6 @@ "build-essential", "libnuma-dev", "libmnl-dev", - "python3-pyelftools", "libelf-dev", "pkg-config", ], @@ -228,6 +225,8 @@ def _setup_node(self) -> None: # like cmake, meson, make, autoconf, etc. self._node.tools[Ninja].install() if not isinstance(self._os, Debian): + self._os.install_packages("python3-pyelftools") + else: self._node.tools[Pip].install_packages("pyelftools") def _uninstall(self) -> None: From b3a37adea1123a032809e40dbdbe5f021c4d45d9 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 21 Jan 2025 09:19:07 -0800 Subject: [PATCH 09/17] Minimum version add debug log if no match --- lisa/operating_system.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index 5d6a312d2a..73f7f28524 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -415,11 +415,19 @@ def package_exists( """ package_name = self.__resolve_package_name(package) exists = self._package_exists(package_name) - if exists and minimum_version: - return ( + if exists and minimum_version is not None: + acceptable = bool( self.get_package_information(package_name=package_name) >= minimum_version ) + if not acceptable: + self._log.debug( + ( + f"Minimum version of package {package_name} " + f"did not meet minimum of {str(minimum_version)}." + ) + ) + return acceptable else: return exists From 3cfa460b979aa339104e9965421679c6174610c7 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 21 Jan 2025 09:25:37 -0800 Subject: [PATCH 10/17] OS SUSE uninstall: use assert_that --- lisa/operating_system.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index 73f7f28524..e6c4a8b353 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -2129,14 +2129,12 @@ def _uninstall_packages( install_result = self._node.execute( command, shell=True, sudo=True, timeout=timeout ) - - if install_result.exit_code == 0: - self._log.debug(f"{packages} is/are removed successfully.") - else: - raise LisaException( - f"Failed to remove {packages}. exit_code: {install_result.exit_code}, " - f"stderr: {install_result.stderr}" - ) + assert_that(install_result.exit_code).described_as( + f"Failed to remove {packages}. " + f"exit_code: {install_result.exit_code}, " + f"stderr: {install_result.stderr}" + ).is_equal_to(0) + self._log.debug(f"{packages} is/are removed successfully.") def _install_packages( self, From 186221b778cd7438bd6a0b65753bd3c3a601a060 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 21 Jan 2025 10:54:24 -0800 Subject: [PATCH 11/17] OS packages, fix printing of List[str] of packages --- lisa/operating_system.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index e6c4a8b353..3d12d695c1 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -2124,13 +2124,14 @@ def _uninstall_packages( command = f"zypper --non-interactive {add_args}" if not signed: command += " --no-gpg-checks " - command += f" rm {' '.join(packages)}" + remove_packages = " ".join(packages) + command += f" rm {remove_packages}" self.wait_running_process("zypper") install_result = self._node.execute( command, shell=True, sudo=True, timeout=timeout ) assert_that(install_result.exit_code).described_as( - f"Failed to remove {packages}. " + f"Failed to remove {remove_packages}. " f"exit_code: {install_result.exit_code}, " f"stderr: {install_result.stderr}" ).is_equal_to(0) From 6bc582ce40abdd476199616e49b92ea2a33f5d6a Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Mon, 27 Jan 2025 07:45:15 -0800 Subject: [PATCH 12/17] make package_exists version check simpler --- lisa/operating_system.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index 3d12d695c1..f721e1b09f 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -415,22 +415,17 @@ def package_exists( """ package_name = self.__resolve_package_name(package) exists = self._package_exists(package_name) - if exists and minimum_version is not None: - acceptable = bool( - self.get_package_information(package_name=package_name) - >= minimum_version - ) - if not acceptable: - self._log.debug( - ( - f"Minimum version of package {package_name} " - f"did not meet minimum of {str(minimum_version)}." - ) - ) - return acceptable - else: + self._log.debug(f"package '{package}' exists: {exists}") + if minimum_version is None or not exists: return exists + actual_version = self.get_package_information(package_name=package_name) + self._log.debug( + f"package '{package}' expected min version: " + f"{str(minimum_version)}, actual version: {str(actual_version)}" + ) + return actual_version >= minimum_version + def is_package_in_repo(self, package: Union[str, Tool, Type[Tool]]) -> bool: """ Query if a package/tool exists in the repo From adfa8cdb21935583030abb5ae013ac7b1e5aa8f9 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Mon, 27 Jan 2025 08:48:08 -0800 Subject: [PATCH 13/17] DPDK: prefer newer pyelftools package --- microsoft/testsuites/dpdk/dpdktestpmd.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/microsoft/testsuites/dpdk/dpdktestpmd.py b/microsoft/testsuites/dpdk/dpdktestpmd.py index f67f9d645d..9b90a28c28 100644 --- a/microsoft/testsuites/dpdk/dpdktestpmd.py +++ b/microsoft/testsuites/dpdk/dpdktestpmd.py @@ -224,9 +224,16 @@ def _setup_node(self) -> None: # which breaks when another tool checks for it's existence before building... # like cmake, meson, make, autoconf, etc. self._node.tools[Ninja].install() - if not isinstance(self._os, Debian): + # try multiple avenues for installing pyelftools, preferring the + # more recent convention of prepending apt/dnf/etc python system packages + # with python3-... + if self._os.is_package_in_repo("python3-pyelftools"): self._os.install_packages("python3-pyelftools") + # then try the older package manager name if it's available + elif self._os.is_package_in_repo("pyelftools"): + self._os.install_packages("pyelftools") else: + # otherwise try pip. This can fail to install for the system on ubuntu 24.04 self._node.tools[Pip].install_packages("pyelftools") def _uninstall(self) -> None: From 452df1c4304564a408356da417c3b17308b3fe27 Mon Sep 17 00:00:00 2001 From: "Matthew McGovern (LINUX)" Date: Tue, 28 Jan 2025 10:18:36 -0800 Subject: [PATCH 14/17] Use helper function instead of instantiating the class directly --- lisa/tools/meson.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index 59c2a019f5..6a7a19225a 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -8,14 +8,14 @@ from lisa.executable import Tool from lisa.operating_system import Posix - +from lisa.util import parse_version from .ln import Ln from .python import Pip from .whoami import Whoami class Meson(Tool): - _minimum_version = VersionInfo(major=0, minor=52, patch=0) + _minimum_version = parse_version("0.52.0") @property def command(self) -> str: From 74d880804f8576197daeab408e01d0ef7bc851ae Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 28 Jan 2025 11:20:14 -0800 Subject: [PATCH 15/17] check_exists( ..., minimum_version) considered harmful Undoing a change I added which enabled a _minimum_version check on _check_exists. This is a bad system because you'll end up needing to do things like this: if not posix_os._check_exists(pkg, minimum_version=...): # Now what? Was it installed or not? # Was it installed and just the wrong version? The ultimate fix should be is_package_in_repo(pkg, minimum_version) Since we should be checking if an available package is the right version _before_ installing it blindly. This all seems out-of-scope for fixing a bug installing meson in _just_ the DPDK suite. So, I'm removing it. We can move the fixed install pattern to the operating_system.py level later if anyone else needs it. --- lisa/operating_system.py | 23 +++++++--------------- lisa/tools/meson.py | 42 ++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/lisa/operating_system.py b/lisa/operating_system.py index f721e1b09f..e87c9a591a 100644 --- a/lisa/operating_system.py +++ b/lisa/operating_system.py @@ -407,7 +407,6 @@ def uninstall_packages( def package_exists( self, package: Union[str, Tool, Type[Tool]], - minimum_version: Optional[VersionInfo] = None, ) -> bool: """ Query if a package/tool is installed on the node. @@ -416,15 +415,7 @@ def package_exists( package_name = self.__resolve_package_name(package) exists = self._package_exists(package_name) self._log.debug(f"package '{package}' exists: {exists}") - if minimum_version is None or not exists: - return exists - - actual_version = self.get_package_information(package_name=package_name) - self._log.debug( - f"package '{package}' expected min version: " - f"{str(minimum_version)}, actual version: {str(actual_version)}" - ) - return actual_version >= minimum_version + return exists def is_package_in_repo(self, package: Union[str, Tool, Type[Tool]]) -> bool: """ @@ -2122,14 +2113,14 @@ def _uninstall_packages( remove_packages = " ".join(packages) command += f" rm {remove_packages}" self.wait_running_process("zypper") - install_result = self._node.execute( + uninstall_result = self._node.execute( command, shell=True, sudo=True, timeout=timeout ) - assert_that(install_result.exit_code).described_as( - f"Failed to remove {remove_packages}. " - f"exit_code: {install_result.exit_code}, " - f"stderr: {install_result.stderr}" - ).is_equal_to(0) + uninstall_result.assert_exit_code( + expected_exit_code=0, + message=f"Could not uninstall package(s): {remove_packages}", + include_output=True, + ) self._log.debug(f"{packages} is/are removed successfully.") def _install_packages( diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index 6a7a19225a..d882d73553 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -9,6 +9,7 @@ from lisa.executable import Tool from lisa.operating_system import Posix from lisa.util import parse_version + from .ln import Ln from .python import Pip from .whoami import Whoami @@ -40,32 +41,45 @@ def _install(self) -> bool: package_available = "" # packaged as 'meson' on older systems and 'python3-meson' on newer ones, # since it's actually just a python package. - # So check for both + # But now we have a bunch of annoying cases. + # 'meson' is installed but the wrong version + # meson is installed but the right version + # meson is not installed and it's the wrong version + # meson is not installed and it's the right version for pkg in [ "python3-meson", "meson", ]: - if posix_os.package_exists(pkg, minimum_version=self._minimum_version): + if posix_os.package_exists(pkg): package_installed = pkg break elif posix_os.is_package_in_repo(pkg): package_available = pkg break - # prefer the packaged version as long as it's the right version - if package_installed: - return self._check_exists() + # install the available package, if one was available and not installed if package_available: posix_os.install_packages(package_available) - # verify version is correct if it's installed from pkg manager - if not posix_os.package_exists(pkg, minimum_version=self._minimum_version): - posix_os.uninstall_packages(pkg) - package_available = "" - - # otherwise, install with pip - # this can get weird on some systems since they have started - # returning an error code if you try to use pip without a venv - if not (package_available or package_installed): + package_installed = package_available + + # now, if either previoulsy or newly installed package, check the version + if package_installed: + if ( + posix_os.get_package_information(package_installed, use_cached=False) + < self._minimum_version + ): + # and uninstall if the version is not recent enough + posix_os.uninstall_packages(package_installed) + package_installed = "" + else: + # otherwise, we're done. + return self._check_exists() + + # If we get here, we couldn't find a good version from the package manager + # so we will install with pip. This is least desirable since it introduces + # unpredictable behavior when running meson or ninja with sudo. + # Like sudo ninja install, for example. + if not package_installed: username = self.node.tools[Whoami].get_username() self.node.tools[Pip].install_packages("meson", install_to_user=True) self.node.tools[Ln].create_link( From 459acb307410e83ef0c6775e6c15ae5c03090aa0 Mon Sep 17 00:00:00 2001 From: Matthew G McGovern Date: Tue, 28 Jan 2025 16:10:35 -0800 Subject: [PATCH 16/17] DPDK: linux-modules-extra-azure reboot --- microsoft/testsuites/dpdk/dpdktestpmd.py | 1 + 1 file changed, 1 insertion(+) diff --git a/microsoft/testsuites/dpdk/dpdktestpmd.py b/microsoft/testsuites/dpdk/dpdktestpmd.py index 9b90a28c28..b30a9961e4 100644 --- a/microsoft/testsuites/dpdk/dpdktestpmd.py +++ b/microsoft/testsuites/dpdk/dpdktestpmd.py @@ -119,6 +119,7 @@ and bool(x.get_kernel_information().version >= "5.15.0") and x.is_package_in_repo("linux-modules-extra-azure"), packages=["linux-modules-extra-azure"], + requires_reboot=True, ), OsPackageDependencies( matcher=lambda x: isinstance(x, Debian), From 5530bc8b82f7066bb38eb2ad3a3efad68de01d11 Mon Sep 17 00:00:00 2001 From: "Matthew McGovern (LINUX)" Date: Fri, 7 Feb 2025 10:00:39 -0800 Subject: [PATCH 17/17] Meson: rework install flow, plus more and better comments. --- lisa/tools/meson.py | 75 ++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/lisa/tools/meson.py b/lisa/tools/meson.py index d882d73553..1e8c183976 100644 --- a/lisa/tools/meson.py +++ b/lisa/tools/meson.py @@ -42,58 +42,71 @@ def _install(self) -> bool: # packaged as 'meson' on older systems and 'python3-meson' on newer ones, # since it's actually just a python package. # But now we have a bunch of annoying cases. - # 'meson' is installed but the wrong version - # meson is installed but the right version - # meson is not installed and it's the wrong version - # meson is not installed and it's the right version + # 1. meson is installed and it's the right version + # 2. 'meson' is installed but the wrong version + # 3. meson is not installed and the right version is in the repo + # 4. meson is not installed and the wrong version is in the repo + for pkg in [ "python3-meson", "meson", ]: if posix_os.package_exists(pkg): package_installed = pkg - break - elif posix_os.is_package_in_repo(pkg): + if posix_os.is_package_in_repo(pkg): package_available = pkg + if package_installed or package_available: break - # install the available package, if one was available and not installed + if package_installed: + # check the installed version before touching anything + if ( + posix_os.get_package_information(package_installed, use_cached=False) + >= self._minimum_version + ): + # meson is installed and it's the right version + return self._check_exists() + + # otherwise, install the available package from the repo if package_available: posix_os.install_packages(package_available) + # and update the cached version info + posix_os.get_package_information(package_available, use_cached=False) package_installed = package_available - # now, if either previoulsy or newly installed package, check the version + # check the version, return if it's good, remove if not if package_installed: if ( - posix_os.get_package_information(package_installed, use_cached=False) - < self._minimum_version + posix_os.get_package_information(package_installed) + >= self._minimum_version ): - # and uninstall if the version is not recent enough + # the right version was in the repo + return self._check_exists() + else: + # the wrong version was in the repo + # (or wrong version installed and no update available from repo) posix_os.uninstall_packages(package_installed) package_installed = "" - else: - # otherwise, we're done. - return self._check_exists() - # If we get here, we couldn't find a good version from the package manager - # so we will install with pip. This is least desirable since it introduces + # If we get here, we couldn't find a good version from the package manager. + # So we will install with pip. This is least desirable since it introduces # unpredictable behavior when running meson or ninja with sudo. # Like sudo ninja install, for example. - if not package_installed: - username = self.node.tools[Whoami].get_username() - self.node.tools[Pip].install_packages("meson", install_to_user=True) - self.node.tools[Ln].create_link( - f"/home/{username}/.local/bin/meson", "/usr/bin/meson", force=True - ) - # ensure sudo has access as well - self.node.execute( - "pip3 install meson", - sudo=True, - shell=True, - no_debug_log=True, - no_info_log=True, - no_error_log=True, - ) + + username = self.node.tools[Whoami].get_username() + self.node.tools[Pip].install_packages("meson", install_to_user=True) + self.node.tools[Ln].create_link( + f"/home/{username}/.local/bin/meson", "/usr/bin/meson", force=True + ) + # ensure sudo has access as well + self.node.execute( + "pip3 install meson", + sudo=True, + shell=True, + no_debug_log=True, + no_info_log=True, + no_error_log=True, + ) return self._check_exists()