From 9696ee0742adc799b6c3cc949f2e3301751a4cf4 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Tue, 4 Oct 2022 15:15:42 +0100 Subject: [PATCH 1/2] lisa._assets: Make HOST_PATH depend on LISA_USE_SYSTEM_BIN FEATURE If env var LISA_USE_SYSTEM_BIN=1, HOST_PATH will give priority to existing PATH, otherwise it will give priority to LISA's PATH containing the shipped binaries. Also add get_bin() function that allows getting the path to a binary. --- lisa/_assets/__init__.py | 47 +++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/lisa/_assets/__init__.py b/lisa/_assets/__init__.py index a66bdbb6f..69deff6da 100644 --- a/lisa/_assets/__init__.py +++ b/lisa/_assets/__init__.py @@ -18,6 +18,8 @@ import os import stat import platform +import shutil +from pathlib import Path def _get_abi(): machine = platform.machine() @@ -58,14 +60,49 @@ del _get_abi_bin HOST_BINARIES = ABI_BINARIES[HOST_ABI] -HOST_PATH = ':'.join(( - os.path.join(ASSETS_PATH, 'binaries', HOST_ABI), - os.path.join(ASSETS_PATH, 'scripts'), - os.environ['PATH'] -)) +def _make_path(abi=None): + abi = abi or HOST_ABI + + compos = [ + os.path.join(ASSETS_PATH, 'binaries', abi), + os.path.join(ASSETS_PATH, 'scripts'), + ] + + if abi == HOST_ABI: + path = os.environ['PATH'] + use_system = bool(int(os.environ.get('LISA_USE_SYSTEM_BIN', 0))) + if use_system: + compos = [path] + compos + else: + compos = compos + [path] + + return ':'.join(compos) + +HOST_PATH = _make_path(HOST_ABI) """ Value to be used as the ``PATH`` env var on the host. """ +def get_bin(name, abi=None): + """ + Return the path to a tool bundled in LISA. + + :param abi: ABI of the binary. If ``abi`` is not the host ABI, + ``LISA_USE_SYSTEM_BIN`` is ignored. + :type abi: str or None + + The result is influenced by the ``LISA_USE_SYSTEM_BIN`` environment + variable: + + * If it is set to ``0`` or unset, it will give priority to the binaries + bundled inside the :mod:`lisa` package. + * If it is set to ``1``, it will use the bundled binaries as a fallback + only. + """ + path = shutil.which(name, path=_make_path(abi)) + if path: + return Path(path).resolve() + else: + raise FileNotFoundError(f'Could not locate the tool: {name}') # vim :set tabstop=4 shiftwidth=4 textwidth=80 expandtab -- GitLab From 962cae4440e7e1b53ecc1ebdb24afc6cf6949843 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Tue, 4 Oct 2022 15:16:51 +0100 Subject: [PATCH 2/2] lisa.trace: Use lisa._assets.get_bin() for trace-cmd FEATURE Use the trace-cmd binary shipped by LISA to improve reproducibility and for when lisa is installed from PyPI. It is still possible to make LISA prefer the system binary by setting LISA_USE_SYSTEM_BIN=1 environment variable. --- lisa/trace.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lisa/trace.py b/lisa/trace.py index 64b27e5b3..e27c9333e 100644 --- a/lisa/trace.py +++ b/lisa/trace.py @@ -60,6 +60,7 @@ from lisa.datautils import SignalDesc, df_add_delta, df_deduplicate, df_window, from lisa.version import VERSION_TOKEN from lisa._typeclass import FromString, IntListFromStringInstance from lisa._kmod import LISAFtraceDynamicKmod +from lisa._assets import get_bin class TaskID(namedtuple('TaskID', ('pid', 'comm'))): @@ -1567,6 +1568,8 @@ class TxtTraceParser(TxtTraceParserBase): be reused in another context (cached on disk), and the set of events in a :class:`Trace` object can be expanded dynamically. """ + bin_ = get_bin('trace-cmd') + if not os.path.exists(path): raise FileNotFoundError(f'Unable to locate specified trace file: {path}') @@ -1595,7 +1598,7 @@ class TxtTraceParser(TxtTraceParserBase): kernel_events = { event.split(':', 1)[1] for event in subprocess.check_output( - ['trace-cmd', 'report', '-N', '-E', '--', path], + [bin_, 'report', '-N', '-E', '--', path], stderr=subprocess.DEVNULL, universal_newlines=True, ).splitlines() @@ -1615,7 +1618,7 @@ class TxtTraceParser(TxtTraceParserBase): symbols_address = dict( parse(line) for line in subprocess.check_output( - ['trace-cmd', 'report', '-N', '-f', '--', path], + [bin_, 'report', '-N', '-f', '--', path], stderr=subprocess.DEVNULL, universal_newlines=True, ).splitlines() @@ -1629,7 +1632,7 @@ class TxtTraceParser(TxtTraceParserBase): if 'cpus-count' in needed_metadata: regex = re.compile(rb'cpus=(?P\d+)') with subprocess.Popen( - ['trace-cmd', 'report', '-N', '--', path], + [bin_, 'report', '-N', '--', path], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, ) as p: @@ -1648,7 +1651,7 @@ class TxtTraceParser(TxtTraceParserBase): pre_filled_metadata=pre_filled_metadata, ) cmd = [ - 'trace-cmd', + bin_, 'report', # Do not load any plugin, so that we get fully reproducible results '-N', -- GitLab