diff --git a/eessi/testsuite/eessi_mixin.py b/eessi/testsuite/eessi_mixin.py index 53508117..0ea55200 100644 --- a/eessi/testsuite/eessi_mixin.py +++ b/eessi/testsuite/eessi_mixin.py @@ -1,11 +1,13 @@ from reframe.core.builtins import parameter, run_after, variable -from reframe.core.exceptions import ReframeFatalError +from reframe.core.exceptions import ReframeFatalError, SanityError from reframe.core.pipeline import RegressionMixin from reframe.utility.sanity import make_performance_function +import reframe.utility.sanity as sn from eessi.testsuite import hooks from eessi.testsuite.constants import DEVICE_TYPES, SCALES, COMPUTE_UNIT, TAGS from eessi.testsuite.utils import log +from eessi.testsuite import __version__ as testsuite_version # Hooks from the Mixin class seem to be executed _before_ those of the child class @@ -42,6 +44,14 @@ class EESSI_Mixin(RegressionMixin): bench_name = None bench_name_ci = None + # Create ReFrame variables for logging runtime environment information + cvmfs_repo_name = variable(str, value='None') + cvmfs_software_subdir = variable(str, value='None') + full_modulepath = variable(str, value='None') + + # Make sure the version of the EESSI test suite gets logged in the ReFrame report + eessi_testsuite_version = variable(str, value=testsuite_version) + # Note that the error for an empty parameter is a bit unclear for ReFrame 4.6.2, but that will hopefully improve # see https://github.com/reframe-hpc/reframe/issues/3254 # If that improves: uncomment the following to force the user to set module_name @@ -165,3 +175,46 @@ def assign_tasks_per_compute_unit(self): def request_mem(self): """Call hook to request the required amount of memory per node""" hooks.req_memory_per_node(self, app_mem_req=self.required_mem_per_node()) + + @run_after('setup') + def log_runtime_info(self): + """Log additional runtime information: which CVMFS repo was used (or if it was testing local software), + path to the modulefile, EESSI software subdir, EESSI testsuite version""" + self.postrun_cmds.append('echo "EESSI_CVMFS_REPO: $EESSI_CVMFS_REPO"') + self.postrun_cmds.append('echo "EESSI_SOFTWARE_SUBDIR: $EESSI_SOFTWARE_SUBDIR"') + if self.module_name: + # Get full modulepath, stripping leading spaces with sed and trailing colon by string substitution + get_full_modpath = f'modpath=$(module show {self.module_name} 2>&1 | ' + get_full_modpath += 'grep ".lua" | ' + get_full_modpath += 'sed "s/^[[:space:]]*//") && echo "FULL_MODULEPATH: ${modpath%:*}"' + self.postrun_cmds.append(get_full_modpath) + + @run_after('run') + def extract_runtime_info_from_log(self): + """Extracts the printed runtime info from the job log and logs it as reframe variables""" + # If EESSI_CVMFS_REPO environment variable was set, extract it and store it in self.cvmfs_repo_name + # Try block is needed to surpress sanity error if there is no match + try: + repo_name = sn.extractsingle(r'EESSI_CVMFS_REPO: /cvmfs/(?P.*)$', f'{self.stagedir}/{self.stdout}', + 'repo', str) + if repo_name: + self.cvmfs_repo_name = f'{repo_name}' + except SanityError: + pass + + try: + software_subdir = sn.extractsingle(r'EESSI_SOFTWARE_SUBDIR: (?P.*)$', + f'{self.stagedir}/{self.stdout}', 'subdir', str) + if software_subdir: + self.cvmfs_software_subdir = f'{software_subdir}' + except SanityError: + pass + + try: + module_path = sn.extractsingle(r'FULL_MODULEPATH: (?P.*)$', f'{self.stagedir}/{self.stdout}', + 'modpath', str) + print(f"Full modulepath: {module_path}") + if module_path: + self.full_modulepath = f'{module_path}' + except SanityError: + pass