From 5b91cfca5f62517003495005c7a5083134ad2021 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 4 Jul 2022 09:27:24 +0200 Subject: [PATCH 01/42] Allow multiple config files --- reframe/core/config.py | 125 +++++++++++++-------------------- reframe/core/runtime.py | 2 +- reframe/frontend/ci.py | 4 +- reframe/frontend/cli.py | 17 +++-- reframe/frontend/runreport.py | 2 +- reframe/schemas/runreport.json | 2 +- unittests/test_config.py | 90 +++++++++--------------- unittests/test_policies.py | 2 +- unittests/utility.py | 2 +- 9 files changed, 100 insertions(+), 146 deletions(-) diff --git a/reframe/core/config.py b/reframe/core/config.py index 6750696324..c4d6002463 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -81,9 +81,9 @@ def _hostname(use_fqdn, use_xthostname): class _SiteConfig: - def __init__(self, site_config, filename): - self._site_config = copy.deepcopy(site_config) - self._filename = filename + def __init__(self): + self._site_config = None + self._filenames = [] self._subconfigs = {} self._local_system = None self._sticky_options = {} @@ -106,6 +106,23 @@ def __init__(self, site_config, filename): f'invalid configuration schema: {schema_filename!r}' ) from e + def add_config(self, config, filename): + self._filenames.append(filename) + nc = copy.deepcopy(config) + if self._site_config is None: + self._site_config = nc + return self + + for i in ['systems', 'environments', 'scheduler', 'logging', + 'modes', 'general']: + if i in nc: + if i in self._site_config: + self._site_config[i] += nc[i] + else: + self._site_config[i] = nc[i] + + return self + def _pick_config(self): if self._local_system: return self._subconfigs[self._local_system] @@ -114,7 +131,7 @@ def _pick_config(self): def __repr__(self): return (f'{type(self).__name__}(site_config={self._site_config!r}, ' - f'filename={self._filename!r})') + f'filenames={self._filenames!r})') def __str__(self): return json.dumps(self._pick_config(), indent=2) @@ -242,25 +259,14 @@ def get(self, option, default=None): return value @property - def filename(self): - return self._filename + def filenames(self): + return self._filenames @property def subconfig_system(self): return self._local_system - @classmethod - def create(cls, filename): - _, ext = os.path.splitext(filename) - if ext == '.py': - return cls._create_from_python(filename) - elif ext == '.json': - return cls._create_from_json(filename) - else: - raise ConfigError(f"unknown configuration file type: '{filename}'") - - @classmethod - def _create_from_python(cls, filename): + def add_python_config(self, filename): try: mod = util.import_module_from_file(filename) except ImportError as e: @@ -284,10 +290,9 @@ def _create_from_python(cls, filename): f"not a valid Python configuration file: '{filename}'" ) - return _SiteConfig(mod.site_configuration, filename) + return self.add_config(mod.site_configuration, filename) - @classmethod - def _create_from_json(cls, filename): + def add_json_config(self, filename): with open(filename) as fp: try: config = json.loads(fp.read()) @@ -296,7 +301,7 @@ def _create_from_json(cls, filename): f"invalid JSON syntax in configuration file '{filename}'" ) from e - return _SiteConfig(config, filename) + self.add_config(config, filename) def _detect_system(self): getlogger().debug( @@ -325,27 +330,8 @@ def validate(self): try: jsonschema.validate(site_config, self._schema) except jsonschema.ValidationError as e: - raise ConfigError(f"could not validate configuration file: " - f"'{self._filename}'") from e - - # Make sure that system and partition names are unique - system_names = set() - for system in self._site_config['systems']: - sysname = system['name'] - if sysname in system_names: - raise ConfigError(f"system '{sysname}' already defined") - - system_names.add(sysname) - partition_names = set() - for part in system['partitions']: - partname = part['name'] - if partname in partition_names: - raise ConfigError( - f"partition '{partname}' already defined " - f"for system '{sysname}'" - ) - - partition_names.add(partname) + raise ConfigError(f"could not validate configuration files: " + f"'{self._filenames}'") from e def select_subconfig(self, system_fullname=None, ignore_resolve_errors=False): @@ -457,6 +443,7 @@ def select_subconfig(self, system_fullname=None, def convert_old_config(filename, newfilename=None): + #TODO fix this to get many files old_config = util.import_module_from_file(filename).settings converted = { 'systems': [], @@ -632,37 +619,21 @@ def handler_list(handler_config, basedir=None): return fp.name -def _find_config_file(): - # The order of elements is important, since it defines the priority - homedir = os.getenv('HOME') - prefixes = [os.path.join(homedir, '.reframe')] if homedir else [] - prefixes += [ - reframe.INSTALL_PREFIX, - '/etc/reframe.d' - ] - valid_exts = ['py', 'json'] - getlogger().debug('Looking for a suitable configuration file') - for d in prefixes: - if not d: - continue - - for ext in valid_exts: - filename = os.path.join(d, f'settings.{ext}') - getlogger().debug(f'Trying {filename!r}') - if os.path.exists(filename): - return filename - - return None - - -def load_config(filename=None): - if filename is None: - filename = _find_config_file() - if filename is None: - # Return the generic configuration - getlogger().debug('No configuration found; ' - 'falling back to a generic one') - return _SiteConfig(settings.site_configuration, '') - - getlogger().debug(f'Loading configuration file: {filename!r}') - return _SiteConfig.create(filename) + +def load_config(filenames=None): + ret = _SiteConfig() + getlogger().debug('Loading the generic configuration') + ret.add_config(settings.site_configuration, '') + if filenames: + getlogger().debug(f'Loading configuration files: {filenames!r}') + for filename in filenames: + _, ext = os.path.splitext(filename) + if ext == '.py': + ret.add_python_config(filename) + elif ext == '.json': + ret.add_json_config(filename) + else: + raise ConfigError(f"unknown configuration file type: " + f"'{filename}'") + + return ret diff --git a/reframe/core/runtime.py b/reframe/core/runtime.py index 1c34455d3c..9a60507751 100644 --- a/reframe/core/runtime.py +++ b/reframe/core/runtime.py @@ -420,7 +420,7 @@ def __init__(self, config_file, sysname=None, options=None): if config_file is None: _runtime_context = None else: - site_config = config.load_config(config_file) + site_config = config.load_config([config_file]) site_config.select_subconfig(sysname, ignore_resolve_errors=True) for opt, value in options.items(): site_config.add_sticky_option(opt, value) diff --git a/reframe/frontend/ci.py b/reframe/frontend/ci.py index 9c9c52a1ac..0f65996882 100644 --- a/reframe/frontend/ci.py +++ b/reframe/frontend/ci.py @@ -22,8 +22,8 @@ def _emit_gitlab_pipeline(testcases, child_pipeline_opts): verbosity = 'v' * config.get('general/0/verbose') def rfm_command(testcase): - if config.filename != '': - config_opt = f'-C {config.filename}' + if config.filenames != ['']: + config_opt = f'-C {config.filenames}' else: config_opt = '' diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index abd8550ce1..21a1b6a80d 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -488,8 +488,8 @@ def main(): # Miscellaneous options misc_options.add_argument( - '-C', '--config-file', action='store', - dest='config_file', metavar='FILE', + '-C', '--config-file', action='append', metavar='FILE', + dest='config_file', help='Set configuration file', envvar='RFM_CONFIG_FILE' ) @@ -680,7 +680,7 @@ def restrict_logging(): # to print pretty messages; logging will be reconfigured by user's # configuration later site_config = config.load_config( - os.path.join(reframe.INSTALL_PREFIX, 'reframe/core/settings.py') + [os.path.join(reframe.INSTALL_PREFIX, 'reframe/core/settings.py')] ) site_config.select_subconfig('generic') options.update_config(site_config) @@ -719,7 +719,10 @@ def restrict_logging(): try: try: printer.debug('Loading user configuration') - site_config = config.load_config(options.config_file) + if options.config_file is None: + site_config = config.load_config(None) + else: + site_config = config.load_config(options.config_file) except warnings.ReframeDeprecationWarning as e: printer.warning(e) converted = config.convert_old_config(options.config_file) @@ -727,7 +730,7 @@ def restrict_logging(): f"configuration file has been converted " f"to the new syntax here: '{converted}'" ) - site_config = config.load_config(converted) + site_config = config.load_config([converted]) site_config.validate() site_config.set_autodetect_meth( @@ -918,7 +921,7 @@ def print_infoline(param, value): session_info = { 'cmdline': ' '.join(sys.argv), - 'config_file': rt.site_config.filename, + 'config_files': rt.site_config.filenames, 'data_version': runreport.DATA_VERSION, 'hostname': socket.gethostname(), 'prefix_output': rt.output_prefix, @@ -937,7 +940,7 @@ def print_infoline(param, value): f"{session_info['user'] or ''}@{session_info['hostname']}" ) print_infoline('working directory', repr(session_info['workdir'])) - print_infoline('settings file', f"{session_info['config_file']!r}") + print_infoline('settings files', f"{session_info['config_files']!r}") print_infoline('check search path', f"{'(R) ' if loader.recurse else ''}" f"{':'.join(loader.load_path)!r}") diff --git a/reframe/frontend/runreport.py b/reframe/frontend/runreport.py index 25e08b6873..ba0216e2a0 100644 --- a/reframe/frontend/runreport.py +++ b/reframe/frontend/runreport.py @@ -18,7 +18,7 @@ # The schema data version # Major version bumps are expected to break the validation of previous schemas -DATA_VERSION = '2.1' +DATA_VERSION = '3.0' _SCHEMA = os.path.join(rfm.INSTALL_PREFIX, 'reframe/schemas/runreport.json') diff --git a/reframe/schemas/runreport.json b/reframe/schemas/runreport.json index d67db1d0cd..d917e12be8 100644 --- a/reframe/schemas/runreport.json +++ b/reframe/schemas/runreport.json @@ -108,7 +108,7 @@ "type": "object", "properties": { "cmdline": {"type": "string"}, - "config_file": {"type": ["string", "null"]}, + "config_files": {"type": ["string", "null"]}, "data_version": {"type": "string"}, "hostname": {"type": "string"}, "num_cases": {"type": "number"}, diff --git a/unittests/test_config.py b/unittests/test_config.py index 57fc912f6c..a88852c5e3 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -11,19 +11,14 @@ from reframe.core.systems import System -def test_load_config_fallback(monkeypatch): - monkeypatch.setattr(config, '_find_config_file', lambda: None) - site_config = config.load_config() - assert site_config.filename == '' - def test_load_config_python(): - config.load_config('reframe/core/settings.py') + config.load_config(['reframe/core/settings.py']) def test_load_config_python_old_syntax(): with pytest.raises(ConfigError): - config.load_config('unittests/resources/settings_old_syntax.py') + config.load_config(['unittests/resources/settings_old_syntax.py']) def test_load_config_nouser(monkeypatch): @@ -42,10 +37,10 @@ def test_convert_old_config(): converted = config.convert_old_config( 'unittests/resources/settings_old_syntax.py' ) - site_config = config.load_config(converted) + site_config = config.load_config([converted]) site_config.validate() - assert len(site_config.get('systems')) == 3 - assert len(site_config.get('logging')) == 2 + assert len(site_config.get('systems')) == 4 + assert len(site_config.get('logging')) == 3 site_config.select_subconfig('testsys') assert len(site_config.get('systems/0/partitions')) == 2 @@ -58,7 +53,7 @@ def test_load_config_python_invalid(tmp_path): pyfile.write_text('x = 1\n') with pytest.raises(ConfigError, match=r'not a valid Python configuration file'): - config.load_config(pyfile) + config.load_config([pyfile]) def test_load_config_json(tmp_path): @@ -66,20 +61,20 @@ def test_load_config_json(tmp_path): json_file = tmp_path / 'settings.json' json_file.write_text(json.dumps(settings.site_configuration, indent=4)) - site_config = config.load_config(json_file) - assert site_config.filename == json_file + site_config = config.load_config([json_file]) + assert site_config.filenames == ['', json_file] def test_load_config_json_invalid_syntax(tmp_path): json_file = tmp_path / 'settings.json' json_file.write_text('foo') with pytest.raises(ConfigError, match=r'invalid JSON syntax'): - config.load_config(json_file) + config.load_config([json_file]) def test_load_config_unknown_file(tmp_path): with pytest.raises(OSError): - config.load_config(tmp_path / 'foo.json') + config.load_config([tmp_path / 'foo.json']) def test_load_config_import_error(): @@ -87,7 +82,7 @@ def test_load_config_import_error(): # raised, which should be wrapped inside ConfigError with pytest.raises(ConfigError, match=r'could not load Python configuration file'): - config.load_config('reframe/core/foo.py') + config.load_config(['reframe/core/foo.py']) def test_load_config_unknown_filetype(tmp_path): @@ -96,54 +91,37 @@ def test_load_config_unknown_filetype(tmp_path): json_file = tmp_path / 'foo' json_file.write_text(json.dumps(settings.site_configuration, indent=4)) with pytest.raises(ConfigError, match=r'unknown configuration file type'): - config.load_config(json_file) + config.load_config([json_file]) def test_validate_fallback_config(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config.validate() def test_validate_unittest_config(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) site_config.validate() def test_validate_config_invalid_syntax(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['systems'][0]['name'] = 123 with pytest.raises(ConfigError, match=r'could not validate configuration file'): site_config.validate() -def test_validate_config_duplicate_systems(): - site_config = config.load_config('reframe/core/settings.py') - site_config['systems'].append(site_config['systems'][0]) - with pytest.raises(ConfigError, - match=r"system 'generic' already defined"): - site_config.validate() - - -def test_validate_config_duplicate_partitions(): - site_config = config.load_config('reframe/core/settings.py') - site_config['systems'][0]['partitions'].append( - site_config['systems'][0]['partitions'][0] - ) - with pytest.raises(ConfigError, - match=r"partition 'default' already defined"): - site_config.validate() - - def test_select_subconfig_autodetect(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config.select_subconfig() assert site_config['systems'][0]['name'] == 'generic' def test_select_subconfig_autodetect_failure(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['systems'][0]['hostnames'] = ['$^'] + site_config['systems'][1]['hostnames'] = ['$^'] with pytest.raises( ConfigError, match=(r'could not find a configuration entry ' @@ -153,7 +131,7 @@ def test_select_subconfig_autodetect_failure(): def test_select_subconfig_unknown_system(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) with pytest.raises( ConfigError, match=(r'could not find a configuration entry ' @@ -163,7 +141,7 @@ def test_select_subconfig_unknown_system(): def test_select_subconfig_unknown_partition(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) with pytest.raises( ConfigError, match=(r'could not find a configuration entry ' @@ -173,22 +151,24 @@ def test_select_subconfig_unknown_partition(): def test_select_subconfig_no_logging(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['logging'][0]['target_systems'] = ['foo'] + site_config['logging'][1]['target_systems'] = ['foo'] with pytest.raises(ConfigError, match=r"section 'logging' not defined"): site_config.select_subconfig() def test_select_subconfig_no_environments(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['environments'][0]['target_systems'] = ['foo'] + site_config['environments'][1]['target_systems'] = ['foo'] with pytest.raises(ConfigError, match=r"section 'environments' not defined"): site_config.select_subconfig() def test_select_subconfig_undefined_environment(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['systems'][0]['partitions'][0]['environs'] += ['foo', 'bar'] with pytest.raises( ConfigError, @@ -198,19 +178,19 @@ def test_select_subconfig_undefined_environment(): def test_select_subconfig_ignore_resolve_errors(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['systems'][0]['partitions'][0]['environs'] += ['foo', 'bar'] site_config.select_subconfig(ignore_resolve_errors=True) def test_select_subconfig_ignore_no_section_errors(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config['environments'][0]['target_systems'] = ['foo'] site_config.select_subconfig(ignore_resolve_errors=True) def test_select_subconfig(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) site_config.select_subconfig('testsys') assert len(site_config['systems']) == 1 assert len(site_config['systems'][0]['partitions']) == 2 @@ -259,9 +239,9 @@ def test_select_subconfig(): assert site_config.get('systems/0/partitions/0/max_jobs') == 8 assert len(site_config['environments']) == 7 assert site_config.get('environments/@PrgEnv-gnu/cc') == 'gcc' - assert site_config.get('environments/0/cxx') == 'g++' + assert site_config.get('environments/1/cxx') == 'g++' assert site_config.get('environments/@PrgEnv-cray/cc') == 'cc' - assert site_config.get('environments/1/cxx') == 'CC' + assert site_config.get('environments/2/cxx') == 'CC' assert (site_config.get('environments/@PrgEnv-cray/modules') == [{'name': 'PrgEnv-cray', 'collection': False, 'path': None}] ) @@ -291,7 +271,7 @@ def test_select_subconfig(): [['FOO_GPU', 'yes']]) assert site_config.get('systems/0/partitions/0/max_jobs') == 10 assert site_config.get('environments/@PrgEnv-gnu/cc') == 'cc' - assert site_config.get('environments/0/cxx') == 'CC' + assert site_config.get('environments/1/cxx') == 'CC' assert site_config.get('general/0/check_search_path') == ['c:d'] # Test default values for non-existent name-addressable objects @@ -313,7 +293,7 @@ def test_select_subconfig(): def test_select_subconfig_optional_section_absent(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config(['reframe/core/settings.py']) site_config.select_subconfig() assert site_config.get('general/0/colorize') is True assert site_config.get('general/0/git_timeout') == 5 @@ -321,7 +301,7 @@ def test_select_subconfig_optional_section_absent(): def test_sticky_options(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) site_config.select_subconfig('testsys:login') site_config.add_sticky_option('environments/cc', 'clang') site_config.add_sticky_option('modes/options', ['foo']) @@ -339,7 +319,7 @@ def test_sticky_options(): def test_system_create(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) site_config.select_subconfig('testsys:gpu') system = System.create(site_config) assert system.name == 'testsys' @@ -410,7 +390,7 @@ def test_hostname_autodetection(): # We set the autodetection method and we call `select_subconfig()` in # order to trigger the auto-detection - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) for use_xthostname in (True, False): for use_fqdn in (True, False): site_config.set_autodetect_meth('hostname', diff --git a/unittests/test_policies.py b/unittests/test_policies.py index 717c7bf1d4..32e360a60b 100644 --- a/unittests/test_policies.py +++ b/unittests/test_policies.py @@ -214,7 +214,7 @@ def _generate_runreport(run_stats, time_start, time_end): return { 'session_info': { 'cmdline': ' '.join(sys.argv), - 'config_file': rt.runtime().site_config.filename, + 'config_files': rt.runtime().site_config.filenames, 'data_version': runreport.DATA_VERSION, 'hostname': socket.gethostname(), 'num_cases': run_stats[0]['num_cases'], diff --git a/unittests/utility.py b/unittests/utility.py index de4ab22f89..1542786b1f 100644 --- a/unittests/utility.py +++ b/unittests/utility.py @@ -38,7 +38,7 @@ def init_runtime(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config(['unittests/resources/settings.py']) site_config.select_subconfig('generic') rt.init_runtime(site_config) From 8d267da028e94ba7467aa441f935a651198e3ff3 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Tue, 12 Jul 2022 11:25:40 +0200 Subject: [PATCH 02/42] Update runreport schema --- reframe/schemas/runreport.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reframe/schemas/runreport.json b/reframe/schemas/runreport.json index 99e943e10b..4a11478de0 100644 --- a/reframe/schemas/runreport.json +++ b/reframe/schemas/runreport.json @@ -110,7 +110,10 @@ "type": "object", "properties": { "cmdline": {"type": "string"}, - "config_files": {"type": ["string", "null"]}, + "config_files": { + "type": "array", + "items": {"type": "string"} + }, "data_version": {"type": "string"}, "hostname": {"type": "string"}, "num_cases": {"type": "number"}, From 7fcfdcaee0f99007bace02dae1345347361f3663 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 25 Jul 2022 10:55:15 +0200 Subject: [PATCH 03/42] Address PR comments --- reframe/core/config.py | 241 +++++-------------------------------- reframe/core/runtime.py | 2 +- reframe/frontend/ci.py | 6 +- reframe/frontend/cli.py | 43 +------ unittests/test_config.py | 70 ++++------- unittests/test_policies.py | 2 +- unittests/utility.py | 2 +- 7 files changed, 64 insertions(+), 302 deletions(-) diff --git a/reframe/core/config.py b/reframe/core/config.py index c4d6002463..f657bfbd5b 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -83,7 +83,7 @@ def _hostname(use_fqdn, use_xthostname): class _SiteConfig: def __init__(self): self._site_config = None - self._filenames = [] + self._sources = [] self._subconfigs = {} self._local_system = None self._sticky_options = {} @@ -106,22 +106,21 @@ def __init__(self): f'invalid configuration schema: {schema_filename!r}' ) from e - def add_config(self, config, filename): - self._filenames.append(filename) + def update_config(self, config, filename): + self._sources.append(filename) nc = copy.deepcopy(config) if self._site_config is None: self._site_config = nc return self - for i in ['systems', 'environments', 'scheduler', 'logging', - 'modes', 'general']: - if i in nc: - if i in self._site_config: - self._site_config[i] += nc[i] - else: - self._site_config[i] = nc[i] - - return self + for sec in nc.keys(): + if sec not in self._site_config: + self._site_config[sec] = nc[sec] + elif sec == 'systems': + # Systems have to be inserted in the beginning of the list + self._site_config[sec] = nc[sec] + self._site_config[sec] + else: + self._site_config[sec] += nc[sec] def _pick_config(self): if self._local_system: @@ -131,7 +130,7 @@ def _pick_config(self): def __repr__(self): return (f'{type(self).__name__}(site_config={self._site_config!r}, ' - f'filenames={self._filenames!r})') + f'sources={self._sources!r})') def __str__(self): return json.dumps(self._pick_config(), indent=2) @@ -259,14 +258,14 @@ def get(self, option, default=None): return value @property - def filenames(self): - return self._filenames + def sources(self): + return self._sources @property def subconfig_system(self): return self._local_system - def add_python_config(self, filename): + def load_python_config(self, filename): try: mod = util.import_module_from_file(filename) except ImportError as e: @@ -290,9 +289,9 @@ def add_python_config(self, filename): f"not a valid Python configuration file: '{filename}'" ) - return self.add_config(mod.site_configuration, filename) + self.update_config(mod.site_configuration, filename) - def add_json_config(self, filename): + def load_json_config(self, filename): with open(filename) as fp: try: config = json.loads(fp.read()) @@ -301,7 +300,7 @@ def add_json_config(self, filename): f"invalid JSON syntax in configuration file '{filename}'" ) from e - self.add_config(config, filename) + self.update_config(config, filename) def _detect_system(self): getlogger().debug( @@ -331,7 +330,7 @@ def validate(self): jsonschema.validate(site_config, self._schema) except jsonschema.ValidationError as e: raise ConfigError(f"could not validate configuration files: " - f"'{self._filenames}'") from e + f"'{self._sources}'") from e def select_subconfig(self, system_fullname=None, ignore_resolve_errors=False): @@ -442,198 +441,18 @@ def select_subconfig(self, system_fullname=None, self._subconfigs[system_fullname] = local_config -def convert_old_config(filename, newfilename=None): - #TODO fix this to get many files - old_config = util.import_module_from_file(filename).settings - converted = { - 'systems': [], - 'environments': [], - 'logging': [], - } - perflogdir = {} - old_systems = old_config.site_configuration['systems'].items() - for sys_name, sys_spec in old_systems: - sys_dict = {'name': sys_name} - - system_perflogdir = sys_spec.pop('perflogdir', None) - perflogdir.setdefault(system_perflogdir, []) - perflogdir[system_perflogdir].append(sys_name) - - sys_dict.update(sys_spec) - - # hostnames is now a required property - if 'hostnames' not in sys_spec: - sys_dict['hostnames'] = [] - - # Make variables dictionary into a list of lists - if 'variables' in sys_spec: - sys_dict['variables'] = [ - [vname, v] for vname, v in sys_dict['variables'].items() - ] - - # Make partitions dictionary into a list - if 'partitions' in sys_spec: - sys_dict['partitions'] = [] - for pname, p in sys_spec['partitions'].items(): - new_p = {'name': pname} - new_p.update(p) - if p['scheduler'] == 'nativeslurm': - new_p['scheduler'] = 'slurm' - new_p['launcher'] = 'srun' - elif p['scheduler'] == 'local': - new_p['scheduler'] = 'local' - new_p['launcher'] = 'local' - else: - sched, launcher, *_ = p['scheduler'].split('+') - new_p['scheduler'] = sched - new_p['launcher'] = launcher - - # Make resources dictionary into a list - if 'resources' in p: - new_p['resources'] = [ - {'name': rname, 'options': r} - for rname, r in p['resources'].items() - ] - - # Make variables dictionary into a list of lists - if 'variables' in p: - new_p['variables'] = [ - [vname, v] for vname, v in p['variables'].items() - ] - - if 'container_platforms' in p: - new_p['container_platforms'] = [] - for cname, c in p['container_platforms'].items(): - new_c = {'type': cname} - new_c.update(c) - if 'variables' in c: - new_c['variables'] = [ - [vn, v] for vn, v in c['variables'].items() - ] - - new_p['container_platforms'].append(new_c) - - sys_dict['partitions'].append(new_p) - - converted['systems'].append(sys_dict) - - old_environs = old_config.site_configuration['environments'].items() - for env_target, env_entries in old_environs: - for ename, e in env_entries.items(): - new_env = {'name': ename} - if env_target != '*': - new_env['target_systems'] = [env_target] - - new_env.update(e) - - # Convert variables dictionary to a list of lists - if 'variables' in e: - new_env['variables'] = [ - [vname, v] for vname, v in e['variables'].items() - ] - - # Type attribute is not used anymore - if 'type' in new_env: - del new_env['type'] - - converted['environments'].append(new_env) - - if 'modes' in old_config.site_configuration: - converted['modes'] = [] - old_modes = old_config.site_configuration['modes'].items() - for target_mode, mode_entries in old_modes: - for mname, m in mode_entries.items(): - new_mode = {'name': mname, 'options': m} - if target_mode != '*': - new_mode['target_systems'] = [target_mode] - - converted['modes'].append(new_mode) - - def handler_list(handler_config, basedir=None): - ret = [] - for h in handler_config: - new_h = h.copy() - new_h['level'] = h['level'].lower() - if h['type'] == 'graylog': - # `host` and `port` attribute are converted to `address` - new_h['address'] = h['host'] - if 'port' in h: - new_h['address'] += ':' + h['port'] - elif h['type'] == 'filelog' and basedir is not None: - new_h['basedir'] = basedir - - ret.append(new_h) - - return ret - - for basedir, target_systems in perflogdir.items(): - converted['logging'].append( - { - 'level': old_config.logging_config['level'].lower(), - 'handlers': handler_list( - old_config.logging_config['handlers'] - ), - 'handlers_perflog': handler_list( - old_config.perf_logging_config['handlers'], - basedir=basedir - ), - 'target_systems': target_systems - } - ) - if basedir is None: - del converted['logging'][-1]['target_systems'] - - converted['general'] = [{}] - if hasattr(old_config, 'checks_path'): - converted['general'][0][ - 'check_search_path' - ] = old_config.checks_path - - if hasattr(old_config, 'checks_path_recurse'): - converted['general'][0][ - 'check_search_recursive' - ] = old_config.checks_path_recurse - - if converted['general'] == [{}]: - del converted['general'] - - contents = (f"#\n# This file was automatically generated " - f"by ReFrame based on '{filename}'.\n#\n\n" - f"site_configuration = {util.ppretty(converted)}\n") - - contents = '\n'.join(l if len(l) < 80 else f'{l} # noqa: E501' - for l in contents.split('\n')) - - if newfilename: - with open(newfilename, 'w') as fp: - if newfilename.endswith('.json'): - json.dump(converted, fp, indent=4) - else: - fp.write(contents) - - else: - with tempfile.NamedTemporaryFile(mode='w', suffix='.py', - delete=False) as fp: - fp.write(contents) - - return fp.name - - - -def load_config(filenames=None): +def load_config(*filenames): ret = _SiteConfig() getlogger().debug('Loading the generic configuration') - ret.add_config(settings.site_configuration, '') - if filenames: - getlogger().debug(f'Loading configuration files: {filenames!r}') - for filename in filenames: - _, ext = os.path.splitext(filename) - if ext == '.py': - ret.add_python_config(filename) - elif ext == '.json': - ret.add_json_config(filename) - else: - raise ConfigError(f"unknown configuration file type: " - f"'{filename}'") + ret.update_config(settings.site_configuration, '') + for f in filenames: + getlogger().debug(f'Loading configuration file: {filenames!r}') + _, ext = os.path.splitext(f) + if ext == '.py': + ret.load_python_config(f) + elif ext == '.json': + ret.load_json_config(f) + else: + raise ConfigError(f"unknown configuration file type: '{f}'") return ret diff --git a/reframe/core/runtime.py b/reframe/core/runtime.py index 9a60507751..1c34455d3c 100644 --- a/reframe/core/runtime.py +++ b/reframe/core/runtime.py @@ -420,7 +420,7 @@ def __init__(self, config_file, sysname=None, options=None): if config_file is None: _runtime_context = None else: - site_config = config.load_config([config_file]) + site_config = config.load_config(config_file) site_config.select_subconfig(sysname, ignore_resolve_errors=True) for opt, value in options.items(): site_config.add_sticky_option(opt, value) diff --git a/reframe/frontend/ci.py b/reframe/frontend/ci.py index 0f65996882..bd48df85ef 100644 --- a/reframe/frontend/ci.py +++ b/reframe/frontend/ci.py @@ -22,10 +22,8 @@ def _emit_gitlab_pipeline(testcases, child_pipeline_opts): verbosity = 'v' * config.get('general/0/verbose') def rfm_command(testcase): - if config.filenames != ['']: - config_opt = f'-C {config.filenames}' - else: - config_opt = '' + # Ignore the first argument, it should be '' + config_opt = ' '.join([f'-C {arg}' for arg in config.sources[1:]]) report_file = f'{testcase.check.unique_name}-report.json' if testcase.level: diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index fb80556557..a9c47fd0b6 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -526,10 +526,6 @@ def main(): '--system', action='store', help='Load configuration for SYSTEM', envvar='RFM_SYSTEM' ) - misc_options.add_argument( - '--upgrade-config-file', action='store', metavar='OLD[:NEW]', - help='Upgrade ReFrame 2.x configuration file to ReFrame 3.x syntax' - ) misc_options.add_argument( '-V', '--version', action='version', version=osext.reframe_version() ) @@ -688,7 +684,7 @@ def restrict_logging(): # to print pretty messages; logging will be reconfigured by user's # configuration later site_config = config.load_config( - [os.path.join(reframe.INSTALL_PREFIX, 'reframe/core/settings.py')] + os.path.join(reframe.INSTALL_PREFIX, 'reframe/core/settings.py') ) site_config.select_subconfig('generic') options.update_config(site_config) @@ -705,41 +701,10 @@ def restrict_logging(): ) os.environ['RFM_GRAYLOG_ADDRESS'] = os.getenv('RFM_GRAYLOG_SERVER') - if options.upgrade_config_file is not None: - old_config, *new_config = options.upgrade_config_file.split( - ':', maxsplit=1 - ) - new_config = new_config[0] if new_config else None - - try: - new_config = config.convert_old_config(old_config, new_config) - except Exception as e: - printer.error(f'could not convert file: {e}') - sys.exit(1) - - printer.info( - f'Conversion successful! ' - f'The converted file can be found at {new_config!r}.' - ) - sys.exit(0) - # Now configure ReFrame according to the user configuration file try: - try: - printer.debug('Loading user configuration') - if options.config_file is None: - site_config = config.load_config(None) - else: - site_config = config.load_config(options.config_file) - except warnings.ReframeDeprecationWarning as e: - printer.warning(e) - converted = config.convert_old_config(options.config_file) - printer.warning( - f"configuration file has been converted " - f"to the new syntax here: '{converted}'" - ) - site_config = config.load_config([converted]) - + printer.debug('Loading user configuration') + site_config = config.load_config(*options.config_file) site_config.validate() site_config.set_autodetect_meth( options.autodetect_method, @@ -929,7 +894,7 @@ def print_infoline(param, value): session_info = { 'cmdline': ' '.join(sys.argv), - 'config_files': rt.site_config.filenames, + 'config_files': rt.site_config.sources, 'data_version': runreport.DATA_VERSION, 'hostname': socket.gethostname(), 'prefix_output': rt.output_prefix, diff --git a/unittests/test_config.py b/unittests/test_config.py index a88852c5e3..9da1d1eaf2 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -13,12 +13,7 @@ def test_load_config_python(): - config.load_config(['reframe/core/settings.py']) - - -def test_load_config_python_old_syntax(): - with pytest.raises(ConfigError): - config.load_config(['unittests/resources/settings_old_syntax.py']) + config.load_config('reframe/core/settings.py') def test_load_config_nouser(monkeypatch): @@ -33,27 +28,12 @@ def test_load_config_nouser(monkeypatch): config.load_config() -def test_convert_old_config(): - converted = config.convert_old_config( - 'unittests/resources/settings_old_syntax.py' - ) - site_config = config.load_config([converted]) - site_config.validate() - assert len(site_config.get('systems')) == 4 - assert len(site_config.get('logging')) == 3 - - site_config.select_subconfig('testsys') - assert len(site_config.get('systems/0/partitions')) == 2 - assert len(site_config.get('modes')) == 1 - assert len(site_config['environments']) == 6 - - def test_load_config_python_invalid(tmp_path): pyfile = tmp_path / 'settings.py' pyfile.write_text('x = 1\n') with pytest.raises(ConfigError, match=r'not a valid Python configuration file'): - config.load_config([pyfile]) + config.load_config(pyfile) def test_load_config_json(tmp_path): @@ -61,20 +41,20 @@ def test_load_config_json(tmp_path): json_file = tmp_path / 'settings.json' json_file.write_text(json.dumps(settings.site_configuration, indent=4)) - site_config = config.load_config([json_file]) - assert site_config.filenames == ['', json_file] + site_config = config.load_config(json_file) + assert site_config.sources == ['', json_file] def test_load_config_json_invalid_syntax(tmp_path): json_file = tmp_path / 'settings.json' json_file.write_text('foo') with pytest.raises(ConfigError, match=r'invalid JSON syntax'): - config.load_config([json_file]) + config.load_config(json_file) def test_load_config_unknown_file(tmp_path): with pytest.raises(OSError): - config.load_config([tmp_path / 'foo.json']) + config.load_config(tmp_path / 'foo.json') def test_load_config_import_error(): @@ -82,7 +62,7 @@ def test_load_config_import_error(): # raised, which should be wrapped inside ConfigError with pytest.raises(ConfigError, match=r'could not load Python configuration file'): - config.load_config(['reframe/core/foo.py']) + config.load_config('reframe/core/foo.py') def test_load_config_unknown_filetype(tmp_path): @@ -91,21 +71,21 @@ def test_load_config_unknown_filetype(tmp_path): json_file = tmp_path / 'foo' json_file.write_text(json.dumps(settings.site_configuration, indent=4)) with pytest.raises(ConfigError, match=r'unknown configuration file type'): - config.load_config([json_file]) + config.load_config(json_file) def test_validate_fallback_config(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config.validate() def test_validate_unittest_config(): - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') site_config.validate() def test_validate_config_invalid_syntax(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['systems'][0]['name'] = 123 with pytest.raises(ConfigError, match=r'could not validate configuration file'): @@ -113,13 +93,13 @@ def test_validate_config_invalid_syntax(): def test_select_subconfig_autodetect(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config.select_subconfig() assert site_config['systems'][0]['name'] == 'generic' def test_select_subconfig_autodetect_failure(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['systems'][0]['hostnames'] = ['$^'] site_config['systems'][1]['hostnames'] = ['$^'] with pytest.raises( @@ -131,7 +111,7 @@ def test_select_subconfig_autodetect_failure(): def test_select_subconfig_unknown_system(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') with pytest.raises( ConfigError, match=(r'could not find a configuration entry ' @@ -141,7 +121,7 @@ def test_select_subconfig_unknown_system(): def test_select_subconfig_unknown_partition(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') with pytest.raises( ConfigError, match=(r'could not find a configuration entry ' @@ -151,7 +131,7 @@ def test_select_subconfig_unknown_partition(): def test_select_subconfig_no_logging(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['logging'][0]['target_systems'] = ['foo'] site_config['logging'][1]['target_systems'] = ['foo'] with pytest.raises(ConfigError, match=r"section 'logging' not defined"): @@ -159,7 +139,7 @@ def test_select_subconfig_no_logging(): def test_select_subconfig_no_environments(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['environments'][0]['target_systems'] = ['foo'] site_config['environments'][1]['target_systems'] = ['foo'] with pytest.raises(ConfigError, @@ -168,7 +148,7 @@ def test_select_subconfig_no_environments(): def test_select_subconfig_undefined_environment(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['systems'][0]['partitions'][0]['environs'] += ['foo', 'bar'] with pytest.raises( ConfigError, @@ -178,19 +158,19 @@ def test_select_subconfig_undefined_environment(): def test_select_subconfig_ignore_resolve_errors(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['systems'][0]['partitions'][0]['environs'] += ['foo', 'bar'] site_config.select_subconfig(ignore_resolve_errors=True) def test_select_subconfig_ignore_no_section_errors(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config['environments'][0]['target_systems'] = ['foo'] site_config.select_subconfig(ignore_resolve_errors=True) def test_select_subconfig(): - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') site_config.select_subconfig('testsys') assert len(site_config['systems']) == 1 assert len(site_config['systems'][0]['partitions']) == 2 @@ -293,7 +273,7 @@ def test_select_subconfig(): def test_select_subconfig_optional_section_absent(): - site_config = config.load_config(['reframe/core/settings.py']) + site_config = config.load_config('reframe/core/settings.py') site_config.select_subconfig() assert site_config.get('general/0/colorize') is True assert site_config.get('general/0/git_timeout') == 5 @@ -301,7 +281,7 @@ def test_select_subconfig_optional_section_absent(): def test_sticky_options(): - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') site_config.select_subconfig('testsys:login') site_config.add_sticky_option('environments/cc', 'clang') site_config.add_sticky_option('modes/options', ['foo']) @@ -319,7 +299,7 @@ def test_sticky_options(): def test_system_create(): - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') site_config.select_subconfig('testsys:gpu') system = System.create(site_config) assert system.name == 'testsys' @@ -390,7 +370,7 @@ def test_hostname_autodetection(): # We set the autodetection method and we call `select_subconfig()` in # order to trigger the auto-detection - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') for use_xthostname in (True, False): for use_fqdn in (True, False): site_config.set_autodetect_meth('hostname', diff --git a/unittests/test_policies.py b/unittests/test_policies.py index 32e360a60b..8384423904 100644 --- a/unittests/test_policies.py +++ b/unittests/test_policies.py @@ -214,7 +214,7 @@ def _generate_runreport(run_stats, time_start, time_end): return { 'session_info': { 'cmdline': ' '.join(sys.argv), - 'config_files': rt.runtime().site_config.filenames, + 'config_files': rt.runtime().site_config.sources, 'data_version': runreport.DATA_VERSION, 'hostname': socket.gethostname(), 'num_cases': run_stats[0]['num_cases'], diff --git a/unittests/utility.py b/unittests/utility.py index 1542786b1f..de4ab22f89 100644 --- a/unittests/utility.py +++ b/unittests/utility.py @@ -38,7 +38,7 @@ def init_runtime(): - site_config = config.load_config(['unittests/resources/settings.py']) + site_config = config.load_config('unittests/resources/settings.py') site_config.select_subconfig('generic') rt.init_runtime(site_config) From eff3c83654bf336bfa7e151f4dc3aa9723dab60a Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 8 Aug 2022 11:24:18 +0200 Subject: [PATCH 04/42] Remove unused imports --- reframe/core/config.py | 1 - reframe/frontend/cli.py | 1 - 2 files changed, 2 deletions(-) diff --git a/reframe/core/config.py b/reframe/core/config.py index f657bfbd5b..82cc764064 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -12,7 +12,6 @@ import os import re import socket -import tempfile import reframe import reframe.core.settings as settings diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index a9c47fd0b6..5346b7824d 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -18,7 +18,6 @@ import reframe.core.exceptions as errors import reframe.core.logging as logging import reframe.core.runtime as runtime -import reframe.core.warnings as warnings import reframe.frontend.argparse as argparse import reframe.frontend.autodetect as autodetect import reframe.frontend.ci as ci From 8cd270317bd8018de9043b959f0f00703c6a0eeb Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 8 Aug 2022 14:15:28 +0200 Subject: [PATCH 05/42] Allow multiple config files from envvar --- reframe/frontend/cli.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 5346b7824d..5a5ae0369c 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -498,7 +498,7 @@ def main(): '-C', '--config-file', action='append', metavar='FILE', dest='config_file', help='Set configuration file', - envvar='RFM_CONFIG_FILE' + envvar='RFM_CONFIG_FILE :' ) misc_options.add_argument( '--detect-host-topology', action='store', nargs='?', const='-', @@ -703,7 +703,10 @@ def restrict_logging(): # Now configure ReFrame according to the user configuration file try: printer.debug('Loading user configuration') - site_config = config.load_config(*options.config_file) + # Cannot set the variable to [] in the argparser because it won't take + # into account the environmane variable + conf_file = options.config_file if options.config_file else [] + site_config = config.load_config(*conf_file) site_config.validate() site_config.set_autodetect_meth( options.autodetect_method, From 9ccc45eebb5e0d781d28cc2a1f3edadff2ed18de Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 8 Aug 2022 14:52:05 +0200 Subject: [PATCH 06/42] Move setting in config directory --- unittests/resources/{ => config}/settings.py | 0 unittests/resources/settings_old_syntax.py | 174 ------------------- unittests/test_cli.py | 2 +- unittests/test_config.py | 10 +- unittests/utility.py | 4 +- 5 files changed, 8 insertions(+), 182 deletions(-) rename unittests/resources/{ => config}/settings.py (100%) delete mode 100644 unittests/resources/settings_old_syntax.py diff --git a/unittests/resources/settings.py b/unittests/resources/config/settings.py similarity index 100% rename from unittests/resources/settings.py rename to unittests/resources/config/settings.py diff --git a/unittests/resources/settings_old_syntax.py b/unittests/resources/settings_old_syntax.py deleted file mode 100644 index 9ec0fa4b98..0000000000 --- a/unittests/resources/settings_old_syntax.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) -# ReFrame Project Developers. See the top-level LICENSE file for details. -# -# SPDX-License-Identifier: BSD-3-Clause - -# -# ReFrame settings for use in the unit tests (old syntax) -# - - -class ReframeSettings: - job_poll_intervals = [1, 2, 3] - job_submit_timeout = 60 - checks_path = ['checks/'] - checks_path_recurse = True - site_configuration = { - 'systems': { - # Generic system configuration that allows to run ReFrame locally - # on any system. - 'generic': { - 'descr': 'Generic example system', - 'hostnames': ['localhost'], - 'partitions': { - 'login': { - 'scheduler': 'local', - 'modules': [], - 'access': [], - 'environs': ['builtin-gcc'], - 'descr': 'Login nodes' - }, - } - }, - 'testsys': { - # A fake system simulating a possible cluster configuration, in - # order to test different aspects of the framework. - 'descr': 'Fake system for unit tests', - 'hostnames': ['testsys'], - 'prefix': '.rfm_testing', - 'resourcesdir': '.rfm_testing/resources', - 'perflogdir': '.rfm_testing/perflogs', - 'modules': ['foo/1.0'], - 'variables': {'FOO_CMD': 'foobar'}, - 'partitions': { - 'login': { - 'scheduler': 'local', - 'resources': {}, - 'environs': ['PrgEnv-cray', - 'PrgEnv-gnu', - 'builtin-gcc'], - 'descr': 'Login nodes' - }, - 'gpu': { - 'scheduler': 'nativeslurm', - 'modules': ['foogpu'], - 'variables': {'FOO_GPU': 'yes'}, - 'resources': { - 'gpu': ['--gres=gpu:{num_gpus_per_node}'], - 'datawarp': [ - '#DW jobdw capacity={capacity}', - '#DW stage_in source={stagein_src}' - ] - }, - 'access': [], - 'environs': ['PrgEnv-gnu', 'builtin-gcc'], - 'descr': 'GPU partition', - } - } - }, - 'sys0': { - # System used for dependency checking - 'descr': 'System for checking test dependencies', - 'hostnames': [r'sys\d+'], - 'partitions': { - 'p0': { - 'scheduler': 'local', - 'environs': ['e0', 'e1'], - }, - 'p1': { - 'scheduler': 'local', - 'environs': ['e0', 'e1'], - } - } - } - }, - 'environments': { - 'testsys:login': { - 'PrgEnv-gnu': { - 'modules': ['PrgEnv-gnu'], - 'cc': 'gcc', - 'cxx': 'g++', - 'ftn': 'gfortran', - }, - }, - '*': { - 'PrgEnv-gnu': { - 'modules': ['PrgEnv-gnu'], - }, - 'PrgEnv-cray': { - 'modules': ['PrgEnv-cray'], - }, - 'builtin': { - 'cc': 'cc', - 'cxx': '', - 'ftn': '', - }, - 'builtin-gcc': { - 'cc': 'gcc', - 'cxx': 'g++', - 'ftn': 'gfortran', - }, - 'e0': { - 'modules': ['m0'], - }, - 'e1': { - 'modules': ['m1'], - }, - } - }, - 'modes': { - '*': { - 'unittest': [ - '-c', 'unittests/resources/checks/hellocheck.py', - '-p', 'builtin-gcc', - '--force-local' - ] - } - } - } - - logging_config = { - 'level': 'DEBUG', - 'handlers': [ - { - 'type': 'file', - 'name': '.rfm_unittest.log', - 'level': 'DEBUG', - 'format': ('[%(asctime)s] %(levelname)s: ' - '%(check_name)s: %(message)s'), - 'datefmt': '%FT%T', - 'append': False, - }, - { - 'type': 'stream', - 'name': 'stdout', - 'level': 'INFO', - 'format': '%(message)s' - }, - ] - } - - perf_logging_config = { - 'level': 'DEBUG', - 'handlers': [ - { - 'type': 'filelog', - 'prefix': '%(check_system)s/%(check_partition)s', - 'level': 'INFO', - 'format': ( - '%(check_job_completion_time)s|reframe %(version)s|' - '%(check_info)s|jobid=%(check_jobid)s|' - '%(check_perf_var)s=%(check_perf_value)s|' - 'ref=%(check_perf_ref)s ' - '(l=%(check_perf_lower_thres)s, ' - 'u=%(check_perf_upper_thres)s)|' - '%(check_perf_unit)s' - ), - 'datefmt': '%FT%T%:z', - 'append': True - } - ] - } - - -settings = ReframeSettings() diff --git a/unittests/test_cli.py b/unittests/test_cli.py index 0136b66fe9..5fd1f64ff2 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -62,7 +62,7 @@ def _run_reframe(system='generic:default', action='run', more_options=None, mode=None, - config_file='unittests/resources/settings.py', + config_file='unittests/resources/config/settings.py', perflogdir=str(perflogdir)): import reframe.frontend.cli as cli diff --git a/unittests/test_config.py b/unittests/test_config.py index 9da1d1eaf2..f24b448be9 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -80,7 +80,7 @@ def test_validate_fallback_config(): def test_validate_unittest_config(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') site_config.validate() @@ -170,7 +170,7 @@ def test_select_subconfig_ignore_no_section_errors(): def test_select_subconfig(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') site_config.select_subconfig('testsys') assert len(site_config['systems']) == 1 assert len(site_config['systems'][0]['partitions']) == 2 @@ -281,7 +281,7 @@ def test_select_subconfig_optional_section_absent(): def test_sticky_options(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') site_config.select_subconfig('testsys:login') site_config.add_sticky_option('environments/cc', 'clang') site_config.add_sticky_option('modes/options', ['foo']) @@ -299,7 +299,7 @@ def test_sticky_options(): def test_system_create(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') site_config.select_subconfig('testsys:gpu') system = System.create(site_config) assert system.name == 'testsys' @@ -370,7 +370,7 @@ def test_hostname_autodetection(): # We set the autodetection method and we call `select_subconfig()` in # order to trigger the auto-detection - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') for use_xthostname in (True, False): for use_fqdn in (True, False): site_config.set_autodetect_meth('hostname', diff --git a/unittests/utility.py b/unittests/utility.py index de4ab22f89..076cbf02a9 100644 --- a/unittests/utility.py +++ b/unittests/utility.py @@ -30,7 +30,7 @@ BUILTIN_CONFIG_FILE = 'reframe/core/settings.py' # Unit tests site configuration -TEST_CONFIG_FILE = 'unittests/resources/settings.py' +TEST_CONFIG_FILE = 'unittests/resources/config/settings.py' # User supplied configuration file and site configuration USER_CONFIG_FILE = None @@ -38,7 +38,7 @@ def init_runtime(): - site_config = config.load_config('unittests/resources/settings.py') + site_config = config.load_config('unittests/resources/config/settings.py') site_config.select_subconfig('generic') rt.init_runtime(site_config) From 2a3a96c8f5c36e4fd73c09a54259cd399da9ec68 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Wed, 17 Aug 2022 09:50:17 +0200 Subject: [PATCH 07/42] Add unittests for multiple configurations --- unittests/resources/config/settings-part1.py | 99 ++++++++++++ unittests/resources/config/settings-part2.py | 155 +++++++++++++++++++ unittests/resources/config/settings-part3.py | 94 +++++++++++ unittests/test_config.py | 39 +++-- 4 files changed, 377 insertions(+), 10 deletions(-) create mode 100644 unittests/resources/config/settings-part1.py create mode 100644 unittests/resources/config/settings-part2.py create mode 100644 unittests/resources/config/settings-part3.py diff --git a/unittests/resources/config/settings-part1.py b/unittests/resources/config/settings-part1.py new file mode 100644 index 0000000000..7af5d32bf4 --- /dev/null +++ b/unittests/resources/config/settings-part1.py @@ -0,0 +1,99 @@ +# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# ReFrame Project Developers. See the top-level LICENSE file for details. +# +# SPDX-License-Identifier: BSD-3-Clause + +# +# Configuration file just for unit testing +# + +site_configuration = { + 'systems': [ + { + 'name': 'sys0', + 'descr': 'System for testing check dependencies', + 'hostnames': [r'sys\d+'], + 'partitions': [ + { + 'name': 'p0', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['e0', 'e1'] + }, + { + 'name': 'p1', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['e0', 'e1'] + } + + ] + }, + { + 'name': 'sys1', + 'descr': 'System for testing fixtures', + 'hostnames': [r'sys\d+'], + 'partitions': [ + { + 'name': 'p0', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['e0', 'e1', 'e3'] + }, + { + 'name': 'p1', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['e0', 'e1', 'e2'] + } + + ] + } + ], + 'environments': [ + { + 'name': 'PrgEnv-gnu', + 'modules': [ + {'name': 'PrgEnv-gnu', 'collection': False, 'path': None} + ], + 'extras': { + 'foo': 2, + 'bar': 'y' + }, + }, + { + 'name': 'PrgEnv-gnu', + 'modules': ['PrgEnv-gnu'], + 'cc': 'gcc', + 'cxx': 'g++', + 'ftn': 'gfortran', + 'features': ['cxx14'], + 'extras': { + 'foo': 1, + 'bar': 'x' + }, + 'target_systems': ['testsys:login'] + }, + { + 'name': 'PrgEnv-cray', + 'modules': ['PrgEnv-cray'], + 'features': ['cxx14', 'mpi'], + }, + ], + 'modes': [ + { + 'name': 'unittest', + 'options': [ + '-c unittests/resources/checks/hellocheck.py', + '-p builtin', + '--force-local' + ] + } + ], + 'general': [ + { + 'check_search_path': ['a:b'], + 'target_systems': ['testsys:login'] + }, + ] +} diff --git a/unittests/resources/config/settings-part2.py b/unittests/resources/config/settings-part2.py new file mode 100644 index 0000000000..44127e4ded --- /dev/null +++ b/unittests/resources/config/settings-part2.py @@ -0,0 +1,155 @@ +# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# ReFrame Project Developers. See the top-level LICENSE file for details. +# +# SPDX-License-Identifier: BSD-3-Clause + +# +# Configuration file just for unit testing +# + +site_configuration = { + 'systems': [ + { + 'name': 'testsys', + 'descr': 'Fake system for unit tests', + 'hostnames': ['testsys'], + 'prefix': '.rfm_testing', + 'resourcesdir': '.rfm_testing/resources', + 'modules': ['foo/1.0'], + 'variables': [['FOO_CMD', 'foobar']], + 'partitions': [ + { + 'name': 'login', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['PrgEnv-cray', 'PrgEnv-gnu'], + 'descr': 'Login nodes', + 'features': ['cross_compile'], + 'container_platforms': [ + {'type': 'Sarus'}, + {'type': 'Docker', 'default': True}, + {'type': 'Singularity'} + ] + }, + { + 'name': 'gpu', + 'descr': 'GPU partition', + 'scheduler': 'slurm', + 'launcher': 'srun', + + # Use the extensive syntax here + 'modules': [ + {'name': 'foogpu', 'collection': False, 'path': '/foo'} + ], + 'variables': [['FOO_GPU', 'yes']], + 'resources': [ + { + 'name': 'gpu', + 'options': ['--gres=gpu:{num_gpus_per_node}'], + }, + { + 'name': 'datawarp', + 'options': [ + '#DW jobdw capacity={capacity}', + '#DW stage_in source={stagein_src}' + ] + } + ], + 'features': ['cuda', 'mpi'], + 'extras': { + 'gpu_arch': 'a100' + }, + 'container_platforms': [{'type': 'Sarus'}], + 'environs': ['PrgEnv-gnu', 'builtin'], + 'max_jobs': 10, + 'processor': { + 'arch': 'skylake', + 'num_cpus': 8, + 'num_cpus_per_core': 2, + 'num_cpus_per_socket': 8, + 'num_sockets': 1, + 'topology': { + 'numa_nodes': ['0x000000ff'], + 'sockets': ['0x000000ff'], + 'cores': ['0x00000003', '0x0000000c', + '0x00000030', '0x000000c0'], + 'caches': [ + { + 'type': 'L1', + 'size': 32768, + 'linesize': 64, + 'associativity': 0, + 'num_cpus': 2, + 'cpusets': ['0x00000003', '0x0000000c', + '0x00000030', '0x000000c0'] + }, + { + 'type': 'L2', + 'size': 262144, + 'linesize': 64, + 'associativity': 4, + 'num_cpus': 2, + 'cpusets': ['0x00000003', '0x0000000c', + '0x00000030', '0x000000c0'] + }, + { + 'type': 'L3', + 'size': 6291456, + 'linesize': 64, + 'associativity': 0, + 'num_cpus': 8, + 'cpusets': ['0x000000ff'] + } + ] + } + }, + 'devices': [ + { + 'type': 'gpu', + 'arch': 'p100', + 'num_devices': 1 + } + ] + } + ] + }, + ], + 'environments': [ + { + 'name': 'builtin', + 'cc': 'cc', + 'cxx': '', + 'ftn': '' + }, + { + 'name': 'e0', + 'modules': ['m0'] + }, + { + 'name': 'e1', + 'modules': ['m1'] + }, + { + 'name': 'e2', + 'modules': ['m2'] + }, + { + 'name': 'e3', + 'modules': ['m3'] + }, + { + 'name': 'irrelevant', + 'target_systems': ['foo'] + } + ], + 'general': [ + { + 'check_search_path': ['c:d'], + 'target_systems': ['testsys'] + }, + { + 'git_timeout': 10, + 'target_systems': ['generic2:part1'] + }, + ] +} diff --git a/unittests/resources/config/settings-part3.py b/unittests/resources/config/settings-part3.py new file mode 100644 index 0000000000..853efd389a --- /dev/null +++ b/unittests/resources/config/settings-part3.py @@ -0,0 +1,94 @@ +# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# ReFrame Project Developers. See the top-level LICENSE file for details. +# +# SPDX-License-Identifier: BSD-3-Clause + +# +# Configuration file just for unit testing +# + +site_configuration = { + 'systems': [ + { + 'name': 'generic', + 'descr': 'Generic example system', + 'hostnames': ['.*'], + 'partitions': [ + { + 'name': 'default', + 'descr': 'Login nodes', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['builtin'] + } + ] + }, + { + 'name': 'generic2', + 'descr': 'Generic example system', + 'hostnames': ['.*'], + 'partitions': [ + { + 'name': 'part1', + 'descr': 'Login nodes', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['builtin'] + }, + { + 'name': 'part2', + 'descr': 'Login nodes', + 'scheduler': 'local', + 'launcher': 'local', + 'environs': ['builtin'] + } + ] + }, + ], + 'logging': [ + { + 'level': 'debug', + 'handlers': [ + { + 'type': 'file', + 'level': 'debug', + 'format': ( + '[%(check_job_completion_time)s] %(levelname)s: ' + '%(check_name)s: %(message)s' + ), + 'datefmt': '%FT%T', + 'append': False, + }, + { + 'type': 'stream', + 'name': 'stdout', + 'level': 'info', + 'format': '%(message)s' + } + ], + 'handlers_perflog': [ + { + 'type': 'filelog', + 'prefix': '%(check_system)s/%(check_partition)s', + 'level': 'info', + 'format': ( + '%(check_job_completion_time)s|reframe %(version)s|' + '%(check_info)s|jobid=%(check_jobid)s|' + '%(check_perf_var)s=%(check_perf_value)s|' + 'ref=%(check_perf_ref)s ' + '(l=%(check_perf_lower_thres)s, ' + 'u=%(check_perf_upper_thres)s)|' + '%(check_perf_unit)s' + ), + 'append': True + } + ] + } + ], + 'general': [ + { + 'git_timeout': 20, + 'target_systems': ['generic2:part2'] + } + ] +} diff --git a/unittests/test_config.py b/unittests/test_config.py index f24b448be9..14ddc7ebb8 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -12,10 +12,34 @@ +@pytest.fixture(params=['full', 'parts']) +def site_config(request): + # `unittests/resources/config/settings.py` should be equivalent to loading + # the `unittests/resources/config/settings-part*.py` files + if request.param == 'full': + return config.load_config('unittests/resources/config/settings.py') + else: + return config.load_config( + 'unittests/resources/config/settings-part1.py', + 'unittests/resources/config/settings-part2.py', + 'unittests/resources/config/settings-part3.py' + ) + + def test_load_config_python(): config.load_config('reframe/core/settings.py') +def test_load_multiple_configs(): + site1 = config.load_config('unittests/resources/config/settings.py') + site2 = config.load_config( + 'unittests/resources/config/settings-part1.py', + 'unittests/resources/config/settings-part2.py', + 'unittests/resources/config/settings-part3.py' + ) + assert site1._site_config == site2._site_config + + def test_load_config_nouser(monkeypatch): import pwd @@ -79,8 +103,7 @@ def test_validate_fallback_config(): site_config.validate() -def test_validate_unittest_config(): - site_config = config.load_config('unittests/resources/config/settings.py') +def test_validate_unittest_config(site_config): site_config.validate() @@ -169,8 +192,7 @@ def test_select_subconfig_ignore_no_section_errors(): site_config.select_subconfig(ignore_resolve_errors=True) -def test_select_subconfig(): - site_config = config.load_config('unittests/resources/config/settings.py') +def test_select_subconfig(site_config): site_config.select_subconfig('testsys') assert len(site_config['systems']) == 1 assert len(site_config['systems'][0]['partitions']) == 2 @@ -280,8 +302,7 @@ def test_select_subconfig_optional_section_absent(): assert site_config.get('general/verbose') == 0 -def test_sticky_options(): - site_config = config.load_config('unittests/resources/config/settings.py') +def test_sticky_options(site_config): site_config.select_subconfig('testsys:login') site_config.add_sticky_option('environments/cc', 'clang') site_config.add_sticky_option('modes/options', ['foo']) @@ -298,8 +319,7 @@ def test_sticky_options(): assert site_config.get('environments/@PrgEnv-cray/cc') == 'cc' -def test_system_create(): - site_config = config.load_config('unittests/resources/config/settings.py') +def test_system_create(site_config): site_config.select_subconfig('testsys:gpu') system = System.create(site_config) assert system.name == 'testsys' @@ -365,12 +385,11 @@ def test_system_create(): assert system.partitions[0].container_runtime == 'Docker' -def test_hostname_autodetection(): +def test_hostname_autodetection(site_config): # This exercises only the various execution paths # We set the autodetection method and we call `select_subconfig()` in # order to trigger the auto-detection - site_config = config.load_config('unittests/resources/config/settings.py') for use_xthostname in (True, False): for use_fqdn in (True, False): site_config.set_autodetect_meth('hostname', From 6df6f6cf25dad4314ed2232f33703636e16a6582 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Wed, 17 Aug 2022 10:25:28 +0200 Subject: [PATCH 08/42] Add RFM_CONFIG_PATH --- reframe/frontend/cli.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 33a46e5cf4..976739578e 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -561,6 +561,12 @@ def main(): default='hostname', help='Method to detect the system' ) + argparser.add_argument( + dest='config_path', + envvar='RFM_CONFIG_PATH :', + action='append', + help='Directories where ReFrame will look for base configuration' + ) argparser.add_argument( dest='autodetect_xthostname', envvar='RFM_AUTODETECT_XTHOSTNAME', @@ -705,7 +711,25 @@ def restrict_logging(): printer.debug('Loading user configuration') # Cannot set the variable to [] in the argparser because it won't take # into account the environmane variable - conf_file = options.config_file if options.config_file else [] + conf_file = [] + if options.config_path: + for p in options.config_path: + if os.path.exists(p + '/settings.py'): + conf_file.append(p + '/settings.py') + elif os.path.exists(p + '/settings.json'): + conf_file.append(p + '/settings.json') + + if options.config_file: + for f in options.config_file: + # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will + # include one empty string in the beginning + if f == '': + conf_file = [] + elif f.startswith(':'): + conf_file = [f[1:]] + else: + conf_file.append(f) + site_config = config.load_config(*conf_file) site_config.validate() site_config.set_autodetect_meth( From 94493dd6ade53324bd8cd7c26b1ba7b58932e4ca Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Wed, 17 Aug 2022 11:22:27 +0200 Subject: [PATCH 09/42] Update configuration docs --- docs/configure.rst | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/configure.rst b/docs/configure.rst index f20b6a72d2..e206b356ac 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -10,7 +10,7 @@ This section will guide you through configuring ReFrame for your site. If you started using ReFrame from version 3.0, you can keep on reading this section, otherwise you are advised to have a look first at the :doc:`migration_2_to_3` page. -ReFrame's configuration file can be either a JSON file or a Python file storing the site configuration in a JSON-formatted string. +ReFrame's configuration files can be either JSON files or a Python files storing the site configuration in a JSON-formatted string. The latter format is useful in cases that you want to generate configuration parameters on-the-fly, since ReFrame will import that Python file and the load the resulting configuration. In the following we will use a Python-based configuration file also for historical reasons, since it was the only way to configure ReFrame in versions prior to 3.0. @@ -18,16 +18,8 @@ In the following we will use a Python-based configuration file also for historic Locating the Configuration File ------------------------------- -ReFrame looks for a configuration file in the following locations in that order: - -1. ``${HOME}/.reframe/settings.{py,json}`` -2. ``${RFM_INSTALL_PREFIX}/settings.{py,json}`` -3. ``/etc/reframe.d/settings.{py,json}`` - -If both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. -The ``RFM_INSTALL_PREFIX`` variable refers to the installation directory of ReFrame or the top-level source directory if you are running ReFrame from source. -Users have no control over this variable. -It is always set by the framework upon startup. +ReFrame looks for the configuration files in ``${RFM_CONFIG_PATH}/settings.{py,json}`` and if both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. +The ``RFM_CONFIG_PATH`` variable can have many paths seperated by ``:`` and all the paths will be considered and added to the configuration as long as there is a ``settings.{py,json}`` file there. If no configuration file is found in any of the predefined locations, ReFrame will fall back to a generic configuration that allows it to run on any system. You can find this generic configuration file `here `__. @@ -39,6 +31,11 @@ There are two ways to provide a custom configuration file to ReFrame: 2. Specify it using the ``RFM_CONFIG_FILE`` environment variable. Command line options take always precedence over their respective environment variables. +In order to replace the configuration files from the ``RFM_CONFIG_PATH`` variable you can pass the option ``-C :config-file.py``. + +.. note:: + .. versionadded:: 3.0.0 + ReFrame accepts multiple configuration files and always uses `the base configuration `__ as a base. Anatomy of the Configuration File @@ -56,8 +53,7 @@ For the complete listing and description of all configuration options, you shoul :start-after: # rfmdocstart: site-configuration :end-before: # rfmdocend: site-configuration -There are three required sections that each configuration file must provide: ``systems``, ``environments`` and ``logging``. -We will first cover these and then move on to the optional ones. +The most important sections are: ``systems``, ``environments`` and ``logging``. --------------------- From fa7edca8eb927b8d21a410ea8da111efac013498 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Wed, 7 Sep 2022 14:28:23 +0200 Subject: [PATCH 10/42] Address PR comments --- reframe/core/config.py | 28 +++- reframe/frontend/cli.py | 26 +--- unittests/resources/config/settings-part1.py | 99 ------------ unittests/resources/config/settings-part2.py | 155 ------------------- unittests/resources/config/settings-part3.py | 94 ----------- unittests/test_config.py | 47 ++++-- 6 files changed, 65 insertions(+), 384 deletions(-) delete mode 100644 unittests/resources/config/settings-part1.py delete mode 100644 unittests/resources/config/settings-part2.py delete mode 100644 unittests/resources/config/settings-part3.py diff --git a/reframe/core/config.py b/reframe/core/config.py index 82cc764064..626f167b85 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -278,8 +278,7 @@ def load_python_config(self, filename): # Looks like an old style config raise ConfigError( f"the syntax of the configuration file {filename!r} " - f"is no longer supported; please convert it using the " - f"'--upgrade-config-file' option" + f"is no longer supported" ) mod = util.import_module_from_file(filename) @@ -440,6 +439,31 @@ def select_subconfig(self, system_fullname=None, self._subconfigs[system_fullname] = local_config +def find_config_files(config_path=None, config_file=None): + res = [] + if config_path: + for p in config_path: + if os.path.exists(p + '/settings.py'): + res.append(p + '/settings.py') + elif os.path.exists(p + '/settings.json'): + res.append(p + '/settings.json') + else: + getlogger().debug('Loading the generic configuration') + + if config_file: + for f in config_file: + # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will + # include one empty string in the beginning + if f == '': + res = [] + elif f.startswith(':'): + res = [f[1:]] + else: + res.append(f) + + return res + + def load_config(*filenames): ret = _SiteConfig() getlogger().debug('Loading the generic configuration') diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 5a47a4b751..0587d6c479 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -709,28 +709,10 @@ def restrict_logging(): # Now configure ReFrame according to the user configuration file try: printer.debug('Loading user configuration') - # Cannot set the variable to [] in the argparser because it won't take - # into account the environmane variable - conf_file = [] - if options.config_path: - for p in options.config_path: - if os.path.exists(p + '/settings.py'): - conf_file.append(p + '/settings.py') - elif os.path.exists(p + '/settings.json'): - conf_file.append(p + '/settings.json') - - if options.config_file: - for f in options.config_file: - # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will - # include one empty string in the beginning - if f == '': - conf_file = [] - elif f.startswith(':'): - conf_file = [f[1:]] - else: - conf_file.append(f) - - site_config = config.load_config(*conf_file) + conf_files = config.find_config_files( + options.config_path, options.config_file + ) + site_config = config.load_config(*conf_files) site_config.validate() site_config.set_autodetect_meth( options.autodetect_method, diff --git a/unittests/resources/config/settings-part1.py b/unittests/resources/config/settings-part1.py deleted file mode 100644 index 7af5d32bf4..0000000000 --- a/unittests/resources/config/settings-part1.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) -# ReFrame Project Developers. See the top-level LICENSE file for details. -# -# SPDX-License-Identifier: BSD-3-Clause - -# -# Configuration file just for unit testing -# - -site_configuration = { - 'systems': [ - { - 'name': 'sys0', - 'descr': 'System for testing check dependencies', - 'hostnames': [r'sys\d+'], - 'partitions': [ - { - 'name': 'p0', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['e0', 'e1'] - }, - { - 'name': 'p1', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['e0', 'e1'] - } - - ] - }, - { - 'name': 'sys1', - 'descr': 'System for testing fixtures', - 'hostnames': [r'sys\d+'], - 'partitions': [ - { - 'name': 'p0', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['e0', 'e1', 'e3'] - }, - { - 'name': 'p1', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['e0', 'e1', 'e2'] - } - - ] - } - ], - 'environments': [ - { - 'name': 'PrgEnv-gnu', - 'modules': [ - {'name': 'PrgEnv-gnu', 'collection': False, 'path': None} - ], - 'extras': { - 'foo': 2, - 'bar': 'y' - }, - }, - { - 'name': 'PrgEnv-gnu', - 'modules': ['PrgEnv-gnu'], - 'cc': 'gcc', - 'cxx': 'g++', - 'ftn': 'gfortran', - 'features': ['cxx14'], - 'extras': { - 'foo': 1, - 'bar': 'x' - }, - 'target_systems': ['testsys:login'] - }, - { - 'name': 'PrgEnv-cray', - 'modules': ['PrgEnv-cray'], - 'features': ['cxx14', 'mpi'], - }, - ], - 'modes': [ - { - 'name': 'unittest', - 'options': [ - '-c unittests/resources/checks/hellocheck.py', - '-p builtin', - '--force-local' - ] - } - ], - 'general': [ - { - 'check_search_path': ['a:b'], - 'target_systems': ['testsys:login'] - }, - ] -} diff --git a/unittests/resources/config/settings-part2.py b/unittests/resources/config/settings-part2.py deleted file mode 100644 index 44127e4ded..0000000000 --- a/unittests/resources/config/settings-part2.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) -# ReFrame Project Developers. See the top-level LICENSE file for details. -# -# SPDX-License-Identifier: BSD-3-Clause - -# -# Configuration file just for unit testing -# - -site_configuration = { - 'systems': [ - { - 'name': 'testsys', - 'descr': 'Fake system for unit tests', - 'hostnames': ['testsys'], - 'prefix': '.rfm_testing', - 'resourcesdir': '.rfm_testing/resources', - 'modules': ['foo/1.0'], - 'variables': [['FOO_CMD', 'foobar']], - 'partitions': [ - { - 'name': 'login', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['PrgEnv-cray', 'PrgEnv-gnu'], - 'descr': 'Login nodes', - 'features': ['cross_compile'], - 'container_platforms': [ - {'type': 'Sarus'}, - {'type': 'Docker', 'default': True}, - {'type': 'Singularity'} - ] - }, - { - 'name': 'gpu', - 'descr': 'GPU partition', - 'scheduler': 'slurm', - 'launcher': 'srun', - - # Use the extensive syntax here - 'modules': [ - {'name': 'foogpu', 'collection': False, 'path': '/foo'} - ], - 'variables': [['FOO_GPU', 'yes']], - 'resources': [ - { - 'name': 'gpu', - 'options': ['--gres=gpu:{num_gpus_per_node}'], - }, - { - 'name': 'datawarp', - 'options': [ - '#DW jobdw capacity={capacity}', - '#DW stage_in source={stagein_src}' - ] - } - ], - 'features': ['cuda', 'mpi'], - 'extras': { - 'gpu_arch': 'a100' - }, - 'container_platforms': [{'type': 'Sarus'}], - 'environs': ['PrgEnv-gnu', 'builtin'], - 'max_jobs': 10, - 'processor': { - 'arch': 'skylake', - 'num_cpus': 8, - 'num_cpus_per_core': 2, - 'num_cpus_per_socket': 8, - 'num_sockets': 1, - 'topology': { - 'numa_nodes': ['0x000000ff'], - 'sockets': ['0x000000ff'], - 'cores': ['0x00000003', '0x0000000c', - '0x00000030', '0x000000c0'], - 'caches': [ - { - 'type': 'L1', - 'size': 32768, - 'linesize': 64, - 'associativity': 0, - 'num_cpus': 2, - 'cpusets': ['0x00000003', '0x0000000c', - '0x00000030', '0x000000c0'] - }, - { - 'type': 'L2', - 'size': 262144, - 'linesize': 64, - 'associativity': 4, - 'num_cpus': 2, - 'cpusets': ['0x00000003', '0x0000000c', - '0x00000030', '0x000000c0'] - }, - { - 'type': 'L3', - 'size': 6291456, - 'linesize': 64, - 'associativity': 0, - 'num_cpus': 8, - 'cpusets': ['0x000000ff'] - } - ] - } - }, - 'devices': [ - { - 'type': 'gpu', - 'arch': 'p100', - 'num_devices': 1 - } - ] - } - ] - }, - ], - 'environments': [ - { - 'name': 'builtin', - 'cc': 'cc', - 'cxx': '', - 'ftn': '' - }, - { - 'name': 'e0', - 'modules': ['m0'] - }, - { - 'name': 'e1', - 'modules': ['m1'] - }, - { - 'name': 'e2', - 'modules': ['m2'] - }, - { - 'name': 'e3', - 'modules': ['m3'] - }, - { - 'name': 'irrelevant', - 'target_systems': ['foo'] - } - ], - 'general': [ - { - 'check_search_path': ['c:d'], - 'target_systems': ['testsys'] - }, - { - 'git_timeout': 10, - 'target_systems': ['generic2:part1'] - }, - ] -} diff --git a/unittests/resources/config/settings-part3.py b/unittests/resources/config/settings-part3.py deleted file mode 100644 index 853efd389a..0000000000 --- a/unittests/resources/config/settings-part3.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich) -# ReFrame Project Developers. See the top-level LICENSE file for details. -# -# SPDX-License-Identifier: BSD-3-Clause - -# -# Configuration file just for unit testing -# - -site_configuration = { - 'systems': [ - { - 'name': 'generic', - 'descr': 'Generic example system', - 'hostnames': ['.*'], - 'partitions': [ - { - 'name': 'default', - 'descr': 'Login nodes', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['builtin'] - } - ] - }, - { - 'name': 'generic2', - 'descr': 'Generic example system', - 'hostnames': ['.*'], - 'partitions': [ - { - 'name': 'part1', - 'descr': 'Login nodes', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['builtin'] - }, - { - 'name': 'part2', - 'descr': 'Login nodes', - 'scheduler': 'local', - 'launcher': 'local', - 'environs': ['builtin'] - } - ] - }, - ], - 'logging': [ - { - 'level': 'debug', - 'handlers': [ - { - 'type': 'file', - 'level': 'debug', - 'format': ( - '[%(check_job_completion_time)s] %(levelname)s: ' - '%(check_name)s: %(message)s' - ), - 'datefmt': '%FT%T', - 'append': False, - }, - { - 'type': 'stream', - 'name': 'stdout', - 'level': 'info', - 'format': '%(message)s' - } - ], - 'handlers_perflog': [ - { - 'type': 'filelog', - 'prefix': '%(check_system)s/%(check_partition)s', - 'level': 'info', - 'format': ( - '%(check_job_completion_time)s|reframe %(version)s|' - '%(check_info)s|jobid=%(check_jobid)s|' - '%(check_perf_var)s=%(check_perf_value)s|' - 'ref=%(check_perf_ref)s ' - '(l=%(check_perf_lower_thres)s, ' - 'u=%(check_perf_upper_thres)s)|' - '%(check_perf_unit)s' - ), - 'append': True - } - ] - } - ], - 'general': [ - { - 'git_timeout': 20, - 'target_systems': ['generic2:part2'] - } - ] -} diff --git a/unittests/test_config.py b/unittests/test_config.py index 14ddc7ebb8..5800828688 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -7,36 +7,59 @@ import pytest import reframe.core.config as config +import reframe.utility as util from reframe.core.exceptions import ConfigError from reframe.core.systems import System +@pytest.fixture +def part_config_files(tmp_path): + part1 = tmp_path / 'settings-part1.py' + part2 = tmp_path / 'settings-part2.py' + part3 = tmp_path / 'settings-part3.py' + mod = util.import_module_from_file('unittests/resources/config/settings.py') + full_config = mod.site_configuration + + config_1 = { + 'systems': full_config['systems'][-2:], + 'environments': full_config['environments'][:3], + 'modes': full_config['modes'], + 'general': full_config['general'][0:1], + } + config_2 = { + 'systems': full_config['systems'][-3:-2], + 'environments': full_config['environments'][3:], + 'general': full_config['general'][1:3], + } + config_3 = { + 'systems': full_config['systems'][:-3], + 'logging': full_config['logging'], + 'general': full_config['general'][3:], + } + part1.write_text(f'site_configuration = {config_1!r}') + part2.write_text(f'site_configuration = {config_2!r}') + part3.write_text(f'site_configuration = {config_3!r}') + + return part1, part2, part3 + @pytest.fixture(params=['full', 'parts']) -def site_config(request): +def site_config(request, part_config_files): # `unittests/resources/config/settings.py` should be equivalent to loading # the `unittests/resources/config/settings-part*.py` files if request.param == 'full': return config.load_config('unittests/resources/config/settings.py') else: - return config.load_config( - 'unittests/resources/config/settings-part1.py', - 'unittests/resources/config/settings-part2.py', - 'unittests/resources/config/settings-part3.py' - ) + return config.load_config(*part_config_files) def test_load_config_python(): config.load_config('reframe/core/settings.py') -def test_load_multiple_configs(): +def test_load_multiple_configs(part_config_files): site1 = config.load_config('unittests/resources/config/settings.py') - site2 = config.load_config( - 'unittests/resources/config/settings-part1.py', - 'unittests/resources/config/settings-part2.py', - 'unittests/resources/config/settings-part3.py' - ) + site2 = config.load_config(*part_config_files) assert site1._site_config == site2._site_config From 4b57c15dcc21ddd93d33fb254694bb10c90a1acb Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Wed, 7 Sep 2022 14:35:11 +0200 Subject: [PATCH 11/42] Update assertions in test_load_multiple_configs --- unittests/test_config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unittests/test_config.py b/unittests/test_config.py index 5800828688..46efc2387b 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -54,13 +54,13 @@ def site_config(request, part_config_files): def test_load_config_python(): - config.load_config('reframe/core/settings.py') + site = config.load_config('reframe/core/settings.py') + assert len(site.sources) == 2 def test_load_multiple_configs(part_config_files): - site1 = config.load_config('unittests/resources/config/settings.py') - site2 = config.load_config(*part_config_files) - assert site1._site_config == site2._site_config + site = config.load_config(*part_config_files) + assert len(site.sources) == 4 def test_load_config_nouser(monkeypatch): From 29fe80d13f6d223d9d013a44daa8da904b5eecf6 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 9 Sep 2022 10:27:57 +0200 Subject: [PATCH 12/42] Address PR comments --- reframe/core/config.py | 12 +++++++----- unittests/test_config.py | 11 +++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/reframe/core/config.py b/reframe/core/config.py index 626f167b85..9ee6be31e2 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -116,7 +116,9 @@ def update_config(self, config, filename): if sec not in self._site_config: self._site_config[sec] = nc[sec] elif sec == 'systems': - # Systems have to be inserted in the beginning of the list + # Systems have to be inserted in the beginning of the list, + # since they are selected by the first matching entry in + # `hostnames`. self._site_config[sec] = nc[sec] + self._site_config[sec] else: self._site_config[sec] += nc[sec] @@ -264,7 +266,7 @@ def sources(self): def subconfig_system(self): return self._local_system - def load_python_config(self, filename): + def load_config_python(self, filename): try: mod = util.import_module_from_file(filename) except ImportError as e: @@ -289,7 +291,7 @@ def load_python_config(self, filename): self.update_config(mod.site_configuration, filename) - def load_json_config(self, filename): + def load_config_json(self, filename): with open(filename) as fp: try: config = json.loads(fp.read()) @@ -472,9 +474,9 @@ def load_config(*filenames): getlogger().debug(f'Loading configuration file: {filenames!r}') _, ext = os.path.splitext(f) if ext == '.py': - ret.load_python_config(f) + ret.load_config_python(f) elif ext == '.json': - ret.load_json_config(f) + ret.load_config_json(f) else: raise ConfigError(f"unknown configuration file type: '{f}'") diff --git a/unittests/test_config.py b/unittests/test_config.py index 46efc2387b..720f812ec2 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -13,7 +13,7 @@ @pytest.fixture -def part_config_files(tmp_path): +def generate_partial_configs(tmp_path): part1 = tmp_path / 'settings-part1.py' part2 = tmp_path / 'settings-part2.py' part3 = tmp_path / 'settings-part3.py' @@ -39,18 +39,17 @@ def part_config_files(tmp_path): part1.write_text(f'site_configuration = {config_1!r}') part2.write_text(f'site_configuration = {config_2!r}') part3.write_text(f'site_configuration = {config_3!r}') - return part1, part2, part3 @pytest.fixture(params=['full', 'parts']) -def site_config(request, part_config_files): +def site_config(request, generate_partial_configs): # `unittests/resources/config/settings.py` should be equivalent to loading # the `unittests/resources/config/settings-part*.py` files if request.param == 'full': return config.load_config('unittests/resources/config/settings.py') else: - return config.load_config(*part_config_files) + return config.load_config(*generate_partial_configs) def test_load_config_python(): @@ -58,8 +57,8 @@ def test_load_config_python(): assert len(site.sources) == 2 -def test_load_multiple_configs(part_config_files): - site = config.load_config(*part_config_files) +def test_load_multiple_configs(generate_partial_configs): + site = config.load_config(*generate_partial_configs) assert len(site.sources) == 4 From 15087b457d7861a60049ec7df9fc93f7eaf89b66 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 9 Sep 2022 10:37:20 +0200 Subject: [PATCH 13/42] Update config file format in setup info --- reframe/frontend/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 6ae852c595..f2abf4d203 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -921,7 +921,10 @@ def print_infoline(param, value): f"{session_info['user'] or ''}@{session_info['hostname']}" ) print_infoline('working directory', repr(session_info['workdir'])) - print_infoline('settings files', f"{session_info['config_files']!r}") + print_infoline( + 'settings files', + f"{', '.join(map(lambda x: repr(x), session_info['config_files']))}" + ) print_infoline('check search path', f"{'(R) ' if loader.recurse else ''}" f"{':'.join(loader.load_path)!r}") From 0e501238ce806e4cf7d1c99f65bb1befc6026821 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 9 Sep 2022 10:45:49 +0200 Subject: [PATCH 14/42] Update debug message --- reframe/core/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reframe/core/config.py b/reframe/core/config.py index 9ee6be31e2..328b16bfa9 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -450,7 +450,8 @@ def find_config_files(config_path=None, config_file=None): elif os.path.exists(p + '/settings.json'): res.append(p + '/settings.json') else: - getlogger().debug('Loading the generic configuration') + getlogger().debug(f"No 'settings.py' or 'settings.json' " + f"found in {p!r}, path will be ignored") if config_file: for f in config_file: From 99a862b8e8352190ddc10abf97da8bff7411c886 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 16 Sep 2022 10:02:44 +0200 Subject: [PATCH 15/42] Simplify string join --- reframe/frontend/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index f2abf4d203..4c2a290cce 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -923,7 +923,7 @@ def print_infoline(param, value): print_infoline('working directory', repr(session_info['workdir'])) print_infoline( 'settings files', - f"{', '.join(map(lambda x: repr(x), session_info['config_files']))}" + ', '.join(repr(x) for x in session_info['config_files']) ) print_infoline('check search path', f"{'(R) ' if loader.recurse else ''}" From ca5c5ddf816b6e347105b79f0832c885f028d69c Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Fri, 16 Sep 2022 17:06:00 +0200 Subject: [PATCH 16/42] Update docs --- docs/configure.rst | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/docs/configure.rst b/docs/configure.rst index e9e06b59b9..ee1ea1b4fb 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -10,32 +10,30 @@ This section will guide you through configuring ReFrame for your site. If you started using ReFrame from version 3.0, you can keep on reading this section, otherwise you are advised to have a look first at the :doc:`migration_2_to_3` page. -ReFrame's configuration files can be either JSON files or a Python files storing the site configuration in a JSON-formatted string. -The latter format is useful in cases that you want to generate configuration parameters on-the-fly, since ReFrame will import that Python file and the load the resulting configuration. -In the following we will use a Python-based configuration file also for historical reasons, since it was the only way to configure ReFrame in versions prior to 3.0. +ReFrame's configuration can be either in JSON or in Python format and can be split into multiple files. +The Python format is useful in cases that you want to generate configuration parameters on-the-fly, since ReFrame will import that Python file and the load the resulting configuration. +In the following we will use a single Python-based configuration file also for historical reasons, since it was the only way to configure ReFrame in versions prior to 3.0. -Locating the Configuration File -------------------------------- +.. versionchanged:: 4.0.0 + The configuration can now be split into multiple files. -ReFrame looks for the configuration files in ``${RFM_CONFIG_PATH}/settings.{py,json}`` and if both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. -The ``RFM_CONFIG_PATH`` variable can have many paths seperated by ``:`` and all the paths will be considered and added to the configuration as long as there is a ``settings.{py,json}`` file there. -If no configuration file is found in any of the predefined locations, ReFrame will fall back to a generic configuration that allows it to run on any system. -You can find this generic configuration file `here `__. -Users may *not* modify this file. -There are two ways to provide a custom configuration file to ReFrame: +Loading the configuration +------------------------- -1. Pass it through the ``-C`` or ``--config-file`` option. -2. Specify it using the ``RFM_CONFIG_FILE`` environment variable. +ReFrame builds its final configuration gradually by combining multiple configuration files. +Each one can have different parts of the configuration, for example different systems, different environments etc. +This technique allows users to avoid having a single huge configuration file. -Command line options take always precedence over their respective environment variables. -In order to replace the configuration files from the ``RFM_CONFIG_PATH`` variable you can pass the option ``-C :config-file.py``. +The first configuration file loaded in this chain is always the generic builtin configuration located under ``${RFM_INSTALL_PREFIX}/reframe/core/settings.py``. +This contains everything that ReFrame needs to run on a generic system, as well as basic settings for logging, so subsequent configuration files may skip defining some configuration sections altogether, if they are not relevant. -.. note:: - .. versionadded:: 3.0.0 - ReFrame accepts multiple configuration files and always uses `the base configuration `__ as a base. +ReFrame continues on looking for configuration files in the directories defined in :envvar:`RFM_CONFIG_PATH`. +For each directory, will look within it for a ``settings.py`` or ``settings.json`` file (in that order), and if it finds one, it will load it. + +Finally, ReFrame processes the :option:`--config-files` option or the :envvar:`RFM_CONFIG_FILES` to load any specific configuration files passed from the command line. Anatomy of the Configuration File @@ -53,8 +51,12 @@ For the complete listing and description of all configuration options, you shoul :start-after: # rfmdocstart: site-configuration :end-before: # rfmdocend: site-configuration -The most important sections are: ``systems``, ``environments`` and ``logging``. +There are three required sections that each configuration must provide: ``systems``, ``environments`` and ``logging``. +We will first cover these and then move on to the optional ones. + +.. tip:: + These configuration sections may not all be defined in the same configuration file, but can reside in any configuration file that is being loaded. --------------------- Systems Configuration From e2b5f024c0f27c1db50a74dccea7ecf837b84d0b Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 26 Sep 2022 10:37:48 +0200 Subject: [PATCH 17/42] Address PR comments --- docs/configure.rst | 4 +-- docs/manpage.rst | 6 ++-- docs/tutorial_advanced.rst | 2 +- docs/tutorial_basics.rst | 4 +-- reframe/core/config.py | 2 +- reframe/frontend/cli.py | 19 ++++++++++-- tools/gendoclistings.py | 60 ++++++++++++++++++------------------- unittests/test_argparser.py | 2 +- 8 files changed, 57 insertions(+), 42 deletions(-) diff --git a/docs/configure.rst b/docs/configure.rst index e9e06b59b9..3396002d64 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -27,8 +27,8 @@ Users may *not* modify this file. There are two ways to provide a custom configuration file to ReFrame: -1. Pass it through the ``-C`` or ``--config-file`` option. -2. Specify it using the ``RFM_CONFIG_FILE`` environment variable. +1. Pass it through the ``-C`` or ``--config-files`` option. +2. Specify it using the ``RFM_CONFIG_FILES`` environment variable. Command line options take always precedence over their respective environment variables. In order to replace the configuration files from the ``RFM_CONFIG_PATH`` variable you can pass the option ``-C :config-file.py``. diff --git a/docs/manpage.rst b/docs/manpage.rst index 8ccfce9110..2ff7638a47 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -775,11 +775,11 @@ It does so by leveraging the selected system's environment modules system. Miscellaneous options --------------------- -.. option:: -C --config-file=FILE +.. option:: -C --config-files=FILE Use ``FILE`` as configuration file for ReFrame. - This option can also be set using the :envvar:`RFM_CONFIG_FILE` environment variable. + This option can also be set using the :envvar:`RFM_CONFIG_FILES` environment variable. .. _--detect-host-topology: @@ -1160,7 +1160,7 @@ Here is an alphabetical list of the environment variables recognized by ReFrame: .. versionadded:: 3.12.0 -.. envvar:: RFM_CONFIG_FILE +.. envvar:: RFM_CONFIG_FILES Set the configuration file for ReFrame. diff --git a/docs/tutorial_advanced.rst b/docs/tutorial_advanced.rst index f23c7fd143..04e608000f 100644 --- a/docs/tutorial_advanced.rst +++ b/docs/tutorial_advanced.rst @@ -9,7 +9,7 @@ Finally, to avoid specifying the tutorial configuration file each time, make sur .. code:: bash - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index b0bd22f1ed..b50c22cae9 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -266,7 +266,7 @@ Since we don't want to type it throughout the tutorial, we will now set it in th .. code-block:: console - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py A Multithreaded "Hello, World!" @@ -650,7 +650,7 @@ We will only do so with the final versions of the tests from the previous sectio .. code-block:: console - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py ./bin/reframe -c tutorials/basics/ -R -n 'HelloMultiLangTest|HelloThreadedExtended2Test|StreamWithRefTest' --performance-report -r .. literalinclude:: listings/alltests_daint.txt diff --git a/reframe/core/config.py b/reframe/core/config.py index 328b16bfa9..bd6c2c38ec 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -455,7 +455,7 @@ def find_config_files(config_path=None, config_file=None): if config_file: for f in config_file: - # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will + # If the user sets RFM_CONFIG_FILES=:conf1:conf2 the list will # include one empty string in the beginning if f == '': res = [] diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 4c2a290cce..a5a542ab2a 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -502,10 +502,16 @@ def main(): # Miscellaneous options misc_options.add_argument( - '-C', '--config-file', action='append', metavar='FILE', + '--config-file', action='append', metavar='FILE', + dest='config_file_alias', + help="Deprecated, alias of `--config-files'", + envvar='RFM_CONFIG_FILE :' + ) + misc_options.add_argument( + '-C', '--config-files', action='append', metavar='FILE', dest='config_file', help='Set configuration file', - envvar='RFM_CONFIG_FILE :' + envvar='RFM_CONFIG_FILES :' ) misc_options.add_argument( '--detect-host-topology', action='store', nargs='?', const='-', @@ -706,6 +712,15 @@ def restrict_logging(): ) os.environ['RFM_GRAYLOG_ADDRESS'] = os.getenv('RFM_GRAYLOG_SERVER') + if options.config_file_alias: + printer.warning( + "`--config-file' option and RFM_CONFIG_FILE environment variable " + "are deprecated; please use `--config-files' and " + "RFM_CONFIG_FILES instead" + ) + if options.config_file is None: + options.config_file = options.config_file_alias + # Now configure ReFrame according to the user configuration file try: printer.debug('Loading user configuration') diff --git a/tools/gendoclistings.py b/tools/gendoclistings.py index 1ecf3af034..3b27321fd7 100755 --- a/tools/gendoclistings.py +++ b/tools/gendoclistings.py @@ -78,8 +78,8 @@ def replace_hostname(s): {'local', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -89,8 +89,8 @@ def replace_hostname(s): {'local', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=True @@ -100,8 +100,8 @@ def replace_hostname(s): {'remote', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -111,8 +111,8 @@ def replace_hostname(s): {'remote', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -122,8 +122,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -133,8 +133,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -144,8 +144,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -155,8 +155,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -166,8 +166,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -184,8 +184,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py') + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py') }, xfail=False ), @@ -194,8 +194,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -205,8 +205,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -216,8 +216,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -227,8 +227,8 @@ def replace_hostname(s): {'local', 'tutorial-advanced'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -238,8 +238,8 @@ def replace_hostname(s): {'local', 'tutorial-advanced'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False diff --git a/unittests/test_argparser.py b/unittests/test_argparser.py index 032490a04a..8e640fa3b8 100644 --- a/unittests/test_argparser.py +++ b/unittests/test_argparser.py @@ -120,7 +120,7 @@ def extended_parser(): envvar='RFM_TIMESTAMP_DIRS', configvar='general/timestamp_dirs' ) foo_options.add_argument( - '-C', '--config-file', action='store', envvar='RFM_CONFIG_FILE' + '-C', '--config-files', action='store', envvar='RFM_CONFIG_FILES' ) foo_options.add_argument( '--check-path', action='append', envvar='RFM_CHECK_SEARCH_PATH :' From 963934478b338e0edfad7c73827f78a57af620a1 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 26 Sep 2022 11:46:48 +0200 Subject: [PATCH 18/42] Add more details for configuration in the manpages --- docs/manpage.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/manpage.rst b/docs/manpage.rst index 2ff7638a47..71d1091fd4 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -778,9 +778,16 @@ Miscellaneous options .. option:: -C --config-files=FILE Use ``FILE`` as configuration file for ReFrame. + The user can pass multiple configuration files that will be added on top of the ``${RFM_INSTALL_PREFIX}/reframe/core/settings.py``. + To ignore previous configuration files you need to pass ``-C :new_config.py`` This option can also be set using the :envvar:`RFM_CONFIG_FILES` environment variable. + ReFrame first loads the builtin config unconditionally and then starts to look for configs in the :envvar:`RFM_CONFIG_PATH` and starts chaining them. + :envvar:`RFM_CONFIG_PATH` containe directories where a file named ``setting.py`` or ``setting.json`` is. + If both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. + Then accumulates the configs of the command line option, potentially replacing completely those from the :envvar:`RFM_CONFIG_PATH`. + .. _--detect-host-topology: .. option:: --detect-host-topology[=FILE] From 4656b7cf9db33dbd4946834f88896410bad61cf8 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Mon, 26 Sep 2022 12:12:27 +0200 Subject: [PATCH 19/42] Fix unittests --- unittests/test_argparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_argparser.py b/unittests/test_argparser.py index 8e640fa3b8..48906099d0 100644 --- a/unittests/test_argparser.py +++ b/unittests/test_argparser.py @@ -153,7 +153,7 @@ def test_option_precedence(default_exec_ctx, extended_parser): assert options.recursive is None assert options.timestamp == '%FT%T' assert options.non_default_craype is True - assert options.config_file is None + assert options.config_files is None assert options.prefix is None assert options.stagedir == '/foo' assert options.module == ['a', 'b', 'c'] From 92c6d559bc88afc8e33a7b65434147024d943ecc Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Thu, 29 Sep 2022 14:45:35 +0200 Subject: [PATCH 20/42] Revert --config-files to --config-file --- docs/configure.rst | 2 +- docs/man/man8/reframe.settings.8 | 2995 ++++++++++++++++++++++++++++++ docs/manpage.rst | 6 +- docs/tutorial_advanced.rst | 2 +- docs/tutorial_basics.rst | 4 +- reframe/core/config.py | 2 +- reframe/frontend/cli.py | 19 +- tools/gendoclistings.py | 60 +- unittests/test_argparser.py | 4 +- 9 files changed, 3037 insertions(+), 57 deletions(-) create mode 100644 docs/man/man8/reframe.settings.8 diff --git a/docs/configure.rst b/docs/configure.rst index d8c564afdc..44dcd4908f 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -33,7 +33,7 @@ This contains everything that ReFrame needs to run on a generic system, as well ReFrame continues on looking for configuration files in the directories defined in :envvar:`RFM_CONFIG_PATH`. For each directory, will look within it for a ``settings.py`` or ``settings.json`` file (in that order), and if it finds one, it will load it. -Finally, ReFrame processes the :option:`--config-files` option or the :envvar:`RFM_CONFIG_FILES` to load any specific configuration files passed from the command line. +Finally, ReFrame processes the :option:`--config-file` option or the :envvar:`RFM_CONFIG_FILE` to load any specific configuration files passed from the command line. Anatomy of the Configuration File diff --git a/docs/man/man8/reframe.settings.8 b/docs/man/man8/reframe.settings.8 new file mode 100644 index 0000000000..79a46ffa17 --- /dev/null +++ b/docs/man/man8/reframe.settings.8 @@ -0,0 +1,2995 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "REFRAME.SETTINGS" "8" "Sep 29, 2022" "4.0.0-dev.1" "ReFrame" +.SH NAME +reframe.settings \- ReFrame Configuration Manual +.sp +ReFrame’s behavior can be configured through its configuration file (see \fI\%Configuring ReFrame for Your Site\fP), environment variables and command\-line options. +An option can be specified via multiple paths (e.g., a configuration file parameter and an environment variable), in which case command\-line options precede environment variables, which in turn precede configuration file options. +This section provides a complete reference guide of the configuration options of ReFrame that can be set in its configuration file or specified using environment variables. +.sp +ReFrame’s configuration is in JSON syntax. +The full schema describing it can be found in \fI\%reframe/schemas/config.json\fP file. +Any configuration file given to ReFrame is validated against this schema. +.sp +The syntax we use in the following to describe the different configuration object attributes is a valid query string for the \fI\%jq(1)\fP command\-line processor. +.SH TOP-LEVEL CONFIGURATION +.sp +The top\-level configuration object is essentially the full configuration of ReFrame. +It consists of the following properties: +.INDENT 0.0 +.TP +.B \&.systems +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of \fI\%system configuration objects\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of \fI\%environment configuration objects\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of \fI\%logging configuration objects\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers +.INDENT 7.0 +.TP +.B Required +No +.UNINDENT +.sp +A list of \fI\%scheduler configuration objects\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.modes +.INDENT 7.0 +.TP +.B Required +No +.UNINDENT +.sp +A list of \fI\%execution mode configuration objects\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general +.INDENT 7.0 +.TP +.B Required +No +.UNINDENT +.sp +A list of \fI\%general configuration objects\fP\&. +.UNINDENT +.SH SYSTEM CONFIGURATION +.INDENT 0.0 +.TP +.B \&.systems[]\&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of this system. +Only alphanumeric characters, dashes (\fB\-\fP) and underscores (\fB_\fP) are allowed. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.descr +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB""\fP +.UNINDENT +.sp +The description of this system. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.hostnames +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of hostname regular expression patterns in Python \fI\%syntax\fP, which will be used by the framework in order to automatically select a system configuration. +For the auto\-selection process, see \fI\%here\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.max_local_jobs +The maximum number of forced local build or run jobs allowed. +.sp +Forced local jobs run within the execution context of ReFrame. +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB8\fP +.UNINDENT +.sp +New in version 3.10.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.modules_system +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"nomod"\fP +.UNINDENT +.sp +The modules system that should be used for loading environment modules on this system. +Available values are the following: +.INDENT 7.0 +.IP \(bu 2 +\fBtmod\fP: The classic Tcl implementation of the \fI\%environment modules\fP (version 3.2). +.IP \(bu 2 +\fBtmod31\fP: The classic Tcl implementation of the \fI\%environment modules\fP (version 3.1). +A separate backend is required for Tmod 3.1, because Python bindings are different from Tmod 3.2. +.IP \(bu 2 +\fBtmod32\fP: A synonym of \fBtmod\fP\&. +.IP \(bu 2 +\fBtmod4\fP: The \fI\%new environment modules\fP implementation (versions older than 4.1 are not supported). +.IP \(bu 2 +\fBlmod\fP: The \fI\%Lua implementation\fP of the environment modules. +.IP \(bu 2 +\fBspack\fP: \fI\%Spack\fP’s built\-in mechanism for managing modules. +.IP \(bu 2 +\fBnomod\fP: This is to denote that no modules system is used by this system. +.UNINDENT +.sp +New in version 3.4: The \fBspack\fP backend is added. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.modules +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to be loaded always when running on this system. +These modules modify the ReFrame environment. +This is useful in cases where a particular module is needed, for example, to submit jobs on a specific system. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.variables +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of environment variables to be set always when running on this system. +These variables modify the ReFrame environment. +Each environment variable is specified as a two\-element list containing the variable name and its value. +You may reference other environment variables when defining an environment variable here. +ReFrame will expand its value. +Variables are set after the environment modules are loaded. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.prefix +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"."\fP +.UNINDENT +.sp +Directory prefix for a ReFrame run on this system. +Any directories or files produced by ReFrame will use this prefix, if not specified otherwise. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.stagedir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"${RFM_PREFIX}/stage"\fP +.UNINDENT +.sp +Stage directory prefix for this system. +This is the directory prefix, where ReFrame will create the stage directories for each individual test case. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.outputdir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"${RFM_PREFIX}/output"\fP +.UNINDENT +.sp +Output directory prefix for this system. +This is the directory prefix, where ReFrame will save information about the successful tests. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.resourcesdir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"."\fP +.UNINDENT +.sp +Directory prefix where external test resources (e.g., large input files) are stored. +You may reference this prefix from within a regression test by accessing the \fI\%reframe.core.systems.System.resourcesdir\fP attribute of the current system. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of \fI\%system partition configuration objects\fP\&. +This list must have at least one element. +.UNINDENT +.SS System Partition Configuration +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of this partition. +Only alphanumeric characters, dashes (\fB\-\fP) and underscores (\fB_\fP) are allowed. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.descr +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB""\fP +.UNINDENT +.sp +The description of this partition. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.scheduler +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The job scheduler that will be used to launch jobs on this partition. +Supported schedulers are the following: +.INDENT 7.0 +.IP \(bu 2 +\fBlocal\fP: Jobs will be launched locally without using any job scheduler. +.IP \(bu 2 +\fBoar\fP: Jobs will be launched using the \fI\%OAR\fP scheduler. +.IP \(bu 2 +\fBpbs\fP: Jobs will be launched using the \fI\%PBS Pro\fP scheduler. +.IP \(bu 2 +\fBsge\fP: Jobs will be launched using the \fI\%Sun Grid Engine\fP scheduler. +.IP \(bu 2 +\fBslurm\fP: Jobs will be launched using the \fI\%Slurm\fP scheduler. +This backend requires job accounting to be enabled in the target system. +If not, you should consider using the \fBsqueue\fP backend below. +.IP \(bu 2 +\fBsqueue\fP: Jobs will be launched using the \fI\%Slurm\fP scheduler. +This backend does not rely on job accounting to retrieve job statuses, but ReFrame does its best to query the job state as reliably as possible. +.IP \(bu 2 +\fBtorque\fP: Jobs will be launched using the \fI\%Torque\fP scheduler. +.IP \(bu 2 +\fBlsf\fP: Jobs will be launched using the \fI\%LSF\fP scheduler. +.UNINDENT +.sp +New in version 3.7.2: Support for the SGE scheduler is added. + +.sp +New in version 3.8.2: Support for the OAR scheduler is added. + +.sp +New in version 3.11.0: Support for the LSF scheduler is added. + +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +The way that multiple node jobs are submitted using the SGE scheduler can be very site\-specific. +For this reason, the \fBsge\fP scheduler backend does not try to interpret any related arguments, e.g., \fBnum_tasks\fP, \fBnum_tasks_per_node\fP etc. +Users must specify how these resources are to be requested by setting the \fBresources\fP partition configuration parameter and then request them from inside a test using the \fI\%extra_resources\fP test attribute. +Here is an example configuration for a system partition named \fBfoo\fP that defines different ways for submitting MPI\-only, OpenMP\-only and MPI+OpenMP jobs: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +{ + \(aqname\(aq: \(aqfoo\(aq, + \(aqscheduler\(aq: \(aqsge\(aq, + \(aqresources\(aq: [ + { + \(aqname\(aq: \(aqsmp\(aq, + \(aqoptions\(aq: [\(aq\-pe smp {num_slots}\(aq] + }, + { + \(aqname\(aq: \(aqmpi\(aq, + \(aqoptions\(aq: [\(aq\-pe mpi {num_slots}\(aq] + }, + { + \(aqname\(aq: \(aqmpismp\(aq, + \(aqoptions\(aq: [\(aq\-pe mpismp {num_slots}\(aq] + } + ] +} +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Each test then can request the different type of slots as follows: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +self.extra_resouces = { + \(aqsmp\(aq: {\(aqnum_slots\(aq: self.num_cpus_per_task}, + \(aqmpi\(aq: {\(aqnum_slots\(aq: self.num_tasks}, + \(aqmpismp\(aq: {\(aqnum_slots\(aq: self.num_tasks*self.num_cpus_per_task} +} +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Notice that defining \fI\%extra_resources\fP does not make the test non\-portable to other systems that have different schedulers; +the \fBextra_resources\fP will be simply ignored in this case and the scheduler backend will interpret the different test fields in the appropriate way. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.launcher +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The parallel job launcher that will be used in this partition to launch parallel programs. +Available values are the following: +.INDENT 7.0 +.IP \(bu 2 +\fBalps\fP: Parallel programs will be launched using the \fI\%Cray ALPS\fP \fBaprun\fP command. +.IP \(bu 2 +\fBibrun\fP: Parallel programs will be launched using the \fBibrun\fP command. +This is a custom parallel program launcher used at \fI\%TACC\fP\&. +.IP \(bu 2 +\fBlocal\fP: No parallel program launcher will be used. +The program will be launched locally. +.IP \(bu 2 +\fBlrun\fP: Parallel programs will be launched using \fI\%LC Launcher\fP’s \fBlrun\fP command. +.IP \(bu 2 +\fBlrun\-gpu\fP: Parallel programs will be launched using \fI\%LC Launcher\fP’s \fBlrun \-M "\-gpu"\fP command that enables the CUDA\-aware Spectrum MPI. +.IP \(bu 2 +\fBmpirun\fP: Parallel programs will be launched using the \fBmpirun\fP command. +.IP \(bu 2 +\fBmpiexec\fP: Parallel programs will be launched using the \fBmpiexec\fP command. +.IP \(bu 2 +\fBsrun\fP: Parallel programs will be launched using \fI\%Slurm\fP’s \fBsrun\fP command. +.IP \(bu 2 +\fBsrunalloc\fP: Parallel programs will be launched using \fI\%Slurm\fP’s \fBsrun\fP command, but job allocation options will also be emitted. +This can be useful when combined with the \fBlocal\fP job scheduler. +.IP \(bu 2 +\fBssh\fP: Parallel programs will be launched using SSH. +This launcher uses the partition’s \fI\%access\fP property in order to determine the remote host and any additional options to be passed to the SSH client. +The ssh command will be launched in “batch mode,” meaning that password\-less access to the remote host must be configured. +Here is an example configuration for the ssh launcher: +.INDENT 2.0 +.INDENT 3.5 +.sp +.nf +.ft C +{ + \(aqname\(aq: \(aqfoo\(aq + \(aqscheduler\(aq: \(aqlocal\(aq, + \(aqlauncher\(aq: \(aqssh\(aq + \(aqaccess\(aq: [\(aq\-l admin\(aq, \(aqremote.host\(aq], + \(aqenvirons\(aq: [\(aqbuiltin\(aq], +} +.ft P +.fi +.UNINDENT +.UNINDENT +.IP \(bu 2 +\fBupcrun\fP: Parallel programs will be launched using the \fI\%UPC\fP \fBupcrun\fP command. +.IP \(bu 2 +\fBupcxx\-run\fP: Parallel programs will be launched using the \fI\%UPC++\fP \fBupcxx\-run\fP command. +.UNINDENT +.sp +\fBTIP:\fP +.INDENT 7.0 +.INDENT 3.5 +New in version 4.0.0: ReFrame also allows you to register your own custom launchers simply by defining them in the configuration. +You can follow a small tutorial \fI\%here\fP\&. + +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.access +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of job scheduler options that will be passed to the generated job script for gaining access to that logical partition. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.environs +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B required +No +.TP +.B default +\fB[]\fP +.UNINDENT +.UNINDENT +.UNINDENT +.sp +A list of environment names that ReFrame will use to run regression tests on this partition. +Each environment must be defined in the \fI\%environments\fP section of the configuration and the definition of the environment must be valid for this partition. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.container_platforms +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list for \fI\%container platform configuration objects\fP\&. +This will allow launching regression tests that use containers on this partition. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.modules +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B required +No +.TP +.B default +\fB[]\fP +.UNINDENT +.UNINDENT +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to be loaded before running a regression test on this partition. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.time_limit +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBnull\fP +.UNINDENT +.sp +The time limit for the jobs submitted on this partition. +When the value is \fBnull\fP, no time limit is applied. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.variables +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of environment variables to be set before running a regression test on this partition. +Each environment variable is specified as a two\-element list containing the variable name and its value. +You may reference other environment variables when defining an environment variable here. +ReFrame will expand its value. +Variables are set after the environment modules are loaded. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.max_jobs +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB8\fP +.UNINDENT +.sp +The maximum number of concurrent regression tests that may be active (i.e., not completed) on this partition. +This option is relevant only when ReFrame executes with the \fI\%asynchronous execution policy\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.prepare_cmds +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +List of shell commands to be emitted before any environment loading commands are emitted. +.sp +New in version 3.5.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.resources +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of job scheduler \fI\%resource specification\fP objects. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.processor +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB{}\fP +.UNINDENT +.sp +Processor information for this partition stored in a \fI\%processor info object\fP\&. +If not set, ReFrame will try to auto\-detect this information (see \fI\%Auto\-detecting processor information\fP for more information). +.sp +New in version 3.5.0. + +.sp +Changed in version 3.7.0: ReFrame is now able to detect the processor information automatically. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.devices +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list with \fI\%device info objects\fP for this partition. +.sp +New in version 3.5.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.features +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +User defined features of the partition. +These are accessible through the \fI\%features\fP attribute of the \fI\%current_partition\fP and can also be selected through the extended syntax of \fI\%valid_systems\fP\&. +The values of this list must be alphanumeric strings starting with a non\-digit character and may also contain a \fB\-\fP\&. +.sp +New in version 3.11.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.extras +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB{}\fP +.UNINDENT +.sp +User defined attributes of the partition. +These are accessible through the \fI\%extras\fP attribute of the \fI\%current_partition\fP and can also be selected through the extended syntax of \fI\%valid_systems\fP\&. +The attributes of this object must be alphanumeric strings starting with a non\-digit character and their values can be of any type. +.sp +New in version 3.5.0. + +.UNINDENT +.SS Container Platform Configuration +.sp +ReFrame can launch containerized applications, but you need to configure properly a system partition in order to do that by defining a container platform configuration. +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.type +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The type of the container platform. +Available values are the following: +.INDENT 7.0 +.IP \(bu 2 +\fBDocker\fP: The \fI\%Docker\fP container runtime. +.IP \(bu 2 +\fBSarus\fP: The \fI\%Sarus\fP container runtime. +.IP \(bu 2 +\fBShifter\fP: The \fI\%Shifter\fP container runtime. +.IP \(bu 2 +\fBSingularity\fP: The \fI\%Singularity\fP container runtime. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.default +.INDENT 7.0 +.TP +.B Required +No +.UNINDENT +.sp +If set to \fBtrue\fP, this is the default container platform of this partition. +If not specified, the default container platform is assumed to be the first in the list of \fBcontainer_platforms\fP\&. +.sp +New in version 3.12.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.modules +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to be loaded when running containerized tests using this container platform. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.variables +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +List of environment variables to be set when running containerized tests using this container platform. +Each environment variable is specified as a two\-element list containing the variable name and its value. +You may reference other environment variables when defining an environment variable here. +ReFrame will expand its value. +Variables are set after the environment modules are loaded. +.UNINDENT +.SS Custom Job Scheduler Resources +.sp +ReFrame allows you to define custom scheduler resources for each partition that you can then transparently access through the \fBextra_resources\fP attribute of a regression test. +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.resources[]\&.name +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B required +Yes +.UNINDENT +.UNINDENT +.UNINDENT +.sp +The name of this resources. +This name will be used to request this resource in a regression test’s \fBextra_resources\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.systems[]\&.partitions[]\&.resources[]\&.options +.INDENT 7.0 +.INDENT 3.5 +.INDENT 0.0 +.TP +.B required +No +.TP +.B default +\fB[]\fP +.UNINDENT +.sp +A list of options to be passed to this partition’s job scheduler. +The option strings can contain placeholders of the form \fB{placeholder_name}\fP\&. +These placeholders may be replaced with concrete values by a regression test through the \fBextra_resources\fP attribute. +.sp +For example, one could define a \fBgpu\fP resource for a multi\-GPU system that uses Slurm as follows: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(aqresources\(aq: [ + { + \(aqname\(aq: \(aqgpu\(aq, + \(aqoptions\(aq: [\(aq\-\-gres=gpu:{num_gpus_per_node}\(aq] + } +] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +A regression test then may request this resource as follows: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +self.extra_resources = {\(aqgpu\(aq: {\(aqnum_gpus_per_node\(aq: \(aq8\(aq}} +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +And the generated job script will have the following line in its preamble: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +#SBATCH \-\-gres=gpu:8 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +A resource specification may also start with \fB#PREFIX\fP, in which case \fB#PREFIX\fP will replace the standard job script prefix of the backend scheduler of this partition. +This is useful in cases of job schedulers like Slurm, that allow alternative prefixes for certain features. +An example is the \fI\%DataWarp\fP functionality of Slurm which is supported by the \fB#DW\fP prefix. +One could then define DataWarp related resources as follows: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(aqresources\(aq: [ + { + \(aqname\(aq: \(aqdatawarp\(aq, + \(aqoptions\(aq: [ + \(aq#DW jobdw capacity={capacity} access_mode={mode} type=scratch\(aq, + \(aq#DW stage_out source={out_src} destination={out_dst} type={stage_filetype}\(aq + ] + } +] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +A regression test that wants to make use of that resource, it can set its \fBextra_resources\fP as follows: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +self.extra_resources = { + \(aqdatawarp\(aq: { + \(aqcapacity\(aq: \(aq100GB\(aq, + \(aqmode\(aq: \(aqstriped\(aq, + \(aqout_src\(aq: \(aq$DW_JOB_STRIPED/name\(aq, + \(aqout_dst\(aq: \(aq/my/file\(aq, + \(aqstage_filetype\(aq: \(aqfile\(aq + } +} +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +For the \fBpbs\fP and \fBtorque\fP backends, options accepted in the \fI\%access\fP and \fI\%resources\fP attributes may either refer to actual \fBqsub\fP options or may be just resources specifications to be passed to the \fB\-l\fP option. +The backend assumes a \fBqsub\fP option, if the options passed in these attributes start with a \fB\-\fP\&. +.UNINDENT +.UNINDENT +.UNINDENT +.SH ENVIRONMENT CONFIGURATION +.sp +Environments defined in this section will be used for running regression tests. +They are associated with \fI\%system partitions\fP\&. +.INDENT 0.0 +.TP +.B \&.environments[]\&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of this environment. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.modules +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to be loaded when this environment is loaded. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.variables +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of environment variables to be set when loading this environment. +Each environment variable is specified as a two\-element list containing the variable name and its value. +You may reference other environment variables when defining an environment variable here. +ReFrame will expand its value. +Variables are set after the environment modules are loaded. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.features +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +User defined features of the environment. +These are accessible through the \fI\%features\fP attribute of the \fI\%current_environ\fP and can also be selected through the extended syntax of \fI\%valid_prog_environs\fP\&. +The values of this list must be alphanumeric strings starting with a non\-digit character and may also contain a \fB\-\fP\&. +.sp +New in version 3.11.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.extras +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB{}\fP +.UNINDENT +.sp +User defined attributes of the environment. +These are accessible through the \fI\%extras\fP attribute of the \fI\%current_environ\fP and can also be selected through the extended syntax of \fI\%valid_prog_environs\fP\&. +The attributes of this object must be alphanumeric strings starting with a non\-digit character and their values can be of any type. +.sp +New in version 3.9.1. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.cc +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"cc"\fP +.UNINDENT +.sp +The C compiler to be used with this environment. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.cxx +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"CC"\fP +.UNINDENT +.sp +The C++ compiler to be used with this environment. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.ftn +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"ftn"\fP +.UNINDENT +.sp +The Fortran compiler to be used with this environment. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.cppflags +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of C preprocessor flags to be used with this environment by default. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.cflags +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of C flags to be used with this environment by default. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.cxxflags +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of C++ flags to be used with this environment by default. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.fflags +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of Fortran flags to be used with this environment by default. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.ldflags +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of linker flags to be used with this environment by default. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.environments[]\&.target_systems +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["*"]\fP +.UNINDENT +.sp +A list of systems or system/partitions combinations that this environment definition is valid for. +A \fB*\fP entry denotes any system. +In case of multiple definitions of an environment, the most specific to the current system partition will be used. +For example, if the current system/partition combination is \fBdaint:mc\fP, the second definition of the \fBPrgEnv\-gnu\fP environment will be used: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(aqenvironments\(aq: [ + { + \(aqname\(aq: \(aqPrgEnv\-gnu\(aq, + \(aqmodules\(aq: [\(aqPrgEnv\-gnu\(aq] + }, + { + \(aqname\(aq: \(aqPrgEnv\-gnu\(aq, + \(aqmodules\(aq: [\(aqPrgEnv\-gnu\(aq, \(aqopenmpi\(aq], + \(aqcc\(aq: \(aqmpicc\(aq, + \(aqcxx\(aq: \(aqmpicxx\(aq, + \(aqftn\(aq: \(aqmpif90\(aq, + \(aqtarget_systems\(aq: [\(aqdaint:mc\(aq] + } +] +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +However, if the current system was \fBdaint:gpu\fP, the first definition would be selected, despite the fact that the second definition is relevant for another partition of the same system. +To better understand this, ReFrame resolves definitions in a hierarchical way. +It first looks for definitions for the current partition, then for the containing system and, finally, for global definitions (the \fB*\fP pseudo\-system). +.UNINDENT +.SH LOGGING CONFIGURATION +.sp +Logging in ReFrame is handled by logger objects which further delegate message to \fIlogging handlers\fP which are eventually responsible for emitting or sending the log records to their destinations. +You may define different logger objects per system but \fInot\fP per partition. +.INDENT 0.0 +.TP +.B \&.logging[]\&.level +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"undefined"\fP +.UNINDENT +.sp +The level associated with this logger object. +There are the following levels in decreasing severity order: +.INDENT 7.0 +.IP \(bu 2 +\fBcritical\fP: Catastrophic errors; the framework cannot proceed with its execution. +.IP \(bu 2 +\fBerror\fP: Normal errors; the framework may or may not proceed with its execution. +.IP \(bu 2 +\fBwarning\fP: Warning messages. +.IP \(bu 2 +\fBinfo\fP: Informational messages. +.IP \(bu 2 +\fBverbose\fP: More informational messages. +.IP \(bu 2 +\fBdebug\fP: Debug messages. +.IP \(bu 2 +\fBdebug2\fP: Further debug messages. +.IP \(bu 2 +\fBundefined\fP: This is the lowest level; do not filter any message. +.UNINDENT +.sp +If a message is logged by the framework, its severity level will be checked by the logger and if it is higher from the logger’s level, it will be passed down to its handlers. +.sp +New in version 3.3: The \fBdebug2\fP and \fBundefined\fP levels are added. + +.sp +Changed in version 3.3: The default level is now \fBundefined\fP\&. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of logging handlers responsible for handling normal framework output. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers_perflog +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +A list of logging handlers responsible for handling performance data from tests. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.target_systems +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["*"]\fP +.UNINDENT +.sp +A list of systems or system/partitions combinations that this logging configuration is valid for. +For a detailed description of this property, you may refer \fI\%here\fP\&. +.UNINDENT +.SS Common logging handler properties +.sp +All logging handlers share the following set of common attributes: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.type +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers_perflog[]\&.type +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The type of handler. +There are the following types available: +.INDENT 7.0 +.IP \(bu 2 +\fBfile\fP: This handler sends log records to file. +See \fI\%here\fP for more details. +.IP \(bu 2 +\fBfilelog\fP: This handler sends performance log records to files. +See \fI\%here\fP for more details. +.IP \(bu 2 +\fBgraylog\fP: This handler sends performance log records to Graylog. +See \fI\%here\fP for more details. +.IP \(bu 2 +\fBstream\fP: This handler sends log records to a file stream. +See \fI\%here\fP for more details. +.IP \(bu 2 +\fBsyslog\fP: This handler sends log records to a Syslog facility. +See \fI\%here\fP for more details. +.IP \(bu 2 +\fBhttpjson\fP: This handler sends log records in JSON format using HTTP post requests. +See \fI\%here\fP for more details. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.level +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers_perflog[]\&.level +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"info"\fP +.UNINDENT +.sp +The \fI\%log level\fP associated with this handler. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.format +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers_perflog[]\&.format +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"%(message)s"\fP +.UNINDENT +.sp +Log record format string. +ReFrame accepts all log record attributes from Python’s \fI\%logging\fP mechanism and adds the following: +.TS +center; +|l|l|l|. +_ +T{ +Log record attribute +T} T{ +Description +T} T{ +T} +_ +T{ +\fB%(check_build_locally)s\fP +T} T{ +The value of the \fI\%build_locally\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_build_time_limit)s\fP +T} T{ +The value of the \fI\%build_time_limit\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_descr)s\fP +T} T{ +The value of the \fI\%descr\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_display_name)s\fP +T} T{ +The value of the \fI\%display_name\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_environ)s\fP +T} T{ +The name of the test’s \fI\%current_environ\fP\&. +T} T{ +T} +_ +T{ +\fB%(check_exclusive_access)s\fP +T} T{ +The value of the \fI\%exclusive_access\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_executable)s\fP +T} T{ +The value of the \fI\%executable\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_executable_opts)s\fP +T} T{ +The value of the \fI\%executable_opts\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_extra_resources)s\fP +T} T{ +The value of the \fI\%extra_resources\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_hashcode)s\fP +T} T{ +The unique hash associated with this test. +T} T{ +T} +_ +T{ +\fB%(check_info)s\fP +T} T{ +Various information about this test; essentially the return value of the test’s \fI\%info()\fP function. +T} T{ +T} +_ +T{ +\fB%(check_job_completion_time)s\fP +T} T{ +Same as the \fB(check_job_completion_time_unix)s\fP but formatted according to \fBdatefmt\fP\&. +T} T{ +T} +_ +T{ +\fB%(check_job_completion_time_unix)s\fP +T} T{ +The completion time of the associated run job (see \fI\%reframe.core.schedulers.Job.completion_time\fP). +T} T{ +T} +_ +T{ +\fB%(check_job_exitcode)s\fP +T} T{ +The exit code of the associated run job. +T} T{ +T} +_ +T{ +\fB%(check_job_nodelist)s\fP +T} T{ +The list of nodes that the associated run job has run on. +T} T{ +T} +_ +T{ +\fB%(check_jobid)s\fP +T} T{ +The ID of the associated run job. +T} T{ +T} +_ +T{ +\fB%(check_keep_files)s\fP +T} T{ +The value of the \fI\%keep_files\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_local)s\fP +T} T{ +The value of the \fI\%local\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_maintainers)s\fP +T} T{ +The value of the \fI\%maintainers\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_max_pending_time)s\fP +T} T{ +The value of the \fI\%max_pending_time\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_modules)s\fP +T} T{ +The value of the \fI\%modules\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_name)s\fP +T} T{ +The value of the \fI\%name\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_cpus_per_task)s\fP +T} T{ +The value of the \fI\%num_cpus_per_task\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_gpus_per_node)s\fP +T} T{ +The value of the \fI\%num_gpus_per_node\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_tasks)s\fP +T} T{ +The value of the \fI\%num_tasks\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_tasks_per_core)s\fP +T} T{ +The value of the \fI\%num_tasks_per_core\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_tasks_per_node)s\fP +T} T{ +The value of the \fI\%num_tasks_per_node\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_num_tasks_per_socket)s\fP +T} T{ +The value of the \fI\%num_tasks_per_socket\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_outputdir)s\fP +T} T{ +The value of the \fI\%outputdir\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_partition)s\fP +T} T{ +The name of the test’s \fI\%current_partition\fP\&. +T} T{ +T} +_ +T{ +\fB%(check_perf_lower_thres)s\fP +T} T{ +The lower threshold of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perf_ref)s\fP +T} T{ +The reference value of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perf_unit)s\fP +T} T{ +The measurement unit of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perf_upper)s\fP +T} T{ +The upper thresholds of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perf_value)s\fP +T} T{ +The actual value of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perf_var)s\fP +T} T{ +The name of the logged performance variable. +T} T{ +T} +_ +T{ +\fB%(check_perfvalues)s\fP +T} T{ +All the performance variables of the test combined along with their values +T} T{ +references and thresholds. +T} +_ +T{ +\fB%(check_postbuild_cmds)s\fP +T} T{ +The value of the \fI\%postbuild_cmds\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_postrun_cmds)s\fP +T} T{ +The value of the \fI\%postrun_cmds\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_prebuild_cmds)s\fP +T} T{ +The value of the \fI\%prebuild_cmds\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_prefix)s\fP +T} T{ +The value of the \fI\%prefix\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_prerun_cmds)s\fP +T} T{ +The value of the \fI\%prerun_cmds\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_readonly_files)s\fP +T} T{ +The value of the \fI\%readonly_files\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_short_name)s\fP +T} T{ +The value of the \fI\%short_name\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_sourcepath)s\fP +T} T{ +The value of the \fI\%sourcepath\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_sourcesdir)s\fP +T} T{ +The value of the \fI\%sourcesdir\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_stagedir)s\fP +T} T{ +The value of the \fI\%stagedir\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_strict_check)s\fP +T} T{ +The value of the \fI\%strict_check\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_system)s\fP +T} T{ +The name of the test’s \fI\%current_system\fP\&. +T} T{ +T} +_ +T{ +\fB%(check_tags)s\fP +T} T{ +The value of the \fI\%tags\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_time_limit)s\fP +T} T{ +The value of the \fI\%time_limit\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_unique_name)s\fP +T} T{ +The value of the \fI\%unique_name\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_use_multithreading)s\fP +T} T{ +The value of the \fI\%use_multithreading\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_valid_prog_environs)s\fP +T} T{ +The value of the \fI\%valid_prog_environs\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_valid_systems)s\fP +T} T{ +The value of the \fI\%valid_systems\fP attribute. +T} T{ +T} +_ +T{ +\fB%(check_variables)s\fP +T} T{ +The value of the \fI\%variables\fP attribute. +T} T{ +T} +_ +T{ +\fB%(osuser)s\fP +T} T{ +The name of the OS user running ReFrame. +T} T{ +T} +_ +T{ +\fB%(osgroup)s\fP +T} T{ +The name of the OS group running ReFrame. +T} T{ +T} +_ +T{ +\fB%(version)s\fP +T} T{ +The ReFrame version. +T} T{ +T} +_ +.TE +.sp +ReFrame allows you to log any test variable, parameter or property if they are marked as “loggable”. +The log record attribute will have the form \fB%(check_NAME)s\fP where \fBNAME\fP is the variable name, the parameter name or the property name that is marked as loggable. +.UNINDENT +.sp +New in version 3.3: Allow arbitrary test attributes to be logged. + +.sp +New in version 3.4.2: Allow arbitrary job attributes to be logged. + +.sp +Changed in version 3.11.0: Limit the number of attributes that can be logged. User attributes or properties must be explicitly marked as “loggable” in order to be selectable for logging. + +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.datefmt +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].datefmt +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"%FT%T"\fP +.UNINDENT +.sp +Time format to be used for printing timestamps fields. +There are two timestamp fields available: \fB%(asctime)s\fP and \fB%(check_job_completion_time)s\fP\&. +In addition to the format directives supported by the standard library’s \fI\%time.strftime()\fP function, ReFrame allows you to use the \fB%:z\fP directive – a GNU \fBdate\fP extension – that will print the time zone difference in a RFC3339 compliant way, i.e., \fB+/\-HH:MM\fP instead of \fB+/\-HHMM\fP\&. +.UNINDENT +.SS The \fBfile\fP log handler +.sp +This log handler handles output to normal files. +The additional properties for the \fBfile\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.name +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].name +.INDENT 7.0 +.TP +.B Required +No +.UNINDENT +.sp +The name of the file where this handler will write log records. +If not specified, ReFrame will create a log file prefixed with \fBrfm\-\fP in the system’s temporary directory. +.sp +Changed in version 3.3: The \fBname\fP parameter is no more required and the default log file resides in the system’s temporary directory. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.append +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].append +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Controls whether this handler should append to its file or not. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.timestamp +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].timestamp +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Append a timestamp to this handler’s log file. +This property may also accept a date format as described in the \fI\%datefmt\fP property. +If the handler’s \fI\%name\fP property is set to \fBfilename.log\fP and this property is set to \fBtrue\fP or to a specific timestamp format, the resulting log file will be \fBfilename_.log\fP\&. +.UNINDENT +.SS The \fBfilelog\fP log handler +.sp +This handler is meant primarily for performance logging and logs the performance of a regression test in one or more files. +The additional properties for the \fBfilelog\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.basedir +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].basedir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"./perflogs"\fP +.UNINDENT +.sp +The base directory of performance data log files. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.prefix +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].prefix +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +This is a directory prefix (usually dynamic), appended to the \fI\%basedir\fP, where the performance logs of a test will be stored. +This attribute accepts any of the check\-specific \fI\%formatting placeholders\fP\&. +This allows to create dynamic paths based on the current system, partition and/or programming environment a test executes with. +For example, a value of \fB%(check_system)s/%(check_partition)s\fP would generate the following structure of performance log files: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +{basedir}/ + system1/ + partition1/ + test_short_name.log + partition2/ + test_short_name.log + ... + system2/ + ... +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers[].append +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].append +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBtrue\fP +.UNINDENT +.sp +Open each log file in append mode. +.UNINDENT +.SS The \fBgraylog\fP log handler +.sp +This handler sends log records to a \fI\%Graylog\fP server. +The additional properties for the \fBgraylog\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.address +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].address +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The address of the Graylog server defined as \fBhost:port\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.extras +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].extras +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB{}\fP +.UNINDENT +.sp +A set of optional key/value pairs to be passed with each log record to the server. +These may depend on the server configuration. +.UNINDENT +.sp +This log handler uses internally \fI\%pygelf\fP\&. +If \fBpygelf\fP is not available, this log handler will be ignored. +\fI\%GELF\fP is a format specification for log messages that are sent over the network. +The \fBgraylog\fP handler sends log messages in JSON format using an HTTP POST request to the specified address. +More details on this log format may be found \fI\%here\fP\&. +An example configuration of this handler for performance logging is shown here: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +{ + \(aqtype\(aq: \(aqgraylog\(aq, + \(aqaddress\(aq: \(aqgraylog\-server:12345\(aq, + \(aqlevel\(aq: \(aqinfo\(aq, + \(aqformat\(aq: \(aq%(message)s\(aq, + \(aqextras\(aq: { + \(aqfacility\(aq: \(aqreframe\(aq, + \(aqdata\-version\(aq: \(aq1.0\(aq + } +} +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Although the \fBformat\fP is defined for this handler, it is not only the log message that will be transmitted the Graylog server. +This handler transmits the whole log record, meaning that all the information will be available and indexable at the remote end. +.SS The \fBstream\fP log handler +.sp +This handler sends log records to a file stream. +The additional properties for the \fBstream\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[].handlers[].name +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].name +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"stdout"\fP +.UNINDENT +.sp +The name of the file stream to send records to. +There are only two available streams: +.INDENT 7.0 +.IP \(bu 2 +\fBstdout\fP: the standard output. +.IP \(bu 2 +\fBstderr\fP: the standard error. +.UNINDENT +.UNINDENT +.SS The \fBsyslog\fP log handler +.sp +This handler sends log records to UNIX syslog. +The additional properties for the \fBsyslog\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.socktype +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].socktype +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"udp"\fP +.UNINDENT +.sp +The socket type where this handler will send log records to. +There are two socket types: +.INDENT 7.0 +.IP \(bu 2 +\fBudp\fP: A UDP datagram socket. +.IP \(bu 2 +\fBtcp\fP: A TCP stream socket. +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.facility +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].facility +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"user"\fP +.UNINDENT +.sp +The Syslog facility where this handler will send log records to. +The list of supported facilities can be found \fI\%here\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers[].address +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].address +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The socket address where this handler will connect to. +This can either be of the form \fB:\fP or simply a path that refers to a Unix domain socket. +.UNINDENT +.SS The \fBhttpjson\fP log handler +.sp +This handler sends log records in JSON format to a server using HTTP POST requests. +The additional properties for the \fBhttpjson\fP handler are the following: +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.url +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].url +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The URL to be used in the HTTP(S) request server. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[]\&.handlers[]\&.extras +.UNINDENT +.INDENT 0.0 +.TP +.B \&.logging[].handlers_perflog[].extras +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB{}\fP +.UNINDENT +.sp +A set of optional key/value pairs to be passed with each log record to the server. +These may depend on the server configuration. +.UNINDENT +.sp +The \fBhttpjson\fP handler sends log messages in JSON format using an HTTP POST request to the specified URL. +.sp +An example configuration of this handler for performance logging is shown here: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +{ + \(aqtype\(aq: \(aqhttpjson\(aq, + \(aqurl\(aq: \(aqhttp://httpjson\-server:12345/rfm\(aq, + \(aqlevel\(aq: \(aqinfo\(aq, + \(aqextras\(aq: { + \(aqfacility\(aq: \(aqreframe\(aq, + \(aqdata\-version\(aq: \(aq1.0\(aq + } +} +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +This handler transmits the whole log record, meaning that all the information will be available and indexable at the remote end. +.SH SCHEDULER CONFIGURATION +.sp +A scheduler configuration object contains configuration options specific to the scheduler’s behavior. +.SS Common scheduler options +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of the scheduler that these options refer to. +It can be any of the supported job scheduler \fI\%backends\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.job_submit_timeout +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +60 +.UNINDENT +.sp +Timeout in seconds for the job submission command. +If timeout is reached, the regression test issuing that command will be marked as a failure. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.target_systems +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["*"]\fP +.UNINDENT +.sp +A list of systems or system/partitions combinations that this scheduler configuration is valid for. +For a detailed description of this property, you may refer \fI\%here\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.use_nodes_option +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Always emit the \fB\-\-nodes\fP Slurm option in the preamble of the job script. +This option is relevant to Slurm backends only. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.ignore_reqnodenotavail +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +This option is relevant to the Slurm backends only. +.sp +If a job associated to a test is in pending state with the Slurm reason \fBReqNodeNotAvail\fP and a list of unavailable nodes is also specified, ReFrame will check the status of the nodes and, if all of them are indeed down, it will cancel the job. +Sometimes, however, when Slurm’s backfill algorithm takes too long to compute, Slurm will set the pending reason to \fBReqNodeNotAvail\fP and mark all system nodes as unavailable, causing ReFrame to kill the job. +In such cases, you may set this parameter to \fBtrue\fP to avoid this. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.schedulers[]\&.resubmit_on_errors +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +This option is relevant to the Slurm backends only. +.sp +If any of the listed errors occur, ReFrame will try to resubmit the job after some seconds. +As an example, you could have ReFrame trying to resubmit a job in case that the maximum submission limit per user is reached by setting this field to \fB["QOSMaxSubmitJobPerUserLimit"]\fP\&. +You can ignore multiple errors at the same time if you add more error strings in the list. +.sp +New in version 3.4.1. + +.sp +\fBWARNING:\fP +.INDENT 7.0 +.INDENT 3.5 +Job submission is a synchronous operation in ReFrame. +If this option is set, ReFrame’s execution will block until the error conditions specified in this list are resolved. +No other test would be able to proceed. +.UNINDENT +.UNINDENT +.UNINDENT +.SH EXECUTION MODE CONFIGURATION +.sp +ReFrame allows you to define groups of command line options that are collectively called \fIexecution modes\fP\&. +An execution mode can then be selected from the command line with the \fB\-mode\fP option. +The options of an execution mode will be passed to ReFrame as if they were specified in the command line. +.INDENT 0.0 +.TP +.B \&.modes[]\&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of this execution mode. +This can be used with the \fI\%\-\-mode\fP command line option to invoke this mode. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.modes[]\&.options +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +The command\-line options associated with this execution mode. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.modes[]\&.target_systems +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["*"]\fP +.UNINDENT +.sp +A list of systems \fIonly\fP that this execution mode is valid for. +For a detailed description of this property, you may refer \fI\%here\fP\&. +.UNINDENT +.SH GENERAL CONFIGURATION +.INDENT 0.0 +.TP +.B \&.general[]\&.check_search_path +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["${RFM_INSTALL_PREFIX}/checks/"]\fP +.UNINDENT +.sp +A list of paths (files or directories) where ReFrame will look for regression test files. +If the search path is set through the environment variable, it should be a colon separated list. +If specified from command line, the search path is constructed by specifying multiple times the command line option. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.check_search_recursive +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Search directories in the \fI\%search path\fP recursively. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.clean_stagedir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBtrue\fP +.UNINDENT +.sp +Clean stage directory of tests before populating it. +.sp +New in version 3.1. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.colorize +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBtrue\fP +.UNINDENT +.sp +Use colors in output. +The command\-line option sets the configuration option to \fBfalse\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.compress_report +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Compress the generated run report file. +See the documentation of the \fI\%\-\-compress\-report\fP option for more information. +.sp +New in version 3.12.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.git_timeout +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +5 +.UNINDENT +.sp +Timeout value in seconds used when checking if a git repository exists. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.dump_pipeline_progress +Dump pipeline progress for the asynchronous execution policy in \fBpipeline\-progress.json\fP\&. +This option is meant for debug purposes only. +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBFalse\fP +.UNINDENT +.sp +New in version 3.10.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.pipeline_timeout +Timeout in seconds for advancing the pipeline in the asynchronous execution policy. +.sp +ReFrame’s asynchronous execution policy will try to advance as many tests as possible in their pipeline, but some tests may take too long to proceed (e.g., due to copying of large files) blocking the advancement of previously started tests. +If this timeout value is exceeded and at least one test has progressed, ReFrame will stop processing new tests and it will try to further advance tests that have already started. +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB10\fP +.UNINDENT +.sp +New in version 3.10.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.remote_detect +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Try to auto\-detect processor information of remote partitions as well. +This may slow down the initialization of the framework, since it involves submitting auto\-detection jobs to the remote partitions. +For more information on how ReFrame auto\-detects processor information, you may refer to \fI\%Auto\-detecting processor information\fP\&. +.sp +New in version 3.7.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.remote_workdir +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"."\fP +.UNINDENT +.sp +The temporary directory prefix that will be used to create a fresh ReFrame clone, in order to auto\-detect the processor information of a remote partition. +.sp +New in version 3.7.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.ignore_check_conflicts +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Ignore test name conflicts when loading tests. +.sp +Deprecated since version 3.8.0: This option will be removed in a future version. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.trap_job_errors +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Trap command errors in the generated job scripts and let them exit immediately. +.sp +New in version 3.2. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.keep_stage_files +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Keep stage files of tests even if they succeed. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.module_map_file +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB""\fP +.UNINDENT +.sp +File containing module mappings. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.module_mappings +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of module mappings. +If specified through the environment variable, the mappings must be separated by commas. +If specified from command line, multiple module mappings are defined by passing the command line option multiple times. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.non_default_craype +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Test a non\-default Cray Programming Environment. +This will emit some special instructions in the generated build and job scripts. +See also \fI\%\-\-non\-default\-craype\fP for more details. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.purge_environment +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Purge any loaded environment modules before running any tests. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.report_file +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB"${HOME}/.reframe/reports/run\-report\-{sessionid}.json"\fP +.UNINDENT +.sp +The file where ReFrame will store its report. +.sp +New in version 3.1. + +.sp +Changed in version 3.2: Default value has changed to avoid generating a report file per session. + +.sp +Changed in version 4.0.0: Default value was reverted back to generate a new file per run. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.report_junit +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBnull\fP +.UNINDENT +.sp +The file where ReFrame will store its report in JUnit format. +The report adheres to the XSD schema \fI\%here\fP\&. +.sp +New in version 3.6.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.resolve_module_conflicts +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBtrue\fP +.UNINDENT +.sp +ReFrame by default resolves any module conflicts and emits the right sequence of \fBmodule unload\fP and \fBmodule load\fP commands, in order to load the requested modules. +This option disables this behavior if set to \fBfalse\fP\&. +.sp +You should avoid using this option for modules system that cannot handle module conflicts automatically, such as early Tmod verions. +.sp +Disabling the automatic module conflict resolution, however, can be useful when modules in a remote system partition are not present on the host where ReFrame runs. +In order to resolve any module conflicts and generate the right load sequence of modules, ReFrame loads temporarily the requested modules and tracks any conflicts along the way. +By disabling this option, ReFrame will simply emit the requested \fBmodule load\fP commands without attempting to load any module. +.sp +New in version 3.6.0. + +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.save_log_files +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Save any log files generated by ReFrame to its output directory +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.target_systems +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB["*"]\fP +.UNINDENT +.sp +A list of systems or system/partitions combinations that these general options are valid for. +For a detailed description of this property, you may refer \fI\%here\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.timestamp_dirs +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB""\fP +.UNINDENT +.sp +Append a timestamp to ReFrame directory prefixes. +Valid formats are those accepted by the \fI\%time.strftime()\fP function. +If specified from the command line without any argument, \fB"%FT%T"\fP will be used as a time format. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.unload_modules +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to unload before executing any test. +If specified using an the environment variable, a space separated list of modules is expected. +If specified from the command line, multiple modules can be passed by passing the command line option multiple times. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.use_login_shell +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +Use a login shell for the generated job scripts. +This option will cause ReFrame to emit \fB\-l\fP in the shebang of shell scripts. +This option, if set to \fBtrue\fP, may cause ReFrame to fail, if the shell changes permanently to a different directory during its start up. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.user_modules +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fB[]\fP +.UNINDENT +.sp +A list of \fI\%environment module objects\fP to be loaded before executing any test. +If specified using an the environment variable, a space separated list of modules is expected. +If specified from the command line, multiple modules can be passed by passing the command line option multiple times. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.general[]\&.verbose +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +0 +.UNINDENT +.sp +Set the verbosity level of the output. +The higher the number, the more verbose the output will be. +If set to a negative number, this will decrease the verbosity level. +.UNINDENT +.SH MODULE OBJECTS +.sp +New in version 3.3. + +.sp +A \fImodule object\fP in ReFrame’s configuration represents an environment module. +It can either be a simple string or a JSON object with the following attributes: +.INDENT 0.0 +.TP +.B \&.name +.INDENT 7.0 +.TP +.B Required +Yes +.UNINDENT +.sp +The name of the module. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.collection +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBfalse\fP +.UNINDENT +.sp +A boolean value indicating whether this module refers to a module collection. +Module collections are treated differently from simple modules when loading. +.UNINDENT +.INDENT 0.0 +.TP +.B path +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBnull\fP +.UNINDENT +.sp +If the module is not present in the default \fBMODULEPATH\fP, the module’s location can be specified here. +ReFrame will make sure to set and restore the \fBMODULEPATH\fP accordingly for loading the module. +.sp +New in version 3.5.0. + +.UNINDENT +.sp +\fBSEE ALSO:\fP +.INDENT 0.0 +.INDENT 3.5 +Module collections with \fI\%Environment Modules\fP and \fI\%Lmod\fP\&. +.UNINDENT +.UNINDENT +.SH PROCESSOR INFO +.sp +New in version 3.5.0. + +.sp +A \fIprocessor info object\fP in ReFrame’s configuration is used to hold information about the processor of a system partition and is made available to the tests through the \fI\%processor\fP attribute of the \fI\%current_partition\fP\&. +.INDENT 0.0 +.TP +.B \&.arch +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +The microarchitecture of the processor. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.num_cpus +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Number of logical CPUs. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.num_cpus_per_core +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Number of logical CPUs per core. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.num_cpus_per_socket +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Number of logical CPUs per socket. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.num_sockets +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Number of sockets. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.topology +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Processor topology. +An example follows: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +\(aqtopology\(aq: { + \(aqnuma_nodes\(aq: [\(aq0x000000ff\(aq], + \(aqsockets\(aq: [\(aq0x000000ff\(aq], + \(aqcores\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, + \(aq0x00000030\(aq, \(aq0x000000c0\(aq], + \(aqcaches\(aq: [ + { + \(aqtype\(aq: \(aqL3\(aq, + \(aqsize\(aq: 6291456, + \(aqlinesize\(aq: 64, + \(aqassociativity\(aq: 0, + \(aqnum_cpus\(aq: 8, + \(aqcpusets\(aq: [\(aq0x000000ff\(aq] + }, + { + \(aqtype\(aq: \(aqL2\(aq, + \(aqsize\(aq: 262144, + \(aqlinesize\(aq: 64, + \(aqassociativity\(aq: 4, + \(aqnum_cpus\(aq: 2, + \(aqcpusets\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, + \(aq0x00000030\(aq, \(aq0x000000c0\(aq] + }, + { + \(aqtype\(aq: \(aqL1\(aq, + \(aqsize\(aq: 32768, + \(aqlinesize\(aq: 64, + \(aqassociativity\(aq: 0, + \(aqnum_cpus\(aq: 2, + \(aqcpusets\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, + \(aq0x00000030\(aq, \(aq0x000000c0\(aq] + } + ] +} +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.SH DEVICE INFO +.sp +New in version 3.5.0. + +.sp +A \fIdevice info object\fP in ReFrame’s configuration is used to hold information about a specific type of devices in a system partition and is made available to the tests through the \fI\%devices\fP attribute of the \fI\%current_partition\fP\&. +.INDENT 0.0 +.TP +.B \&.type +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +The type of the device, for example \fB"gpu"\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.arch +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +The microarchitecture of the device. +.UNINDENT +.INDENT 0.0 +.TP +.B \&.num_devices +.INDENT 7.0 +.TP +.B Required +No +.TP +.B Default +\fBNone\fP +.UNINDENT +.sp +Number of devices of this type inside the system partition. +.UNINDENT +.SH AUTHOR +ReFrame Project Developers +.SH COPYRIGHT +2016-2022, CSCS/ETH Zurich +.\" Generated by docutils manpage writer. +. diff --git a/docs/manpage.rst b/docs/manpage.rst index 71d1091fd4..1911a8080f 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -775,13 +775,13 @@ It does so by leveraging the selected system's environment modules system. Miscellaneous options --------------------- -.. option:: -C --config-files=FILE +.. option:: -C --config-file=FILE Use ``FILE`` as configuration file for ReFrame. The user can pass multiple configuration files that will be added on top of the ``${RFM_INSTALL_PREFIX}/reframe/core/settings.py``. To ignore previous configuration files you need to pass ``-C :new_config.py`` - This option can also be set using the :envvar:`RFM_CONFIG_FILES` environment variable. + This option can also be set using the :envvar:`RFM_CONFIG_FILE` environment variable. ReFrame first loads the builtin config unconditionally and then starts to look for configs in the :envvar:`RFM_CONFIG_PATH` and starts chaining them. :envvar:`RFM_CONFIG_PATH` containe directories where a file named ``setting.py`` or ``setting.json`` is. @@ -1167,7 +1167,7 @@ Here is an alphabetical list of the environment variables recognized by ReFrame: .. versionadded:: 3.12.0 -.. envvar:: RFM_CONFIG_FILES +.. envvar:: RFM_CONFIG_FILE Set the configuration file for ReFrame. diff --git a/docs/tutorial_advanced.rst b/docs/tutorial_advanced.rst index 04e608000f..f23c7fd143 100644 --- a/docs/tutorial_advanced.rst +++ b/docs/tutorial_advanced.rst @@ -9,7 +9,7 @@ Finally, to avoid specifying the tutorial configuration file each time, make sur .. code:: bash - export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index b50c22cae9..b0bd22f1ed 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -266,7 +266,7 @@ Since we don't want to type it throughout the tutorial, we will now set it in th .. code-block:: console - export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py A Multithreaded "Hello, World!" @@ -650,7 +650,7 @@ We will only do so with the final versions of the tests from the previous sectio .. code-block:: console - export RFM_CONFIG_FILES=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py ./bin/reframe -c tutorials/basics/ -R -n 'HelloMultiLangTest|HelloThreadedExtended2Test|StreamWithRefTest' --performance-report -r .. literalinclude:: listings/alltests_daint.txt diff --git a/reframe/core/config.py b/reframe/core/config.py index bd6c2c38ec..328b16bfa9 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -455,7 +455,7 @@ def find_config_files(config_path=None, config_file=None): if config_file: for f in config_file: - # If the user sets RFM_CONFIG_FILES=:conf1:conf2 the list will + # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will # include one empty string in the beginning if f == '': res = [] diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index a5a542ab2a..4c2a290cce 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -502,16 +502,10 @@ def main(): # Miscellaneous options misc_options.add_argument( - '--config-file', action='append', metavar='FILE', - dest='config_file_alias', - help="Deprecated, alias of `--config-files'", - envvar='RFM_CONFIG_FILE :' - ) - misc_options.add_argument( - '-C', '--config-files', action='append', metavar='FILE', + '-C', '--config-file', action='append', metavar='FILE', dest='config_file', help='Set configuration file', - envvar='RFM_CONFIG_FILES :' + envvar='RFM_CONFIG_FILE :' ) misc_options.add_argument( '--detect-host-topology', action='store', nargs='?', const='-', @@ -712,15 +706,6 @@ def restrict_logging(): ) os.environ['RFM_GRAYLOG_ADDRESS'] = os.getenv('RFM_GRAYLOG_SERVER') - if options.config_file_alias: - printer.warning( - "`--config-file' option and RFM_CONFIG_FILE environment variable " - "are deprecated; please use `--config-files' and " - "RFM_CONFIG_FILES instead" - ) - if options.config_file is None: - options.config_file = options.config_file_alias - # Now configure ReFrame according to the user configuration file try: printer.debug('Loading user configuration') diff --git a/tools/gendoclistings.py b/tools/gendoclistings.py index 3b27321fd7..1ecf3af034 100755 --- a/tools/gendoclistings.py +++ b/tools/gendoclistings.py @@ -78,8 +78,8 @@ def replace_hostname(s): {'local', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -89,8 +89,8 @@ def replace_hostname(s): {'local', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=True @@ -100,8 +100,8 @@ def replace_hostname(s): {'remote', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -111,8 +111,8 @@ def replace_hostname(s): {'remote', 'tutorial-basics'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -122,8 +122,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -133,8 +133,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -144,8 +144,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -155,8 +155,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -166,8 +166,8 @@ def replace_hostname(s): {'remote', 'tutorial-deps'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -184,8 +184,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py') + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py') }, xfail=False ), @@ -194,8 +194,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -205,8 +205,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -216,8 +216,8 @@ def replace_hostname(s): {'remote', 'tutorial-fixtures'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -227,8 +227,8 @@ def replace_hostname(s): {'local', 'tutorial-advanced'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False @@ -238,8 +238,8 @@ def replace_hostname(s): {'local', 'tutorial-advanced'}, DEFAULT_FILTERS, env={ - 'RFM_CONFIG_FILES': os.path.join(os.getcwd(), - 'tutorials/config/settings.py'), + 'RFM_CONFIG_FILE': os.path.join(os.getcwd(), + 'tutorials/config/settings.py'), 'RFM_COLORIZE': 'n' }, xfail=False diff --git a/unittests/test_argparser.py b/unittests/test_argparser.py index 48906099d0..032490a04a 100644 --- a/unittests/test_argparser.py +++ b/unittests/test_argparser.py @@ -120,7 +120,7 @@ def extended_parser(): envvar='RFM_TIMESTAMP_DIRS', configvar='general/timestamp_dirs' ) foo_options.add_argument( - '-C', '--config-files', action='store', envvar='RFM_CONFIG_FILES' + '-C', '--config-file', action='store', envvar='RFM_CONFIG_FILE' ) foo_options.add_argument( '--check-path', action='append', envvar='RFM_CHECK_SEARCH_PATH :' @@ -153,7 +153,7 @@ def test_option_precedence(default_exec_ctx, extended_parser): assert options.recursive is None assert options.timestamp == '%FT%T' assert options.non_default_craype is True - assert options.config_files is None + assert options.config_file is None assert options.prefix is None assert options.stagedir == '/foo' assert options.module == ['a', 'b', 'c'] From afabf4632acfbf80a896ab45b7a408194c62dd8a Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Thu, 29 Sep 2022 14:54:04 +0200 Subject: [PATCH 21/42] Add versionchanged in --config-file --- docs/manpage.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/manpage.rst b/docs/manpage.rst index 1911a8080f..c290e8eb8e 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -788,6 +788,8 @@ Miscellaneous options If both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. Then accumulates the configs of the command line option, potentially replacing completely those from the :envvar:`RFM_CONFIG_PATH`. + .. versionchanged:: 4.0.0 + .. _--detect-host-topology: .. option:: --detect-host-topology[=FILE] From 6eabfc6d58fdd79095fa35ca180769c57f65e515 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Tue, 4 Oct 2022 17:01:15 +0200 Subject: [PATCH 22/42] Use RFM_CONFIG_PATH in tutorial --- docs/tutorial_advanced.rst | 2 +- docs/tutorial_basics.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial_advanced.rst b/docs/tutorial_advanced.rst index f23c7fd143..81471d7b12 100644 --- a/docs/tutorial_advanced.rst +++ b/docs/tutorial_advanced.rst @@ -9,7 +9,7 @@ Finally, to avoid specifying the tutorial configuration file each time, make sur .. code:: bash - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_PATH=$(pwd)/tutorials/config diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index b0bd22f1ed..d1544b68f6 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -266,7 +266,7 @@ Since we don't want to type it throughout the tutorial, we will now set it in th .. code-block:: console - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_PATH=$(pwd)/tutorials/config=$(pwd)/tutorials/config A Multithreaded "Hello, World!" From 936bb36f01ebc77b9067b58d57fe894e96a87883 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Thu, 6 Oct 2022 17:30:09 +0200 Subject: [PATCH 23/42] Remove file --- docs/man/man8/reframe.settings.8 | 2995 ------------------------------ 1 file changed, 2995 deletions(-) delete mode 100644 docs/man/man8/reframe.settings.8 diff --git a/docs/man/man8/reframe.settings.8 b/docs/man/man8/reframe.settings.8 deleted file mode 100644 index 79a46ffa17..0000000000 --- a/docs/man/man8/reframe.settings.8 +++ /dev/null @@ -1,2995 +0,0 @@ -.\" Man page generated from reStructuredText. -. -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. -.TH "REFRAME.SETTINGS" "8" "Sep 29, 2022" "4.0.0-dev.1" "ReFrame" -.SH NAME -reframe.settings \- ReFrame Configuration Manual -.sp -ReFrame’s behavior can be configured through its configuration file (see \fI\%Configuring ReFrame for Your Site\fP), environment variables and command\-line options. -An option can be specified via multiple paths (e.g., a configuration file parameter and an environment variable), in which case command\-line options precede environment variables, which in turn precede configuration file options. -This section provides a complete reference guide of the configuration options of ReFrame that can be set in its configuration file or specified using environment variables. -.sp -ReFrame’s configuration is in JSON syntax. -The full schema describing it can be found in \fI\%reframe/schemas/config.json\fP file. -Any configuration file given to ReFrame is validated against this schema. -.sp -The syntax we use in the following to describe the different configuration object attributes is a valid query string for the \fI\%jq(1)\fP command\-line processor. -.SH TOP-LEVEL CONFIGURATION -.sp -The top\-level configuration object is essentially the full configuration of ReFrame. -It consists of the following properties: -.INDENT 0.0 -.TP -.B \&.systems -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of \fI\%system configuration objects\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of \fI\%environment configuration objects\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of \fI\%logging configuration objects\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers -.INDENT 7.0 -.TP -.B Required -No -.UNINDENT -.sp -A list of \fI\%scheduler configuration objects\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.modes -.INDENT 7.0 -.TP -.B Required -No -.UNINDENT -.sp -A list of \fI\%execution mode configuration objects\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general -.INDENT 7.0 -.TP -.B Required -No -.UNINDENT -.sp -A list of \fI\%general configuration objects\fP\&. -.UNINDENT -.SH SYSTEM CONFIGURATION -.INDENT 0.0 -.TP -.B \&.systems[]\&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of this system. -Only alphanumeric characters, dashes (\fB\-\fP) and underscores (\fB_\fP) are allowed. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.descr -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB""\fP -.UNINDENT -.sp -The description of this system. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.hostnames -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of hostname regular expression patterns in Python \fI\%syntax\fP, which will be used by the framework in order to automatically select a system configuration. -For the auto\-selection process, see \fI\%here\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.max_local_jobs -The maximum number of forced local build or run jobs allowed. -.sp -Forced local jobs run within the execution context of ReFrame. -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB8\fP -.UNINDENT -.sp -New in version 3.10.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.modules_system -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"nomod"\fP -.UNINDENT -.sp -The modules system that should be used for loading environment modules on this system. -Available values are the following: -.INDENT 7.0 -.IP \(bu 2 -\fBtmod\fP: The classic Tcl implementation of the \fI\%environment modules\fP (version 3.2). -.IP \(bu 2 -\fBtmod31\fP: The classic Tcl implementation of the \fI\%environment modules\fP (version 3.1). -A separate backend is required for Tmod 3.1, because Python bindings are different from Tmod 3.2. -.IP \(bu 2 -\fBtmod32\fP: A synonym of \fBtmod\fP\&. -.IP \(bu 2 -\fBtmod4\fP: The \fI\%new environment modules\fP implementation (versions older than 4.1 are not supported). -.IP \(bu 2 -\fBlmod\fP: The \fI\%Lua implementation\fP of the environment modules. -.IP \(bu 2 -\fBspack\fP: \fI\%Spack\fP’s built\-in mechanism for managing modules. -.IP \(bu 2 -\fBnomod\fP: This is to denote that no modules system is used by this system. -.UNINDENT -.sp -New in version 3.4: The \fBspack\fP backend is added. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.modules -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to be loaded always when running on this system. -These modules modify the ReFrame environment. -This is useful in cases where a particular module is needed, for example, to submit jobs on a specific system. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.variables -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of environment variables to be set always when running on this system. -These variables modify the ReFrame environment. -Each environment variable is specified as a two\-element list containing the variable name and its value. -You may reference other environment variables when defining an environment variable here. -ReFrame will expand its value. -Variables are set after the environment modules are loaded. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.prefix -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"."\fP -.UNINDENT -.sp -Directory prefix for a ReFrame run on this system. -Any directories or files produced by ReFrame will use this prefix, if not specified otherwise. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.stagedir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"${RFM_PREFIX}/stage"\fP -.UNINDENT -.sp -Stage directory prefix for this system. -This is the directory prefix, where ReFrame will create the stage directories for each individual test case. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.outputdir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"${RFM_PREFIX}/output"\fP -.UNINDENT -.sp -Output directory prefix for this system. -This is the directory prefix, where ReFrame will save information about the successful tests. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.resourcesdir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"."\fP -.UNINDENT -.sp -Directory prefix where external test resources (e.g., large input files) are stored. -You may reference this prefix from within a regression test by accessing the \fI\%reframe.core.systems.System.resourcesdir\fP attribute of the current system. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of \fI\%system partition configuration objects\fP\&. -This list must have at least one element. -.UNINDENT -.SS System Partition Configuration -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of this partition. -Only alphanumeric characters, dashes (\fB\-\fP) and underscores (\fB_\fP) are allowed. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.descr -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB""\fP -.UNINDENT -.sp -The description of this partition. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.scheduler -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The job scheduler that will be used to launch jobs on this partition. -Supported schedulers are the following: -.INDENT 7.0 -.IP \(bu 2 -\fBlocal\fP: Jobs will be launched locally without using any job scheduler. -.IP \(bu 2 -\fBoar\fP: Jobs will be launched using the \fI\%OAR\fP scheduler. -.IP \(bu 2 -\fBpbs\fP: Jobs will be launched using the \fI\%PBS Pro\fP scheduler. -.IP \(bu 2 -\fBsge\fP: Jobs will be launched using the \fI\%Sun Grid Engine\fP scheduler. -.IP \(bu 2 -\fBslurm\fP: Jobs will be launched using the \fI\%Slurm\fP scheduler. -This backend requires job accounting to be enabled in the target system. -If not, you should consider using the \fBsqueue\fP backend below. -.IP \(bu 2 -\fBsqueue\fP: Jobs will be launched using the \fI\%Slurm\fP scheduler. -This backend does not rely on job accounting to retrieve job statuses, but ReFrame does its best to query the job state as reliably as possible. -.IP \(bu 2 -\fBtorque\fP: Jobs will be launched using the \fI\%Torque\fP scheduler. -.IP \(bu 2 -\fBlsf\fP: Jobs will be launched using the \fI\%LSF\fP scheduler. -.UNINDENT -.sp -New in version 3.7.2: Support for the SGE scheduler is added. - -.sp -New in version 3.8.2: Support for the OAR scheduler is added. - -.sp -New in version 3.11.0: Support for the LSF scheduler is added. - -.sp -\fBNOTE:\fP -.INDENT 7.0 -.INDENT 3.5 -The way that multiple node jobs are submitted using the SGE scheduler can be very site\-specific. -For this reason, the \fBsge\fP scheduler backend does not try to interpret any related arguments, e.g., \fBnum_tasks\fP, \fBnum_tasks_per_node\fP etc. -Users must specify how these resources are to be requested by setting the \fBresources\fP partition configuration parameter and then request them from inside a test using the \fI\%extra_resources\fP test attribute. -Here is an example configuration for a system partition named \fBfoo\fP that defines different ways for submitting MPI\-only, OpenMP\-only and MPI+OpenMP jobs: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -{ - \(aqname\(aq: \(aqfoo\(aq, - \(aqscheduler\(aq: \(aqsge\(aq, - \(aqresources\(aq: [ - { - \(aqname\(aq: \(aqsmp\(aq, - \(aqoptions\(aq: [\(aq\-pe smp {num_slots}\(aq] - }, - { - \(aqname\(aq: \(aqmpi\(aq, - \(aqoptions\(aq: [\(aq\-pe mpi {num_slots}\(aq] - }, - { - \(aqname\(aq: \(aqmpismp\(aq, - \(aqoptions\(aq: [\(aq\-pe mpismp {num_slots}\(aq] - } - ] -} -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Each test then can request the different type of slots as follows: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -self.extra_resouces = { - \(aqsmp\(aq: {\(aqnum_slots\(aq: self.num_cpus_per_task}, - \(aqmpi\(aq: {\(aqnum_slots\(aq: self.num_tasks}, - \(aqmpismp\(aq: {\(aqnum_slots\(aq: self.num_tasks*self.num_cpus_per_task} -} -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Notice that defining \fI\%extra_resources\fP does not make the test non\-portable to other systems that have different schedulers; -the \fBextra_resources\fP will be simply ignored in this case and the scheduler backend will interpret the different test fields in the appropriate way. -.UNINDENT -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.launcher -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The parallel job launcher that will be used in this partition to launch parallel programs. -Available values are the following: -.INDENT 7.0 -.IP \(bu 2 -\fBalps\fP: Parallel programs will be launched using the \fI\%Cray ALPS\fP \fBaprun\fP command. -.IP \(bu 2 -\fBibrun\fP: Parallel programs will be launched using the \fBibrun\fP command. -This is a custom parallel program launcher used at \fI\%TACC\fP\&. -.IP \(bu 2 -\fBlocal\fP: No parallel program launcher will be used. -The program will be launched locally. -.IP \(bu 2 -\fBlrun\fP: Parallel programs will be launched using \fI\%LC Launcher\fP’s \fBlrun\fP command. -.IP \(bu 2 -\fBlrun\-gpu\fP: Parallel programs will be launched using \fI\%LC Launcher\fP’s \fBlrun \-M "\-gpu"\fP command that enables the CUDA\-aware Spectrum MPI. -.IP \(bu 2 -\fBmpirun\fP: Parallel programs will be launched using the \fBmpirun\fP command. -.IP \(bu 2 -\fBmpiexec\fP: Parallel programs will be launched using the \fBmpiexec\fP command. -.IP \(bu 2 -\fBsrun\fP: Parallel programs will be launched using \fI\%Slurm\fP’s \fBsrun\fP command. -.IP \(bu 2 -\fBsrunalloc\fP: Parallel programs will be launched using \fI\%Slurm\fP’s \fBsrun\fP command, but job allocation options will also be emitted. -This can be useful when combined with the \fBlocal\fP job scheduler. -.IP \(bu 2 -\fBssh\fP: Parallel programs will be launched using SSH. -This launcher uses the partition’s \fI\%access\fP property in order to determine the remote host and any additional options to be passed to the SSH client. -The ssh command will be launched in “batch mode,” meaning that password\-less access to the remote host must be configured. -Here is an example configuration for the ssh launcher: -.INDENT 2.0 -.INDENT 3.5 -.sp -.nf -.ft C -{ - \(aqname\(aq: \(aqfoo\(aq - \(aqscheduler\(aq: \(aqlocal\(aq, - \(aqlauncher\(aq: \(aqssh\(aq - \(aqaccess\(aq: [\(aq\-l admin\(aq, \(aqremote.host\(aq], - \(aqenvirons\(aq: [\(aqbuiltin\(aq], -} -.ft P -.fi -.UNINDENT -.UNINDENT -.IP \(bu 2 -\fBupcrun\fP: Parallel programs will be launched using the \fI\%UPC\fP \fBupcrun\fP command. -.IP \(bu 2 -\fBupcxx\-run\fP: Parallel programs will be launched using the \fI\%UPC++\fP \fBupcxx\-run\fP command. -.UNINDENT -.sp -\fBTIP:\fP -.INDENT 7.0 -.INDENT 3.5 -New in version 4.0.0: ReFrame also allows you to register your own custom launchers simply by defining them in the configuration. -You can follow a small tutorial \fI\%here\fP\&. - -.UNINDENT -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.access -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of job scheduler options that will be passed to the generated job script for gaining access to that logical partition. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.environs -.INDENT 7.0 -.INDENT 3.5 -.INDENT 0.0 -.TP -.B required -No -.TP -.B default -\fB[]\fP -.UNINDENT -.UNINDENT -.UNINDENT -.sp -A list of environment names that ReFrame will use to run regression tests on this partition. -Each environment must be defined in the \fI\%environments\fP section of the configuration and the definition of the environment must be valid for this partition. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.container_platforms -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list for \fI\%container platform configuration objects\fP\&. -This will allow launching regression tests that use containers on this partition. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.modules -.INDENT 7.0 -.INDENT 3.5 -.INDENT 0.0 -.TP -.B required -No -.TP -.B default -\fB[]\fP -.UNINDENT -.UNINDENT -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to be loaded before running a regression test on this partition. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.time_limit -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBnull\fP -.UNINDENT -.sp -The time limit for the jobs submitted on this partition. -When the value is \fBnull\fP, no time limit is applied. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.variables -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of environment variables to be set before running a regression test on this partition. -Each environment variable is specified as a two\-element list containing the variable name and its value. -You may reference other environment variables when defining an environment variable here. -ReFrame will expand its value. -Variables are set after the environment modules are loaded. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.max_jobs -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB8\fP -.UNINDENT -.sp -The maximum number of concurrent regression tests that may be active (i.e., not completed) on this partition. -This option is relevant only when ReFrame executes with the \fI\%asynchronous execution policy\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.prepare_cmds -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -List of shell commands to be emitted before any environment loading commands are emitted. -.sp -New in version 3.5.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.resources -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of job scheduler \fI\%resource specification\fP objects. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.processor -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB{}\fP -.UNINDENT -.sp -Processor information for this partition stored in a \fI\%processor info object\fP\&. -If not set, ReFrame will try to auto\-detect this information (see \fI\%Auto\-detecting processor information\fP for more information). -.sp -New in version 3.5.0. - -.sp -Changed in version 3.7.0: ReFrame is now able to detect the processor information automatically. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.devices -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list with \fI\%device info objects\fP for this partition. -.sp -New in version 3.5.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.features -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -User defined features of the partition. -These are accessible through the \fI\%features\fP attribute of the \fI\%current_partition\fP and can also be selected through the extended syntax of \fI\%valid_systems\fP\&. -The values of this list must be alphanumeric strings starting with a non\-digit character and may also contain a \fB\-\fP\&. -.sp -New in version 3.11.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.extras -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB{}\fP -.UNINDENT -.sp -User defined attributes of the partition. -These are accessible through the \fI\%extras\fP attribute of the \fI\%current_partition\fP and can also be selected through the extended syntax of \fI\%valid_systems\fP\&. -The attributes of this object must be alphanumeric strings starting with a non\-digit character and their values can be of any type. -.sp -New in version 3.5.0. - -.UNINDENT -.SS Container Platform Configuration -.sp -ReFrame can launch containerized applications, but you need to configure properly a system partition in order to do that by defining a container platform configuration. -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.type -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The type of the container platform. -Available values are the following: -.INDENT 7.0 -.IP \(bu 2 -\fBDocker\fP: The \fI\%Docker\fP container runtime. -.IP \(bu 2 -\fBSarus\fP: The \fI\%Sarus\fP container runtime. -.IP \(bu 2 -\fBShifter\fP: The \fI\%Shifter\fP container runtime. -.IP \(bu 2 -\fBSingularity\fP: The \fI\%Singularity\fP container runtime. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.default -.INDENT 7.0 -.TP -.B Required -No -.UNINDENT -.sp -If set to \fBtrue\fP, this is the default container platform of this partition. -If not specified, the default container platform is assumed to be the first in the list of \fBcontainer_platforms\fP\&. -.sp -New in version 3.12.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.modules -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to be loaded when running containerized tests using this container platform. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.container_platforms[]\&.variables -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -List of environment variables to be set when running containerized tests using this container platform. -Each environment variable is specified as a two\-element list containing the variable name and its value. -You may reference other environment variables when defining an environment variable here. -ReFrame will expand its value. -Variables are set after the environment modules are loaded. -.UNINDENT -.SS Custom Job Scheduler Resources -.sp -ReFrame allows you to define custom scheduler resources for each partition that you can then transparently access through the \fBextra_resources\fP attribute of a regression test. -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.resources[]\&.name -.INDENT 7.0 -.INDENT 3.5 -.INDENT 0.0 -.TP -.B required -Yes -.UNINDENT -.UNINDENT -.UNINDENT -.sp -The name of this resources. -This name will be used to request this resource in a regression test’s \fBextra_resources\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.systems[]\&.partitions[]\&.resources[]\&.options -.INDENT 7.0 -.INDENT 3.5 -.INDENT 0.0 -.TP -.B required -No -.TP -.B default -\fB[]\fP -.UNINDENT -.sp -A list of options to be passed to this partition’s job scheduler. -The option strings can contain placeholders of the form \fB{placeholder_name}\fP\&. -These placeholders may be replaced with concrete values by a regression test through the \fBextra_resources\fP attribute. -.sp -For example, one could define a \fBgpu\fP resource for a multi\-GPU system that uses Slurm as follows: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -\(aqresources\(aq: [ - { - \(aqname\(aq: \(aqgpu\(aq, - \(aqoptions\(aq: [\(aq\-\-gres=gpu:{num_gpus_per_node}\(aq] - } -] -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -A regression test then may request this resource as follows: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -self.extra_resources = {\(aqgpu\(aq: {\(aqnum_gpus_per_node\(aq: \(aq8\(aq}} -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -And the generated job script will have the following line in its preamble: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -#SBATCH \-\-gres=gpu:8 -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -A resource specification may also start with \fB#PREFIX\fP, in which case \fB#PREFIX\fP will replace the standard job script prefix of the backend scheduler of this partition. -This is useful in cases of job schedulers like Slurm, that allow alternative prefixes for certain features. -An example is the \fI\%DataWarp\fP functionality of Slurm which is supported by the \fB#DW\fP prefix. -One could then define DataWarp related resources as follows: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -\(aqresources\(aq: [ - { - \(aqname\(aq: \(aqdatawarp\(aq, - \(aqoptions\(aq: [ - \(aq#DW jobdw capacity={capacity} access_mode={mode} type=scratch\(aq, - \(aq#DW stage_out source={out_src} destination={out_dst} type={stage_filetype}\(aq - ] - } -] -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -A regression test that wants to make use of that resource, it can set its \fBextra_resources\fP as follows: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -self.extra_resources = { - \(aqdatawarp\(aq: { - \(aqcapacity\(aq: \(aq100GB\(aq, - \(aqmode\(aq: \(aqstriped\(aq, - \(aqout_src\(aq: \(aq$DW_JOB_STRIPED/name\(aq, - \(aqout_dst\(aq: \(aq/my/file\(aq, - \(aqstage_filetype\(aq: \(aqfile\(aq - } -} -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 7.0 -.INDENT 3.5 -For the \fBpbs\fP and \fBtorque\fP backends, options accepted in the \fI\%access\fP and \fI\%resources\fP attributes may either refer to actual \fBqsub\fP options or may be just resources specifications to be passed to the \fB\-l\fP option. -The backend assumes a \fBqsub\fP option, if the options passed in these attributes start with a \fB\-\fP\&. -.UNINDENT -.UNINDENT -.UNINDENT -.SH ENVIRONMENT CONFIGURATION -.sp -Environments defined in this section will be used for running regression tests. -They are associated with \fI\%system partitions\fP\&. -.INDENT 0.0 -.TP -.B \&.environments[]\&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of this environment. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.modules -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to be loaded when this environment is loaded. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.variables -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of environment variables to be set when loading this environment. -Each environment variable is specified as a two\-element list containing the variable name and its value. -You may reference other environment variables when defining an environment variable here. -ReFrame will expand its value. -Variables are set after the environment modules are loaded. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.features -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -User defined features of the environment. -These are accessible through the \fI\%features\fP attribute of the \fI\%current_environ\fP and can also be selected through the extended syntax of \fI\%valid_prog_environs\fP\&. -The values of this list must be alphanumeric strings starting with a non\-digit character and may also contain a \fB\-\fP\&. -.sp -New in version 3.11.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.extras -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB{}\fP -.UNINDENT -.sp -User defined attributes of the environment. -These are accessible through the \fI\%extras\fP attribute of the \fI\%current_environ\fP and can also be selected through the extended syntax of \fI\%valid_prog_environs\fP\&. -The attributes of this object must be alphanumeric strings starting with a non\-digit character and their values can be of any type. -.sp -New in version 3.9.1. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.cc -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"cc"\fP -.UNINDENT -.sp -The C compiler to be used with this environment. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.cxx -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"CC"\fP -.UNINDENT -.sp -The C++ compiler to be used with this environment. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.ftn -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"ftn"\fP -.UNINDENT -.sp -The Fortran compiler to be used with this environment. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.cppflags -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of C preprocessor flags to be used with this environment by default. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.cflags -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of C flags to be used with this environment by default. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.cxxflags -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of C++ flags to be used with this environment by default. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.fflags -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of Fortran flags to be used with this environment by default. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.ldflags -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of linker flags to be used with this environment by default. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.environments[]\&.target_systems -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["*"]\fP -.UNINDENT -.sp -A list of systems or system/partitions combinations that this environment definition is valid for. -A \fB*\fP entry denotes any system. -In case of multiple definitions of an environment, the most specific to the current system partition will be used. -For example, if the current system/partition combination is \fBdaint:mc\fP, the second definition of the \fBPrgEnv\-gnu\fP environment will be used: -.INDENT 7.0 -.INDENT 3.5 -.sp -.nf -.ft C -\(aqenvironments\(aq: [ - { - \(aqname\(aq: \(aqPrgEnv\-gnu\(aq, - \(aqmodules\(aq: [\(aqPrgEnv\-gnu\(aq] - }, - { - \(aqname\(aq: \(aqPrgEnv\-gnu\(aq, - \(aqmodules\(aq: [\(aqPrgEnv\-gnu\(aq, \(aqopenmpi\(aq], - \(aqcc\(aq: \(aqmpicc\(aq, - \(aqcxx\(aq: \(aqmpicxx\(aq, - \(aqftn\(aq: \(aqmpif90\(aq, - \(aqtarget_systems\(aq: [\(aqdaint:mc\(aq] - } -] -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -However, if the current system was \fBdaint:gpu\fP, the first definition would be selected, despite the fact that the second definition is relevant for another partition of the same system. -To better understand this, ReFrame resolves definitions in a hierarchical way. -It first looks for definitions for the current partition, then for the containing system and, finally, for global definitions (the \fB*\fP pseudo\-system). -.UNINDENT -.SH LOGGING CONFIGURATION -.sp -Logging in ReFrame is handled by logger objects which further delegate message to \fIlogging handlers\fP which are eventually responsible for emitting or sending the log records to their destinations. -You may define different logger objects per system but \fInot\fP per partition. -.INDENT 0.0 -.TP -.B \&.logging[]\&.level -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"undefined"\fP -.UNINDENT -.sp -The level associated with this logger object. -There are the following levels in decreasing severity order: -.INDENT 7.0 -.IP \(bu 2 -\fBcritical\fP: Catastrophic errors; the framework cannot proceed with its execution. -.IP \(bu 2 -\fBerror\fP: Normal errors; the framework may or may not proceed with its execution. -.IP \(bu 2 -\fBwarning\fP: Warning messages. -.IP \(bu 2 -\fBinfo\fP: Informational messages. -.IP \(bu 2 -\fBverbose\fP: More informational messages. -.IP \(bu 2 -\fBdebug\fP: Debug messages. -.IP \(bu 2 -\fBdebug2\fP: Further debug messages. -.IP \(bu 2 -\fBundefined\fP: This is the lowest level; do not filter any message. -.UNINDENT -.sp -If a message is logged by the framework, its severity level will be checked by the logger and if it is higher from the logger’s level, it will be passed down to its handlers. -.sp -New in version 3.3: The \fBdebug2\fP and \fBundefined\fP levels are added. - -.sp -Changed in version 3.3: The default level is now \fBundefined\fP\&. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of logging handlers responsible for handling normal framework output. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers_perflog -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -A list of logging handlers responsible for handling performance data from tests. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.target_systems -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["*"]\fP -.UNINDENT -.sp -A list of systems or system/partitions combinations that this logging configuration is valid for. -For a detailed description of this property, you may refer \fI\%here\fP\&. -.UNINDENT -.SS Common logging handler properties -.sp -All logging handlers share the following set of common attributes: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.type -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers_perflog[]\&.type -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The type of handler. -There are the following types available: -.INDENT 7.0 -.IP \(bu 2 -\fBfile\fP: This handler sends log records to file. -See \fI\%here\fP for more details. -.IP \(bu 2 -\fBfilelog\fP: This handler sends performance log records to files. -See \fI\%here\fP for more details. -.IP \(bu 2 -\fBgraylog\fP: This handler sends performance log records to Graylog. -See \fI\%here\fP for more details. -.IP \(bu 2 -\fBstream\fP: This handler sends log records to a file stream. -See \fI\%here\fP for more details. -.IP \(bu 2 -\fBsyslog\fP: This handler sends log records to a Syslog facility. -See \fI\%here\fP for more details. -.IP \(bu 2 -\fBhttpjson\fP: This handler sends log records in JSON format using HTTP post requests. -See \fI\%here\fP for more details. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.level -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers_perflog[]\&.level -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"info"\fP -.UNINDENT -.sp -The \fI\%log level\fP associated with this handler. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.format -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers_perflog[]\&.format -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"%(message)s"\fP -.UNINDENT -.sp -Log record format string. -ReFrame accepts all log record attributes from Python’s \fI\%logging\fP mechanism and adds the following: -.TS -center; -|l|l|l|. -_ -T{ -Log record attribute -T} T{ -Description -T} T{ -T} -_ -T{ -\fB%(check_build_locally)s\fP -T} T{ -The value of the \fI\%build_locally\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_build_time_limit)s\fP -T} T{ -The value of the \fI\%build_time_limit\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_descr)s\fP -T} T{ -The value of the \fI\%descr\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_display_name)s\fP -T} T{ -The value of the \fI\%display_name\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_environ)s\fP -T} T{ -The name of the test’s \fI\%current_environ\fP\&. -T} T{ -T} -_ -T{ -\fB%(check_exclusive_access)s\fP -T} T{ -The value of the \fI\%exclusive_access\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_executable)s\fP -T} T{ -The value of the \fI\%executable\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_executable_opts)s\fP -T} T{ -The value of the \fI\%executable_opts\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_extra_resources)s\fP -T} T{ -The value of the \fI\%extra_resources\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_hashcode)s\fP -T} T{ -The unique hash associated with this test. -T} T{ -T} -_ -T{ -\fB%(check_info)s\fP -T} T{ -Various information about this test; essentially the return value of the test’s \fI\%info()\fP function. -T} T{ -T} -_ -T{ -\fB%(check_job_completion_time)s\fP -T} T{ -Same as the \fB(check_job_completion_time_unix)s\fP but formatted according to \fBdatefmt\fP\&. -T} T{ -T} -_ -T{ -\fB%(check_job_completion_time_unix)s\fP -T} T{ -The completion time of the associated run job (see \fI\%reframe.core.schedulers.Job.completion_time\fP). -T} T{ -T} -_ -T{ -\fB%(check_job_exitcode)s\fP -T} T{ -The exit code of the associated run job. -T} T{ -T} -_ -T{ -\fB%(check_job_nodelist)s\fP -T} T{ -The list of nodes that the associated run job has run on. -T} T{ -T} -_ -T{ -\fB%(check_jobid)s\fP -T} T{ -The ID of the associated run job. -T} T{ -T} -_ -T{ -\fB%(check_keep_files)s\fP -T} T{ -The value of the \fI\%keep_files\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_local)s\fP -T} T{ -The value of the \fI\%local\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_maintainers)s\fP -T} T{ -The value of the \fI\%maintainers\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_max_pending_time)s\fP -T} T{ -The value of the \fI\%max_pending_time\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_modules)s\fP -T} T{ -The value of the \fI\%modules\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_name)s\fP -T} T{ -The value of the \fI\%name\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_cpus_per_task)s\fP -T} T{ -The value of the \fI\%num_cpus_per_task\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_gpus_per_node)s\fP -T} T{ -The value of the \fI\%num_gpus_per_node\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_tasks)s\fP -T} T{ -The value of the \fI\%num_tasks\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_tasks_per_core)s\fP -T} T{ -The value of the \fI\%num_tasks_per_core\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_tasks_per_node)s\fP -T} T{ -The value of the \fI\%num_tasks_per_node\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_num_tasks_per_socket)s\fP -T} T{ -The value of the \fI\%num_tasks_per_socket\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_outputdir)s\fP -T} T{ -The value of the \fI\%outputdir\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_partition)s\fP -T} T{ -The name of the test’s \fI\%current_partition\fP\&. -T} T{ -T} -_ -T{ -\fB%(check_perf_lower_thres)s\fP -T} T{ -The lower threshold of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perf_ref)s\fP -T} T{ -The reference value of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perf_unit)s\fP -T} T{ -The measurement unit of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perf_upper)s\fP -T} T{ -The upper thresholds of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perf_value)s\fP -T} T{ -The actual value of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perf_var)s\fP -T} T{ -The name of the logged performance variable. -T} T{ -T} -_ -T{ -\fB%(check_perfvalues)s\fP -T} T{ -All the performance variables of the test combined along with their values -T} T{ -references and thresholds. -T} -_ -T{ -\fB%(check_postbuild_cmds)s\fP -T} T{ -The value of the \fI\%postbuild_cmds\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_postrun_cmds)s\fP -T} T{ -The value of the \fI\%postrun_cmds\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_prebuild_cmds)s\fP -T} T{ -The value of the \fI\%prebuild_cmds\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_prefix)s\fP -T} T{ -The value of the \fI\%prefix\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_prerun_cmds)s\fP -T} T{ -The value of the \fI\%prerun_cmds\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_readonly_files)s\fP -T} T{ -The value of the \fI\%readonly_files\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_short_name)s\fP -T} T{ -The value of the \fI\%short_name\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_sourcepath)s\fP -T} T{ -The value of the \fI\%sourcepath\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_sourcesdir)s\fP -T} T{ -The value of the \fI\%sourcesdir\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_stagedir)s\fP -T} T{ -The value of the \fI\%stagedir\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_strict_check)s\fP -T} T{ -The value of the \fI\%strict_check\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_system)s\fP -T} T{ -The name of the test’s \fI\%current_system\fP\&. -T} T{ -T} -_ -T{ -\fB%(check_tags)s\fP -T} T{ -The value of the \fI\%tags\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_time_limit)s\fP -T} T{ -The value of the \fI\%time_limit\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_unique_name)s\fP -T} T{ -The value of the \fI\%unique_name\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_use_multithreading)s\fP -T} T{ -The value of the \fI\%use_multithreading\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_valid_prog_environs)s\fP -T} T{ -The value of the \fI\%valid_prog_environs\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_valid_systems)s\fP -T} T{ -The value of the \fI\%valid_systems\fP attribute. -T} T{ -T} -_ -T{ -\fB%(check_variables)s\fP -T} T{ -The value of the \fI\%variables\fP attribute. -T} T{ -T} -_ -T{ -\fB%(osuser)s\fP -T} T{ -The name of the OS user running ReFrame. -T} T{ -T} -_ -T{ -\fB%(osgroup)s\fP -T} T{ -The name of the OS group running ReFrame. -T} T{ -T} -_ -T{ -\fB%(version)s\fP -T} T{ -The ReFrame version. -T} T{ -T} -_ -.TE -.sp -ReFrame allows you to log any test variable, parameter or property if they are marked as “loggable”. -The log record attribute will have the form \fB%(check_NAME)s\fP where \fBNAME\fP is the variable name, the parameter name or the property name that is marked as loggable. -.UNINDENT -.sp -New in version 3.3: Allow arbitrary test attributes to be logged. - -.sp -New in version 3.4.2: Allow arbitrary job attributes to be logged. - -.sp -Changed in version 3.11.0: Limit the number of attributes that can be logged. User attributes or properties must be explicitly marked as “loggable” in order to be selectable for logging. - -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.datefmt -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].datefmt -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"%FT%T"\fP -.UNINDENT -.sp -Time format to be used for printing timestamps fields. -There are two timestamp fields available: \fB%(asctime)s\fP and \fB%(check_job_completion_time)s\fP\&. -In addition to the format directives supported by the standard library’s \fI\%time.strftime()\fP function, ReFrame allows you to use the \fB%:z\fP directive – a GNU \fBdate\fP extension – that will print the time zone difference in a RFC3339 compliant way, i.e., \fB+/\-HH:MM\fP instead of \fB+/\-HHMM\fP\&. -.UNINDENT -.SS The \fBfile\fP log handler -.sp -This log handler handles output to normal files. -The additional properties for the \fBfile\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.name -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].name -.INDENT 7.0 -.TP -.B Required -No -.UNINDENT -.sp -The name of the file where this handler will write log records. -If not specified, ReFrame will create a log file prefixed with \fBrfm\-\fP in the system’s temporary directory. -.sp -Changed in version 3.3: The \fBname\fP parameter is no more required and the default log file resides in the system’s temporary directory. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.append -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].append -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Controls whether this handler should append to its file or not. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.timestamp -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].timestamp -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Append a timestamp to this handler’s log file. -This property may also accept a date format as described in the \fI\%datefmt\fP property. -If the handler’s \fI\%name\fP property is set to \fBfilename.log\fP and this property is set to \fBtrue\fP or to a specific timestamp format, the resulting log file will be \fBfilename_.log\fP\&. -.UNINDENT -.SS The \fBfilelog\fP log handler -.sp -This handler is meant primarily for performance logging and logs the performance of a regression test in one or more files. -The additional properties for the \fBfilelog\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.basedir -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].basedir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"./perflogs"\fP -.UNINDENT -.sp -The base directory of performance data log files. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.prefix -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].prefix -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -This is a directory prefix (usually dynamic), appended to the \fI\%basedir\fP, where the performance logs of a test will be stored. -This attribute accepts any of the check\-specific \fI\%formatting placeholders\fP\&. -This allows to create dynamic paths based on the current system, partition and/or programming environment a test executes with. -For example, a value of \fB%(check_system)s/%(check_partition)s\fP would generate the following structure of performance log files: -.INDENT 7.0 -.INDENT 3.5 -.sp -.nf -.ft C -{basedir}/ - system1/ - partition1/ - test_short_name.log - partition2/ - test_short_name.log - ... - system2/ - ... -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers[].append -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].append -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBtrue\fP -.UNINDENT -.sp -Open each log file in append mode. -.UNINDENT -.SS The \fBgraylog\fP log handler -.sp -This handler sends log records to a \fI\%Graylog\fP server. -The additional properties for the \fBgraylog\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.address -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].address -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The address of the Graylog server defined as \fBhost:port\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.extras -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].extras -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB{}\fP -.UNINDENT -.sp -A set of optional key/value pairs to be passed with each log record to the server. -These may depend on the server configuration. -.UNINDENT -.sp -This log handler uses internally \fI\%pygelf\fP\&. -If \fBpygelf\fP is not available, this log handler will be ignored. -\fI\%GELF\fP is a format specification for log messages that are sent over the network. -The \fBgraylog\fP handler sends log messages in JSON format using an HTTP POST request to the specified address. -More details on this log format may be found \fI\%here\fP\&. -An example configuration of this handler for performance logging is shown here: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -{ - \(aqtype\(aq: \(aqgraylog\(aq, - \(aqaddress\(aq: \(aqgraylog\-server:12345\(aq, - \(aqlevel\(aq: \(aqinfo\(aq, - \(aqformat\(aq: \(aq%(message)s\(aq, - \(aqextras\(aq: { - \(aqfacility\(aq: \(aqreframe\(aq, - \(aqdata\-version\(aq: \(aq1.0\(aq - } -} -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Although the \fBformat\fP is defined for this handler, it is not only the log message that will be transmitted the Graylog server. -This handler transmits the whole log record, meaning that all the information will be available and indexable at the remote end. -.SS The \fBstream\fP log handler -.sp -This handler sends log records to a file stream. -The additional properties for the \fBstream\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[].handlers[].name -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].name -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"stdout"\fP -.UNINDENT -.sp -The name of the file stream to send records to. -There are only two available streams: -.INDENT 7.0 -.IP \(bu 2 -\fBstdout\fP: the standard output. -.IP \(bu 2 -\fBstderr\fP: the standard error. -.UNINDENT -.UNINDENT -.SS The \fBsyslog\fP log handler -.sp -This handler sends log records to UNIX syslog. -The additional properties for the \fBsyslog\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.socktype -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].socktype -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"udp"\fP -.UNINDENT -.sp -The socket type where this handler will send log records to. -There are two socket types: -.INDENT 7.0 -.IP \(bu 2 -\fBudp\fP: A UDP datagram socket. -.IP \(bu 2 -\fBtcp\fP: A TCP stream socket. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.facility -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].facility -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"user"\fP -.UNINDENT -.sp -The Syslog facility where this handler will send log records to. -The list of supported facilities can be found \fI\%here\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers[].address -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].address -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The socket address where this handler will connect to. -This can either be of the form \fB:\fP or simply a path that refers to a Unix domain socket. -.UNINDENT -.SS The \fBhttpjson\fP log handler -.sp -This handler sends log records in JSON format to a server using HTTP POST requests. -The additional properties for the \fBhttpjson\fP handler are the following: -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.url -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].url -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The URL to be used in the HTTP(S) request server. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[]\&.handlers[]\&.extras -.UNINDENT -.INDENT 0.0 -.TP -.B \&.logging[].handlers_perflog[].extras -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB{}\fP -.UNINDENT -.sp -A set of optional key/value pairs to be passed with each log record to the server. -These may depend on the server configuration. -.UNINDENT -.sp -The \fBhttpjson\fP handler sends log messages in JSON format using an HTTP POST request to the specified URL. -.sp -An example configuration of this handler for performance logging is shown here: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -{ - \(aqtype\(aq: \(aqhttpjson\(aq, - \(aqurl\(aq: \(aqhttp://httpjson\-server:12345/rfm\(aq, - \(aqlevel\(aq: \(aqinfo\(aq, - \(aqextras\(aq: { - \(aqfacility\(aq: \(aqreframe\(aq, - \(aqdata\-version\(aq: \(aq1.0\(aq - } -} -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -This handler transmits the whole log record, meaning that all the information will be available and indexable at the remote end. -.SH SCHEDULER CONFIGURATION -.sp -A scheduler configuration object contains configuration options specific to the scheduler’s behavior. -.SS Common scheduler options -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of the scheduler that these options refer to. -It can be any of the supported job scheduler \fI\%backends\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.job_submit_timeout -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -60 -.UNINDENT -.sp -Timeout in seconds for the job submission command. -If timeout is reached, the regression test issuing that command will be marked as a failure. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.target_systems -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["*"]\fP -.UNINDENT -.sp -A list of systems or system/partitions combinations that this scheduler configuration is valid for. -For a detailed description of this property, you may refer \fI\%here\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.use_nodes_option -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Always emit the \fB\-\-nodes\fP Slurm option in the preamble of the job script. -This option is relevant to Slurm backends only. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.ignore_reqnodenotavail -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -This option is relevant to the Slurm backends only. -.sp -If a job associated to a test is in pending state with the Slurm reason \fBReqNodeNotAvail\fP and a list of unavailable nodes is also specified, ReFrame will check the status of the nodes and, if all of them are indeed down, it will cancel the job. -Sometimes, however, when Slurm’s backfill algorithm takes too long to compute, Slurm will set the pending reason to \fBReqNodeNotAvail\fP and mark all system nodes as unavailable, causing ReFrame to kill the job. -In such cases, you may set this parameter to \fBtrue\fP to avoid this. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.schedulers[]\&.resubmit_on_errors -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -This option is relevant to the Slurm backends only. -.sp -If any of the listed errors occur, ReFrame will try to resubmit the job after some seconds. -As an example, you could have ReFrame trying to resubmit a job in case that the maximum submission limit per user is reached by setting this field to \fB["QOSMaxSubmitJobPerUserLimit"]\fP\&. -You can ignore multiple errors at the same time if you add more error strings in the list. -.sp -New in version 3.4.1. - -.sp -\fBWARNING:\fP -.INDENT 7.0 -.INDENT 3.5 -Job submission is a synchronous operation in ReFrame. -If this option is set, ReFrame’s execution will block until the error conditions specified in this list are resolved. -No other test would be able to proceed. -.UNINDENT -.UNINDENT -.UNINDENT -.SH EXECUTION MODE CONFIGURATION -.sp -ReFrame allows you to define groups of command line options that are collectively called \fIexecution modes\fP\&. -An execution mode can then be selected from the command line with the \fB\-mode\fP option. -The options of an execution mode will be passed to ReFrame as if they were specified in the command line. -.INDENT 0.0 -.TP -.B \&.modes[]\&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of this execution mode. -This can be used with the \fI\%\-\-mode\fP command line option to invoke this mode. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.modes[]\&.options -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -The command\-line options associated with this execution mode. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.modes[]\&.target_systems -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["*"]\fP -.UNINDENT -.sp -A list of systems \fIonly\fP that this execution mode is valid for. -For a detailed description of this property, you may refer \fI\%here\fP\&. -.UNINDENT -.SH GENERAL CONFIGURATION -.INDENT 0.0 -.TP -.B \&.general[]\&.check_search_path -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["${RFM_INSTALL_PREFIX}/checks/"]\fP -.UNINDENT -.sp -A list of paths (files or directories) where ReFrame will look for regression test files. -If the search path is set through the environment variable, it should be a colon separated list. -If specified from command line, the search path is constructed by specifying multiple times the command line option. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.check_search_recursive -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Search directories in the \fI\%search path\fP recursively. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.clean_stagedir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBtrue\fP -.UNINDENT -.sp -Clean stage directory of tests before populating it. -.sp -New in version 3.1. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.colorize -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBtrue\fP -.UNINDENT -.sp -Use colors in output. -The command\-line option sets the configuration option to \fBfalse\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.compress_report -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Compress the generated run report file. -See the documentation of the \fI\%\-\-compress\-report\fP option for more information. -.sp -New in version 3.12.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.git_timeout -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -5 -.UNINDENT -.sp -Timeout value in seconds used when checking if a git repository exists. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.dump_pipeline_progress -Dump pipeline progress for the asynchronous execution policy in \fBpipeline\-progress.json\fP\&. -This option is meant for debug purposes only. -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBFalse\fP -.UNINDENT -.sp -New in version 3.10.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.pipeline_timeout -Timeout in seconds for advancing the pipeline in the asynchronous execution policy. -.sp -ReFrame’s asynchronous execution policy will try to advance as many tests as possible in their pipeline, but some tests may take too long to proceed (e.g., due to copying of large files) blocking the advancement of previously started tests. -If this timeout value is exceeded and at least one test has progressed, ReFrame will stop processing new tests and it will try to further advance tests that have already started. -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB10\fP -.UNINDENT -.sp -New in version 3.10.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.remote_detect -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Try to auto\-detect processor information of remote partitions as well. -This may slow down the initialization of the framework, since it involves submitting auto\-detection jobs to the remote partitions. -For more information on how ReFrame auto\-detects processor information, you may refer to \fI\%Auto\-detecting processor information\fP\&. -.sp -New in version 3.7.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.remote_workdir -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"."\fP -.UNINDENT -.sp -The temporary directory prefix that will be used to create a fresh ReFrame clone, in order to auto\-detect the processor information of a remote partition. -.sp -New in version 3.7.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.ignore_check_conflicts -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Ignore test name conflicts when loading tests. -.sp -Deprecated since version 3.8.0: This option will be removed in a future version. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.trap_job_errors -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Trap command errors in the generated job scripts and let them exit immediately. -.sp -New in version 3.2. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.keep_stage_files -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Keep stage files of tests even if they succeed. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.module_map_file -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB""\fP -.UNINDENT -.sp -File containing module mappings. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.module_mappings -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of module mappings. -If specified through the environment variable, the mappings must be separated by commas. -If specified from command line, multiple module mappings are defined by passing the command line option multiple times. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.non_default_craype -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Test a non\-default Cray Programming Environment. -This will emit some special instructions in the generated build and job scripts. -See also \fI\%\-\-non\-default\-craype\fP for more details. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.purge_environment -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Purge any loaded environment modules before running any tests. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.report_file -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB"${HOME}/.reframe/reports/run\-report\-{sessionid}.json"\fP -.UNINDENT -.sp -The file where ReFrame will store its report. -.sp -New in version 3.1. - -.sp -Changed in version 3.2: Default value has changed to avoid generating a report file per session. - -.sp -Changed in version 4.0.0: Default value was reverted back to generate a new file per run. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.report_junit -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBnull\fP -.UNINDENT -.sp -The file where ReFrame will store its report in JUnit format. -The report adheres to the XSD schema \fI\%here\fP\&. -.sp -New in version 3.6.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.resolve_module_conflicts -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBtrue\fP -.UNINDENT -.sp -ReFrame by default resolves any module conflicts and emits the right sequence of \fBmodule unload\fP and \fBmodule load\fP commands, in order to load the requested modules. -This option disables this behavior if set to \fBfalse\fP\&. -.sp -You should avoid using this option for modules system that cannot handle module conflicts automatically, such as early Tmod verions. -.sp -Disabling the automatic module conflict resolution, however, can be useful when modules in a remote system partition are not present on the host where ReFrame runs. -In order to resolve any module conflicts and generate the right load sequence of modules, ReFrame loads temporarily the requested modules and tracks any conflicts along the way. -By disabling this option, ReFrame will simply emit the requested \fBmodule load\fP commands without attempting to load any module. -.sp -New in version 3.6.0. - -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.save_log_files -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Save any log files generated by ReFrame to its output directory -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.target_systems -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB["*"]\fP -.UNINDENT -.sp -A list of systems or system/partitions combinations that these general options are valid for. -For a detailed description of this property, you may refer \fI\%here\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.timestamp_dirs -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB""\fP -.UNINDENT -.sp -Append a timestamp to ReFrame directory prefixes. -Valid formats are those accepted by the \fI\%time.strftime()\fP function. -If specified from the command line without any argument, \fB"%FT%T"\fP will be used as a time format. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.unload_modules -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to unload before executing any test. -If specified using an the environment variable, a space separated list of modules is expected. -If specified from the command line, multiple modules can be passed by passing the command line option multiple times. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.use_login_shell -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -Use a login shell for the generated job scripts. -This option will cause ReFrame to emit \fB\-l\fP in the shebang of shell scripts. -This option, if set to \fBtrue\fP, may cause ReFrame to fail, if the shell changes permanently to a different directory during its start up. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.user_modules -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fB[]\fP -.UNINDENT -.sp -A list of \fI\%environment module objects\fP to be loaded before executing any test. -If specified using an the environment variable, a space separated list of modules is expected. -If specified from the command line, multiple modules can be passed by passing the command line option multiple times. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.general[]\&.verbose -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -0 -.UNINDENT -.sp -Set the verbosity level of the output. -The higher the number, the more verbose the output will be. -If set to a negative number, this will decrease the verbosity level. -.UNINDENT -.SH MODULE OBJECTS -.sp -New in version 3.3. - -.sp -A \fImodule object\fP in ReFrame’s configuration represents an environment module. -It can either be a simple string or a JSON object with the following attributes: -.INDENT 0.0 -.TP -.B \&.name -.INDENT 7.0 -.TP -.B Required -Yes -.UNINDENT -.sp -The name of the module. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.collection -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBfalse\fP -.UNINDENT -.sp -A boolean value indicating whether this module refers to a module collection. -Module collections are treated differently from simple modules when loading. -.UNINDENT -.INDENT 0.0 -.TP -.B path -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBnull\fP -.UNINDENT -.sp -If the module is not present in the default \fBMODULEPATH\fP, the module’s location can be specified here. -ReFrame will make sure to set and restore the \fBMODULEPATH\fP accordingly for loading the module. -.sp -New in version 3.5.0. - -.UNINDENT -.sp -\fBSEE ALSO:\fP -.INDENT 0.0 -.INDENT 3.5 -Module collections with \fI\%Environment Modules\fP and \fI\%Lmod\fP\&. -.UNINDENT -.UNINDENT -.SH PROCESSOR INFO -.sp -New in version 3.5.0. - -.sp -A \fIprocessor info object\fP in ReFrame’s configuration is used to hold information about the processor of a system partition and is made available to the tests through the \fI\%processor\fP attribute of the \fI\%current_partition\fP\&. -.INDENT 0.0 -.TP -.B \&.arch -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -The microarchitecture of the processor. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.num_cpus -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Number of logical CPUs. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.num_cpus_per_core -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Number of logical CPUs per core. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.num_cpus_per_socket -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Number of logical CPUs per socket. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.num_sockets -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Number of sockets. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.topology -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Processor topology. -An example follows: -.INDENT 7.0 -.INDENT 3.5 -.sp -.nf -.ft C -\(aqtopology\(aq: { - \(aqnuma_nodes\(aq: [\(aq0x000000ff\(aq], - \(aqsockets\(aq: [\(aq0x000000ff\(aq], - \(aqcores\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, - \(aq0x00000030\(aq, \(aq0x000000c0\(aq], - \(aqcaches\(aq: [ - { - \(aqtype\(aq: \(aqL3\(aq, - \(aqsize\(aq: 6291456, - \(aqlinesize\(aq: 64, - \(aqassociativity\(aq: 0, - \(aqnum_cpus\(aq: 8, - \(aqcpusets\(aq: [\(aq0x000000ff\(aq] - }, - { - \(aqtype\(aq: \(aqL2\(aq, - \(aqsize\(aq: 262144, - \(aqlinesize\(aq: 64, - \(aqassociativity\(aq: 4, - \(aqnum_cpus\(aq: 2, - \(aqcpusets\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, - \(aq0x00000030\(aq, \(aq0x000000c0\(aq] - }, - { - \(aqtype\(aq: \(aqL1\(aq, - \(aqsize\(aq: 32768, - \(aqlinesize\(aq: 64, - \(aqassociativity\(aq: 0, - \(aqnum_cpus\(aq: 2, - \(aqcpusets\(aq: [\(aq0x00000003\(aq, \(aq0x0000000c\(aq, - \(aq0x00000030\(aq, \(aq0x000000c0\(aq] - } - ] -} -.ft P -.fi -.UNINDENT -.UNINDENT -.UNINDENT -.SH DEVICE INFO -.sp -New in version 3.5.0. - -.sp -A \fIdevice info object\fP in ReFrame’s configuration is used to hold information about a specific type of devices in a system partition and is made available to the tests through the \fI\%devices\fP attribute of the \fI\%current_partition\fP\&. -.INDENT 0.0 -.TP -.B \&.type -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -The type of the device, for example \fB"gpu"\fP\&. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.arch -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -The microarchitecture of the device. -.UNINDENT -.INDENT 0.0 -.TP -.B \&.num_devices -.INDENT 7.0 -.TP -.B Required -No -.TP -.B Default -\fBNone\fP -.UNINDENT -.sp -Number of devices of this type inside the system partition. -.UNINDENT -.SH AUTHOR -ReFrame Project Developers -.SH COPYRIGHT -2016-2022, CSCS/ETH Zurich -.\" Generated by docutils manpage writer. -. From 0c01d09c57e6d1a9affa792473b7c20baf47ad9a Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 7 Oct 2022 15:07:06 +0200 Subject: [PATCH 24/42] Add remote listings --- docs/listings/alltests_daint.txt | 130 +++++----- .../osu_bandwidth_concretized_daint.txt | 8 +- docs/listings/osu_bench_deps.txt | 78 +++--- docs/listings/osu_bench_fixtures_list.txt | 8 +- docs/listings/osu_bench_fixtures_run.txt | 74 +++--- docs/listings/osu_bench_list_concretized.txt | 8 +- .../osu_bench_list_concretized_gnu.txt | 8 +- docs/listings/osu_latency_list.txt | 8 +- docs/listings/osu_latency_unresolved_deps.txt | 40 +-- docs/listings/stream4_daint.txt | 244 +++++++++--------- 10 files changed, 303 insertions(+), 303 deletions(-) diff --git a/docs/listings/alltests_daint.txt b/docs/listings/alltests_daint.txt index 9d6bb1bfb5..1d75dd1829 100644 --- a/docs/listings/alltests_daint.txt +++ b/docs/listings/alltests_daint.txt @@ -1,16 +1,16 @@ [ReFrame Setup] - version: 4.0.0-dev.1+a4a2a15f + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/basics/ -R -n HelloMultiLangTest|HelloThreadedExtended2Test|StreamWithRefTest --performance-report -r' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: (R) '/home/user/Devel/reframe/tutorials/basics' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-_wgq5paa.log' + log files: '/tmp/rfm-rlcxnr_v.log' [==========] Running 4 check(s) -[==========] Started on Fri Oct 7 11:17:20 2022 +[==========] Started on Fri Oct 7 12:28:29 2022 [----------] start processing checks [ RUN ] HelloMultiLangTest %lang=cpp /71bf65a3 @daint:login+builtin @@ -65,82 +65,82 @@ [ OK ] ( 8/42) HelloMultiLangTest %lang=c /7cfa870e @daint:login+intel [ OK ] ( 9/42) HelloMultiLangTest %lang=c /7cfa870e @daint:login+nvidia [ OK ] (10/42) HelloMultiLangTest %lang=c /7cfa870e @daint:login+cray -[ OK ] (11/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+nvidia -[ OK ] (12/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+intel -[ OK ] (13/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+intel -[ OK ] (14/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+nvidia -[ OK ] (15/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+cray -[ OK ] (16/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+cray -[ OK ] (17/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+gnu -[ OK ] (18/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+gnu -[ OK ] (19/42) HelloThreadedExtended2Test /57223829 @daint:login+builtin -[ OK ] (20/42) HelloThreadedExtended2Test /57223829 @daint:login+gnu -[ OK ] (21/42) HelloThreadedExtended2Test /57223829 @daint:login+intel -[ OK ] (22/42) HelloThreadedExtended2Test /57223829 @daint:login+nvidia -[ OK ] (23/42) HelloThreadedExtended2Test /57223829 @daint:login+cray -[ OK ] (24/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+gnu -[ OK ] (25/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+intel -[ OK ] (26/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+nvidia -[ OK ] (27/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+cray -[ OK ] (28/42) HelloThreadedExtended2Test /57223829 @daint:mc+gnu -[ OK ] (29/42) HelloThreadedExtended2Test /57223829 @daint:mc+intel -[ OK ] (30/42) HelloThreadedExtended2Test /57223829 @daint:mc+nvidia -[ OK ] (31/42) StreamWithRefTest /f925207b @daint:login+gnu -P: Copy: 71563.0 MB/s (r:0, l:None, u:None) -P: Scale: 44535.4 MB/s (r:0, l:None, u:None) -P: Add: 48558.8 MB/s (r:0, l:None, u:None) -P: Triad: 48609.1 MB/s (r:0, l:None, u:None) -[ OK ] (32/42) HelloThreadedExtended2Test /57223829 @daint:mc+cray -[ OK ] (33/42) StreamWithRefTest /f925207b @daint:mc+gnu -P: Copy: 49028.9 MB/s (r:0, l:None, u:None) -P: Scale: 32063.7 MB/s (r:0, l:None, u:None) -P: Add: 33367.9 MB/s (r:0, l:None, u:None) -P: Triad: 33669.6 MB/s (r:0, l:None, u:None) -[ OK ] (34/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+nvidia -[ OK ] (35/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+cray -[ OK ] (36/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+intel -[ OK ] (37/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+gnu -[ OK ] (38/42) HelloThreadedExtended2Test /57223829 @daint:gpu+intel -[ OK ] (39/42) HelloThreadedExtended2Test /57223829 @daint:gpu+gnu +[ OK ] (11/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+cray +[ OK ] (12/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+intel +[ OK ] (13/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+nvidia +[ OK ] (14/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:mc+gnu +[ OK ] (15/42) HelloThreadedExtended2Test /57223829 @daint:login+builtin +[ OK ] (16/42) HelloThreadedExtended2Test /57223829 @daint:login+gnu +[ OK ] (17/42) HelloThreadedExtended2Test /57223829 @daint:login+intel +[ OK ] (18/42) HelloThreadedExtended2Test /57223829 @daint:login+nvidia +[ OK ] (19/42) HelloThreadedExtended2Test /57223829 @daint:login+cray +[ OK ] (20/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+gnu +[ OK ] (21/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+intel +[ OK ] (22/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+cray +[ OK ] (23/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+gnu +[ OK ] (24/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+cray +[ OK ] (25/42) HelloThreadedExtended2Test /57223829 @daint:gpu+intel +[ OK ] (26/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+intel +[ OK ] (27/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+nvidia +[ OK ] (28/42) StreamWithRefTest /f925207b @daint:login+gnu +P: Copy: 69797.3 MB/s (r:0, l:None, u:None) +P: Scale: 45046.8 MB/s (r:0, l:None, u:None) +P: Add: 48981.3 MB/s (r:0, l:None, u:None) +P: Triad: 48733.2 MB/s (r:0, l:None, u:None) +[ OK ] (29/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+cray +[ OK ] (30/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+gnu +[ OK ] (31/42) HelloMultiLangTest %lang=c /7cfa870e @daint:gpu+intel +[ OK ] (32/42) HelloMultiLangTest %lang=cpp /71bf65a3 @daint:gpu+nvidia +[ OK ] (33/42) HelloMultiLangTest %lang=c /7cfa870e @daint:mc+nvidia +[ OK ] (34/42) HelloThreadedExtended2Test /57223829 @daint:gpu+gnu +[ OK ] (35/42) HelloThreadedExtended2Test /57223829 @daint:mc+cray +[ OK ] (36/42) HelloThreadedExtended2Test /57223829 @daint:mc+gnu +[ OK ] (37/42) StreamWithRefTest /f925207b @daint:mc+gnu +P: Copy: 52773.7 MB/s (r:0, l:None, u:None) +P: Scale: 32666.0 MB/s (r:0, l:None, u:None) +P: Add: 34786.5 MB/s (r:0, l:None, u:None) +P: Triad: 34904.0 MB/s (r:0, l:None, u:None) +[ OK ] (38/42) HelloThreadedExtended2Test /57223829 @daint:mc+nvidia +[ OK ] (39/42) HelloThreadedExtended2Test /57223829 @daint:mc+intel [ OK ] (40/42) HelloThreadedExtended2Test /57223829 @daint:gpu+cray -[ OK ] (41/42) HelloThreadedExtended2Test /57223829 @daint:gpu+nvidia -[ OK ] (42/42) StreamWithRefTest /f925207b @daint:gpu+gnu -P: Copy: 50682.0 MB/s (r:0, l:None, u:None) -P: Scale: 35014.2 MB/s (r:0, l:None, u:None) -P: Add: 38535.3 MB/s (r:0, l:None, u:None) -P: Triad: 38559.1 MB/s (r:0, l:None, u:None) +[ OK ] (41/42) StreamWithRefTest /f925207b @daint:gpu+gnu +P: Copy: 50396.1 MB/s (r:0, l:None, u:None) +P: Scale: 34650.0 MB/s (r:0, l:None, u:None) +P: Add: 38072.3 MB/s (r:0, l:None, u:None) +P: Triad: 38566.1 MB/s (r:0, l:None, u:None) +[ OK ] (42/42) HelloThreadedExtended2Test /57223829 @daint:gpu+nvidia [----------] all spawned checks have finished [ PASSED ] Ran 42/42 test case(s) from 4 check(s) (0 failure(s), 0 skipped) -[==========] Finished on Fri Oct 7 11:22:14 2022 +[==========] Finished on Fri Oct 7 12:38:41 2022 ================================================================================ PERFORMANCE REPORT -------------------------------------------------------------------------------- [StreamWithRefTest /f925207b @daint:login:gnu] - num_gpus_per_node: 0 num_tasks: 1 + num_gpus_per_node: 0 performance: - - Copy: 71563.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 44535.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 48558.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 48609.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 69797.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 45046.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 48981.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 48733.2 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamWithRefTest /f925207b @daint:gpu:gnu] - num_gpus_per_node: 0 num_tasks: 1 + num_gpus_per_node: 0 performance: - - Copy: 50682.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 35014.2 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 38535.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 38559.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 50396.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 34650.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 38072.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 38566.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamWithRefTest /f925207b @daint:mc:gnu] - num_gpus_per_node: 0 num_tasks: 1 + num_gpus_per_node: 0 performance: - - Copy: 49028.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 32063.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 33367.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 33669.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 52773.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 32666.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 34786.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 34904.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) -------------------------------------------------------------------------------- -Run report saved in '/home/user/.reframe/reports/run-report-70.json' -Log file(s) saved in '/tmp/rfm-_wgq5paa.log' +Run report saved in '/home/user/.reframe/reports/run-report-74.json' +Log file(s) saved in '/tmp/rfm-rlcxnr_v.log' diff --git a/docs/listings/osu_bandwidth_concretized_daint.txt b/docs/listings/osu_bandwidth_concretized_daint.txt index 4ca62eaeee..884f566c6e 100644 --- a/docs/listings/osu_bandwidth_concretized_daint.txt +++ b/docs/listings/osu_bandwidth_concretized_daint.txt @@ -1,13 +1,13 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/fixtures/osu_benchmarks.py -n osu_bandwidth_test -lC' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/fixtures/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-29dsnhwp.log' + log files: '/tmp/rfm-ww7yfkil.log' [List of matched checks] - osu_bandwidth_test /026711a1 @daint:gpu+gnu @@ -21,4 +21,4 @@ ^fetch_osu_benchmarks ~daint /79cd6023 @daint:gpu+gnu Concretized 7 test case(s) -Log file(s) saved in '/tmp/rfm-29dsnhwp.log' +Log file(s) saved in '/tmp/rfm-ww7yfkil.log' diff --git a/docs/listings/osu_bench_deps.txt b/docs/listings/osu_bench_deps.txt index 2b61a84c97..1a212e3883 100644 --- a/docs/listings/osu_bench_deps.txt +++ b/docs/listings/osu_bench_deps.txt @@ -1,16 +1,16 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/deps/osu_benchmarks.py -r' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-bcp1443i.log' + log files: '/tmp/rfm-csrlj0_9.log' [==========] Running 8 check(s) -[==========] Started on Wed Oct 5 15:11:25 2022 +[==========] Started on Fri Oct 7 12:42:05 2022 [----------] start processing checks [ RUN ] OSUDownloadTest /7de668df @daint:login+builtin @@ -40,44 +40,44 @@ [ RUN ] OSULatencyTest /14f35a43 @daint:gpu+intel [ RUN ] OSULatencyTest /14f35a43 @daint:gpu+nvidia [ OK ] ( 5/22) OSUAllreduceTest %mpi_tasks=16 /7f033d39 @daint:gpu+gnu -P: latency: 12.25 us (r:0, l:None, u:None) -[ OK ] ( 6/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+gnu -P: latency: 8.9 us (r:0, l:None, u:None) -[ OK ] ( 7/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+intel -P: latency: 8.97 us (r:0, l:None, u:None) -[ OK ] ( 8/22) OSULatencyTest /14f35a43 @daint:gpu+gnu -P: latency: 1.15 us (r:0, l:None, u:None) -[ OK ] ( 9/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+gnu -P: latency: 3.33 us (r:0, l:None, u:None) -[ OK ] (10/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+gnu -P: latency: 1.73 us (r:0, l:None, u:None) -[ OK ] (11/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+intel -P: latency: 1.7 us (r:0, l:None, u:None) -[ OK ] (12/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+intel -P: latency: 4.66 us (r:0, l:None, u:None) +P: latency: 21.48 us (r:0, l:None, u:None) +[ OK ] ( 6/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+intel +P: latency: 10.72 us (r:0, l:None, u:None) +[ OK ] ( 7/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+gnu +P: latency: 1.69 us (r:0, l:None, u:None) +[ OK ] ( 8/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+intel +P: latency: 3.25 us (r:0, l:None, u:None) +[ OK ] ( 9/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+gnu +P: latency: 12.05 us (r:0, l:None, u:None) +[ OK ] (10/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+gnu +P: latency: 6.28 us (r:0, l:None, u:None) +[ OK ] (11/22) OSULatencyTest /14f35a43 @daint:gpu+gnu +P: latency: 1.21 us (r:0, l:None, u:None) +[ OK ] (12/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+intel +P: latency: 1.68 us (r:0, l:None, u:None) [ OK ] (13/22) OSUAllreduceTest %mpi_tasks=16 /7f033d39 @daint:gpu+intel -P: latency: 14.28 us (r:0, l:None, u:None) +P: latency: 36.2 us (r:0, l:None, u:None) [ OK ] (14/22) OSUBandwidthTest /764cdb0b @daint:gpu+gnu -P: bandwidth: 9711.67 MB/s (r:0, l:None, u:None) -[ OK ] (15/22) OSULatencyTest /14f35a43 @daint:gpu+intel -P: latency: 1.17 us (r:0, l:None, u:None) -[ OK ] (16/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+nvidia -P: latency: 1.66 us (r:0, l:None, u:None) -[ OK ] (17/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+nvidia -P: latency: 7.84 us (r:0, l:None, u:None) -[ OK ] (18/22) OSULatencyTest /14f35a43 @daint:gpu+nvidia -P: latency: 1.15 us (r:0, l:None, u:None) -[ OK ] (19/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+nvidia -P: latency: 4.18 us (r:0, l:None, u:None) +P: bandwidth: 8979.26 MB/s (r:0, l:None, u:None) +[ OK ] (15/22) OSUAllreduceTest %mpi_tasks=2 /9d550c4f @daint:gpu+nvidia +P: latency: 1.65 us (r:0, l:None, u:None) +[ OK ] (16/22) OSULatencyTest /14f35a43 @daint:gpu+nvidia +P: latency: 1.14 us (r:0, l:None, u:None) +[ OK ] (17/22) OSUAllreduceTest %mpi_tasks=4 /84b85d90 @daint:gpu+nvidia +P: latency: 4.97 us (r:0, l:None, u:None) +[ OK ] (18/22) OSUAllreduceTest %mpi_tasks=8 /005fca19 @daint:gpu+nvidia +P: latency: 10.16 us (r:0, l:None, u:None) +[ OK ] (19/22) OSULatencyTest /14f35a43 @daint:gpu+intel +P: latency: 1.18 us (r:0, l:None, u:None) [ OK ] (20/22) OSUAllreduceTest %mpi_tasks=16 /7f033d39 @daint:gpu+nvidia -P: latency: 13.2 us (r:0, l:None, u:None) -[ OK ] (21/22) OSUBandwidthTest /764cdb0b @daint:gpu+intel -P: bandwidth: 9508.26 MB/s (r:0, l:None, u:None) -[ OK ] (22/22) OSUBandwidthTest /764cdb0b @daint:gpu+nvidia -P: bandwidth: 9298.19 MB/s (r:0, l:None, u:None) +P: latency: 25.37 us (r:0, l:None, u:None) +[ OK ] (21/22) OSUBandwidthTest /764cdb0b @daint:gpu+nvidia +P: bandwidth: 9779.82 MB/s (r:0, l:None, u:None) +[ OK ] (22/22) OSUBandwidthTest /764cdb0b @daint:gpu+intel +P: bandwidth: 9429.47 MB/s (r:0, l:None, u:None) [----------] all spawned checks have finished [ PASSED ] Ran 22/22 test case(s) from 8 check(s) (0 failure(s), 0 skipped) -[==========] Finished on Wed Oct 5 15:24:10 2022 -Run report saved in '/home/user/.reframe/reports/run-report-65.json' -Log file(s) saved in '/tmp/rfm-bcp1443i.log' +[==========] Finished on Fri Oct 7 12:51:03 2022 +Run report saved in '/home/user/.reframe/reports/run-report-76.json' +Log file(s) saved in '/tmp/rfm-csrlj0_9.log' diff --git a/docs/listings/osu_bench_fixtures_list.txt b/docs/listings/osu_bench_fixtures_list.txt index 10bb8d3a42..88ecda7749 100644 --- a/docs/listings/osu_bench_fixtures_list.txt +++ b/docs/listings/osu_bench_fixtures_list.txt @@ -1,13 +1,13 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/fixtures/osu_benchmarks.py -l' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/fixtures/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-i3lzbixe.log' + log files: '/tmp/rfm-522ch6rc.log' [List of matched checks] - osu_allreduce_test %mpi_tasks=16 /1fe48834 @@ -54,4 +54,4 @@ ^fetch_osu_benchmarks ~daint /79cd6023 Found 6 check(s) -Log file(s) saved in '/tmp/rfm-i3lzbixe.log' +Log file(s) saved in '/tmp/rfm-522ch6rc.log' diff --git a/docs/listings/osu_bench_fixtures_run.txt b/docs/listings/osu_bench_fixtures_run.txt index c62185d82d..bc6a051026 100644 --- a/docs/listings/osu_bench_fixtures_run.txt +++ b/docs/listings/osu_bench_fixtures_run.txt @@ -1,16 +1,16 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/fixtures/osu_benchmarks.py -r' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/fixtures/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-n_metrl9.log' + log files: '/tmp/rfm-0c2dohjr.log' [==========] Running 10 check(s) -[==========] Started on Wed Oct 5 15:24:14 2022 +[==========] Started on Fri Oct 7 12:51:07 2022 [----------] start processing checks [ RUN ] fetch_osu_benchmarks ~daint /79cd6023 @daint:gpu+gnu @@ -39,45 +39,45 @@ [ RUN ] osu_bandwidth_test /026711a1 @daint:gpu+nvidia [ RUN ] osu_latency_test /d2c978ad @daint:gpu+intel [ RUN ] osu_latency_test /d2c978ad @daint:gpu+nvidia -[ OK ] ( 5/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+intel -P: latency: 9.26 us (r:0, l:None, u:None) -[ OK ] ( 6/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+intel -P: latency: 20.63 us (r:0, l:None, u:None) -[ OK ] ( 7/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+gnu -P: latency: 8.21 us (r:0, l:None, u:None) -[ OK ] ( 8/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+gnu -P: latency: 4.56 us (r:0, l:None, u:None) -[ OK ] ( 9/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+intel -P: latency: 3.26 us (r:0, l:None, u:None) -[ OK ] (10/22) osu_latency_test /d2c978ad @daint:gpu+gnu +[ OK ] ( 5/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+gnu +P: latency: 8.84 us (r:0, l:None, u:None) +[ OK ] ( 6/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+intel +P: latency: 5.14 us (r:0, l:None, u:None) +[ OK ] ( 7/22) osu_latency_test /d2c978ad @daint:gpu+gnu P: latency: 1.18 us (r:0, l:None, u:None) -[ OK ] (11/22) osu_allreduce_test %mpi_tasks=2 /9f29c081 @daint:gpu+gnu -P: latency: 1.73 us (r:0, l:None, u:None) -[ OK ] (12/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+gnu -P: latency: 13.15 us (r:0, l:None, u:None) -[ OK ] (13/22) osu_allreduce_test %mpi_tasks=2 /9f29c081 @daint:gpu+intel +[ OK ] ( 8/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+intel +P: latency: 38.64 us (r:0, l:None, u:None) +[ OK ] ( 9/22) osu_allreduce_test %mpi_tasks=2 /9f29c081 @daint:gpu+gnu P: latency: 1.69 us (r:0, l:None, u:None) +[ OK ] (10/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+intel +P: latency: 6.97 us (r:0, l:None, u:None) +[ OK ] (11/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+gnu +P: latency: 49.68 us (r:0, l:None, u:None) +[ OK ] (12/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+nvidia +P: latency: 55.51 us (r:0, l:None, u:None) +[ OK ] (13/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+gnu +P: latency: 5.71 us (r:0, l:None, u:None) [ OK ] (14/22) osu_bandwidth_test /026711a1 @daint:gpu+gnu -P: bandwidth: 9711.54 MB/s (r:0, l:None, u:None) -[ OK ] (15/22) osu_allreduce_test %mpi_tasks=16 /1fe48834 @daint:gpu+nvidia -P: latency: 13.41 us (r:0, l:None, u:None) +P: bandwidth: 8982.88 MB/s (r:0, l:None, u:None) +[ OK ] (15/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+nvidia +P: latency: 6.87 us (r:0, l:None, u:None) [ OK ] (16/22) osu_allreduce_test %mpi_tasks=2 /9f29c081 @daint:gpu+nvidia P: latency: 1.65 us (r:0, l:None, u:None) -[ OK ] (17/22) osu_latency_test /d2c978ad @daint:gpu+intel -P: latency: 1.17 us (r:0, l:None, u:None) -[ OK ] (18/22) osu_latency_test /d2c978ad @daint:gpu+nvidia +[ OK ] (17/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+nvidia +P: latency: 6.8 us (r:0, l:None, u:None) +[ OK ] (18/22) osu_latency_test /d2c978ad @daint:gpu+intel P: latency: 1.18 us (r:0, l:None, u:None) -[ OK ] (19/22) osu_allreduce_test %mpi_tasks=4 /2129dc34 @daint:gpu+nvidia -P: latency: 4.79 us (r:0, l:None, u:None) -[ OK ] (20/22) osu_allreduce_test %mpi_tasks=8 /ae01c137 @daint:gpu+nvidia -P: latency: 7.57 us (r:0, l:None, u:None) -[ OK ] (21/22) osu_bandwidth_test /026711a1 @daint:gpu+intel -P: bandwidth: 9843.72 MB/s (r:0, l:None, u:None) -[ OK ] (22/22) osu_bandwidth_test /026711a1 @daint:gpu+nvidia -P: bandwidth: 9785.8 MB/s (r:0, l:None, u:None) +[ OK ] (19/22) osu_allreduce_test %mpi_tasks=2 /9f29c081 @daint:gpu+intel +P: latency: 2.62 us (r:0, l:None, u:None) +[ OK ] (20/22) osu_latency_test /d2c978ad @daint:gpu+nvidia +P: latency: 1.11 us (r:0, l:None, u:None) +[ OK ] (21/22) osu_bandwidth_test /026711a1 @daint:gpu+nvidia +P: bandwidth: 9813.96 MB/s (r:0, l:None, u:None) +[ OK ] (22/22) osu_bandwidth_test /026711a1 @daint:gpu+intel +P: bandwidth: 9775.67 MB/s (r:0, l:None, u:None) [----------] all spawned checks have finished [ PASSED ] Ran 22/22 test case(s) from 10 check(s) (0 failure(s), 0 skipped) -[==========] Finished on Wed Oct 5 15:31:53 2022 -Run report saved in '/home/user/.reframe/reports/run-report-66.json' -Log file(s) saved in '/tmp/rfm-n_metrl9.log' +[==========] Finished on Fri Oct 7 12:57:46 2022 +Run report saved in '/home/user/.reframe/reports/run-report-77.json' +Log file(s) saved in '/tmp/rfm-0c2dohjr.log' diff --git a/docs/listings/osu_bench_list_concretized.txt b/docs/listings/osu_bench_list_concretized.txt index 4e8282dcf7..32ff336663 100644 --- a/docs/listings/osu_bench_list_concretized.txt +++ b/docs/listings/osu_bench_list_concretized.txt @@ -1,13 +1,13 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/deps/osu_benchmarks.py -lC' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-ry5fdbm2.log' + log files: '/tmp/rfm-j2qd_as2.log' [List of matched checks] - OSUAllreduceTest %mpi_tasks=16 /7f033d39 @daint:gpu+gnu @@ -66,4 +66,4 @@ ^OSUDownloadTest /7de668df @daint:login+builtin Concretized 22 test case(s) -Log file(s) saved in '/tmp/rfm-ry5fdbm2.log' +Log file(s) saved in '/tmp/rfm-j2qd_as2.log' diff --git a/docs/listings/osu_bench_list_concretized_gnu.txt b/docs/listings/osu_bench_list_concretized_gnu.txt index 748b8ec86d..b293e73021 100644 --- a/docs/listings/osu_bench_list_concretized_gnu.txt +++ b/docs/listings/osu_bench_list_concretized_gnu.txt @@ -1,13 +1,13 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/deps/osu_benchmarks.py -n OSULatencyTest -L -p builtin -p gnu' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-o4x9lxoo.log' + log files: '/tmp/rfm-86ylicrv.log' [List of matched checks] - OSULatencyTest /14f35a43 [variant: 0, file: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py'] @@ -15,4 +15,4 @@ ^OSUDownloadTest /7de668df [variant: 0, file: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py'] Found 3 check(s) -Log file(s) saved in '/tmp/rfm-o4x9lxoo.log' +Log file(s) saved in '/tmp/rfm-86ylicrv.log' diff --git a/docs/listings/osu_latency_list.txt b/docs/listings/osu_latency_list.txt index e95d70a057..fd7838ec7f 100644 --- a/docs/listings/osu_latency_list.txt +++ b/docs/listings/osu_latency_list.txt @@ -1,13 +1,13 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/deps/osu_benchmarks.py -n OSULatencyTest -l' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-4_7t2oj3.log' + log files: '/tmp/rfm-nlbvceid.log' [List of matched checks] - OSULatencyTest /14f35a43 @@ -15,4 +15,4 @@ ^OSUDownloadTest /7de668df Found 3 check(s) -Log file(s) saved in '/tmp/rfm-4_7t2oj3.log' +Log file(s) saved in '/tmp/rfm-nlbvceid.log' diff --git a/docs/listings/osu_latency_unresolved_deps.txt b/docs/listings/osu_latency_unresolved_deps.txt index 5193769926..1a3424f579 100644 --- a/docs/listings/osu_latency_unresolved_deps.txt +++ b/docs/listings/osu_latency_unresolved_deps.txt @@ -1,41 +1,41 @@ [ReFrame Setup] - version: 4.0.0-dev.1+6c51b548 + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/deps/osu_benchmarks.py -n OSULatencyTest --system=daint:gpu -l' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/deps/osu_benchmarks.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-es6fy9jr.log' + log files: '/tmp/rfm-b_xhljuk.log' WARNING: could not resolve dependency: ('OSUBuildTest', 'daint:gpu', 'gnu') -> 'OSUDownloadTest' WARNING: could not resolve dependency: ('OSUBuildTest', 'daint:gpu', 'intel') -> 'OSUDownloadTest' WARNING: could not resolve dependency: ('OSUBuildTest', 'daint:gpu', 'nvidia') -> 'OSUDownloadTest' WARNING: skipping all dependent test cases - - ('OSUBuildTest', 'daint:gpu', 'gnu') + - ('OSUBuildTest', 'daint:gpu', 'intel') + - ('OSULatencyTest', 'daint:gpu', 'intel') + - ('OSUAllreduceTest_2', 'daint:gpu', 'intel') + - ('OSUAllreduceTest_3', 'daint:gpu', 'intel') - ('OSUBuildTest', 'daint:gpu', 'nvidia') - - ('OSUAllreduceTest_1', 'daint:gpu', 'gnu') + - ('OSUAllreduceTest_3', 'daint:gpu', 'nvidia') + - ('OSUAllreduceTest_0', 'daint:gpu', 'intel') + - ('OSUAllreduceTest_1', 'daint:gpu', 'intel') - ('OSUAllreduceTest_2', 'daint:gpu', 'nvidia') - - ('OSUAllreduceTest_0', 'daint:gpu', 'nvidia') + - ('OSUBandwidthTest', 'daint:gpu', 'intel') + - ('OSUBuildTest', 'daint:gpu', 'gnu') + - ('OSULatencyTest', 'daint:gpu', 'nvidia') - ('OSUBandwidthTest', 'daint:gpu', 'nvidia') - - ('OSUAllreduceTest_3', 'daint:gpu', 'gnu') - - ('OSUAllreduceTest_0', 'daint:gpu', 'gnu') - - ('OSUBandwidthTest', 'daint:gpu', 'gnu') + - ('OSUAllreduceTest_0', 'daint:gpu', 'nvidia') - ('OSUAllreduceTest_1', 'daint:gpu', 'nvidia') - - ('OSUBuildTest', 'daint:gpu', 'intel') - - ('OSUBandwidthTest', 'daint:gpu', 'intel') - - ('OSUAllreduceTest_0', 'daint:gpu', 'intel') - - ('OSUAllreduceTest_1', 'daint:gpu', 'intel') - - ('OSUAllreduceTest_2', 'daint:gpu', 'intel') - - ('OSULatencyTest', 'daint:gpu', 'gnu') + - ('OSUBandwidthTest', 'daint:gpu', 'gnu') + - ('OSUAllreduceTest_0', 'daint:gpu', 'gnu') + - ('OSUAllreduceTest_1', 'daint:gpu', 'gnu') + - ('OSUAllreduceTest_3', 'daint:gpu', 'gnu') - ('OSUAllreduceTest_2', 'daint:gpu', 'gnu') - - ('OSULatencyTest', 'daint:gpu', 'nvidia') - - ('OSUAllreduceTest_3', 'daint:gpu', 'nvidia') - - ('OSULatencyTest', 'daint:gpu', 'intel') - - ('OSUAllreduceTest_3', 'daint:gpu', 'intel') + - ('OSULatencyTest', 'daint:gpu', 'gnu') [List of matched checks] Found 0 check(s) -Log file(s) saved in '/tmp/rfm-es6fy9jr.log' +Log file(s) saved in '/tmp/rfm-b_xhljuk.log' diff --git a/docs/listings/stream4_daint.txt b/docs/listings/stream4_daint.txt index 709a72dc6c..dda1cd3076 100644 --- a/docs/listings/stream4_daint.txt +++ b/docs/listings/stream4_daint.txt @@ -1,16 +1,16 @@ [ReFrame Setup] - version: 4.0.0-dev.1+a4a2a15f + version: 4.0.0-dev.1+9a4b68ae command: './bin/reframe -c tutorials/basics/stream/stream4.py -r --performance-report' launched by: user@daint104 working directory: '/home/user/Devel/reframe' - settings file: '/home/user/Devel/reframe/tutorials/config/settings.py' + settings files: '', '/home/user/Devel/reframe/tutorials/config/settings.py' check search path: '/home/user/Devel/reframe/tutorials/basics/stream/stream4.py' stage directory: '/home/user/Devel/reframe/stage' output directory: '/home/user/Devel/reframe/output' - log files: '/tmp/rfm-c9f_ne8m.log' + log files: '/tmp/rfm-k4x8yojn.log' [==========] Running 1 check(s) -[==========] Started on Fri Oct 7 11:22:15 2022 +[==========] Started on Fri Oct 7 12:38:42 2022 [----------] start processing checks [ RUN ] StreamMultiSysTest /eec1c676 @daint:login+gnu @@ -26,181 +26,181 @@ [ RUN ] StreamMultiSysTest /eec1c676 @daint:mc+nvidia [ RUN ] StreamMultiSysTest /eec1c676 @daint:mc+cray [ OK ] ( 1/12) StreamMultiSysTest /eec1c676 @daint:login+gnu -P: Copy: 90564.7 MB/s (r:0, l:None, u:None) -P: Scale: 69209.5 MB/s (r:0, l:None, u:None) -P: Add: 74898.5 MB/s (r:0, l:None, u:None) -P: Triad: 74036.6 MB/s (r:0, l:None, u:None) +P: Copy: 92708.6 MB/s (r:0, l:None, u:None) +P: Scale: 68575.1 MB/s (r:0, l:None, u:None) +P: Add: 76050.3 MB/s (r:0, l:None, u:None) +P: Triad: 78071.8 MB/s (r:0, l:None, u:None) [ OK ] ( 2/12) StreamMultiSysTest /eec1c676 @daint:login+intel -P: Copy: 83611.7 MB/s (r:0, l:None, u:None) -P: Scale: 72885.0 MB/s (r:0, l:None, u:None) -P: Add: 79780.7 MB/s (r:0, l:None, u:None) -P: Triad: 99212.3 MB/s (r:0, l:None, u:None) +P: Copy: 87982.8 MB/s (r:0, l:None, u:None) +P: Scale: 67941.1 MB/s (r:0, l:None, u:None) +P: Add: 48635.5 MB/s (r:0, l:None, u:None) +P: Triad: 77366.4 MB/s (r:0, l:None, u:None) [ OK ] ( 3/12) StreamMultiSysTest /eec1c676 @daint:login+nvidia -P: Copy: 98383.4 MB/s (r:0, l:None, u:None) -P: Scale: 70538.5 MB/s (r:0, l:None, u:None) -P: Add: 79402.4 MB/s (r:0, l:None, u:None) -P: Triad: 79138.3 MB/s (r:0, l:None, u:None) +P: Copy: 97052.0 MB/s (r:0, l:None, u:None) +P: Scale: 69147.9 MB/s (r:0, l:None, u:None) +P: Add: 76828.8 MB/s (r:0, l:None, u:None) +P: Triad: 75792.7 MB/s (r:0, l:None, u:None) [ OK ] ( 4/12) StreamMultiSysTest /eec1c676 @daint:login+cray -P: Copy: 63243.9 MB/s (r:0, l:None, u:None) -P: Scale: 49733.9 MB/s (r:0, l:None, u:None) -P: Add: 40884.8 MB/s (r:0, l:None, u:None) -P: Triad: 56149.9 MB/s (r:0, l:None, u:None) -[ OK ] ( 5/12) StreamMultiSysTest /eec1c676 @daint:mc+cray -P: Copy: 47068.4 MB/s (r:0, l:None, u:None) -P: Scale: 40086.2 MB/s (r:0, l:None, u:None) -P: Add: 43688.6 MB/s (r:0, l:None, u:None) -P: Triad: 44106.8 MB/s (r:0, l:None, u:None) -[ OK ] ( 6/12) StreamMultiSysTest /eec1c676 @daint:mc+nvidia -P: Copy: 46798.4 MB/s (r:0, l:None, u:None) -P: Scale: 40481.8 MB/s (r:0, l:None, u:None) -P: Add: 44143.7 MB/s (r:0, l:None, u:None) -P: Triad: 44570.7 MB/s (r:0, l:None, u:None) -[ OK ] ( 7/12) StreamMultiSysTest /eec1c676 @daint:mc+intel -P: Copy: 52240.0 MB/s (r:0, l:None, u:None) -P: Scale: 49426.5 MB/s (r:0, l:None, u:None) -P: Add: 56988.6 MB/s (r:0, l:None, u:None) -P: Triad: 56457.3 MB/s (r:0, l:None, u:None) -[ OK ] ( 8/12) StreamMultiSysTest /eec1c676 @daint:mc+gnu -P: Copy: 48686.5 MB/s (r:0, l:None, u:None) -P: Scale: 38562.8 MB/s (r:0, l:None, u:None) -P: Add: 43707.3 MB/s (r:0, l:None, u:None) -P: Triad: 44041.8 MB/s (r:0, l:None, u:None) -[ OK ] ( 9/12) StreamMultiSysTest /eec1c676 @daint:gpu+gnu -P: Copy: 42724.6 MB/s (r:0, l:None, u:None) -P: Scale: 38443.7 MB/s (r:0, l:None, u:None) -P: Add: 43619.8 MB/s (r:0, l:None, u:None) -P: Triad: 43258.9 MB/s (r:0, l:None, u:None) -[ OK ] (10/12) StreamMultiSysTest /eec1c676 @daint:gpu+intel -P: Copy: 52316.4 MB/s (r:0, l:None, u:None) -P: Scale: 54141.9 MB/s (r:0, l:None, u:None) -P: Add: 57550.7 MB/s (r:0, l:None, u:None) -P: Triad: 57150.4 MB/s (r:0, l:None, u:None) -[ OK ] (11/12) StreamMultiSysTest /eec1c676 @daint:gpu+nvidia -P: Copy: 51687.1 MB/s (r:0, l:None, u:None) -P: Scale: 39685.6 MB/s (r:0, l:None, u:None) -P: Add: 44116.6 MB/s (r:0, l:None, u:None) -P: Triad: 44475.0 MB/s (r:0, l:None, u:None) +P: Copy: 83067.7 MB/s (r:0, l:None, u:None) +P: Scale: 69435.7 MB/s (r:0, l:None, u:None) +P: Add: 77441.8 MB/s (r:0, l:None, u:None) +P: Triad: 76907.5 MB/s (r:0, l:None, u:None) +[ OK ] ( 5/12) StreamMultiSysTest /eec1c676 @daint:mc+gnu +P: Copy: 48802.6 MB/s (r:0, l:None, u:None) +P: Scale: 38805.4 MB/s (r:0, l:None, u:None) +P: Add: 43816.7 MB/s (r:0, l:None, u:None) +P: Triad: 44180.1 MB/s (r:0, l:None, u:None) +[ OK ] ( 6/12) StreamMultiSysTest /eec1c676 @daint:mc+intel +P: Copy: 52603.5 MB/s (r:0, l:None, u:None) +P: Scale: 49793.3 MB/s (r:0, l:None, u:None) +P: Add: 57158.5 MB/s (r:0, l:None, u:None) +P: Triad: 56795.7 MB/s (r:0, l:None, u:None) +[ OK ] ( 7/12) StreamMultiSysTest /eec1c676 @daint:mc+nvidia +P: Copy: 47397.3 MB/s (r:0, l:None, u:None) +P: Scale: 40625.7 MB/s (r:0, l:None, u:None) +P: Add: 44391.4 MB/s (r:0, l:None, u:None) +P: Triad: 44786.4 MB/s (r:0, l:None, u:None) +[ OK ] ( 8/12) StreamMultiSysTest /eec1c676 @daint:mc+cray +P: Copy: 51607.7 MB/s (r:0, l:None, u:None) +P: Scale: 44579.5 MB/s (r:0, l:None, u:None) +P: Add: 48547.6 MB/s (r:0, l:None, u:None) +P: Triad: 49056.7 MB/s (r:0, l:None, u:None) +[ OK ] ( 9/12) StreamMultiSysTest /eec1c676 @daint:gpu+intel +P: Copy: 52810.4 MB/s (r:0, l:None, u:None) +P: Scale: 54267.8 MB/s (r:0, l:None, u:None) +P: Add: 57985.8 MB/s (r:0, l:None, u:None) +P: Triad: 57398.9 MB/s (r:0, l:None, u:None) +[ OK ] (10/12) StreamMultiSysTest /eec1c676 @daint:gpu+nvidia +P: Copy: 51632.6 MB/s (r:0, l:None, u:None) +P: Scale: 39659.7 MB/s (r:0, l:None, u:None) +P: Add: 44080.3 MB/s (r:0, l:None, u:None) +P: Triad: 44415.9 MB/s (r:0, l:None, u:None) +[ OK ] (11/12) StreamMultiSysTest /eec1c676 @daint:gpu+gnu +P: Copy: 42038.6 MB/s (r:0, l:None, u:None) +P: Scale: 37506.9 MB/s (r:0, l:None, u:None) +P: Add: 42947.6 MB/s (r:0, l:None, u:None) +P: Triad: 43664.9 MB/s (r:0, l:None, u:None) [ OK ] (12/12) StreamMultiSysTest /eec1c676 @daint:gpu+cray -P: Copy: 51184.2 MB/s (r:0, l:None, u:None) -P: Scale: 39397.4 MB/s (r:0, l:None, u:None) -P: Add: 43648.0 MB/s (r:0, l:None, u:None) -P: Triad: 43898.2 MB/s (r:0, l:None, u:None) +P: Copy: 50960.7 MB/s (r:0, l:None, u:None) +P: Scale: 38794.0 MB/s (r:0, l:None, u:None) +P: Add: 43296.1 MB/s (r:0, l:None, u:None) +P: Triad: 42881.1 MB/s (r:0, l:None, u:None) [----------] all spawned checks have finished [ PASSED ] Ran 12/12 test case(s) from 1 check(s) (0 failure(s), 0 skipped) -[==========] Finished on Fri Oct 7 11:25:31 2022 +[==========] Finished on Fri Oct 7 12:42:04 2022 ================================================================================ PERFORMANCE REPORT -------------------------------------------------------------------------------- [StreamMultiSysTest /eec1c676 @daint:login:gnu] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 10 + num_tasks: 1 performance: - - Copy: 90564.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 69209.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 74898.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 74036.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 92708.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 68575.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 76050.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 78071.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:login:intel] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 10 + num_tasks: 1 performance: - - Copy: 83611.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 72885.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 79780.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 99212.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 87982.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 67941.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 48635.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 77366.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:login:nvidia] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 10 + num_tasks: 1 performance: - - Copy: 98383.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 70538.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 79402.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 79138.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 97052.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 69147.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 76828.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 75792.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:login:cray] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 10 + num_tasks: 1 performance: - - Copy: 63243.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 49733.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 40884.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 56149.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 83067.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 69435.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 77441.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 76907.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:gpu:gnu] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 12 + num_tasks: 1 performance: - - Copy: 42724.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 38443.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 43619.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 43258.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 42038.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 37506.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 42947.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 43664.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:gpu:intel] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 12 + num_tasks: 1 performance: - - Copy: 52316.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 54141.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 57550.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 57150.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 52810.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 54267.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 57985.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 57398.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:gpu:nvidia] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 12 + num_tasks: 1 performance: - - Copy: 51687.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 39685.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 44116.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 44475.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 51632.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 39659.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 44080.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 44415.9 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:gpu:cray] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 12 + num_tasks: 1 performance: - - Copy: 51184.2 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 39397.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 43648.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 43898.2 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 50960.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 38794.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 43296.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 42881.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:mc:gnu] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 36 + num_tasks: 1 performance: - - Copy: 48686.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 38562.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 43707.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 44041.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 48802.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 38805.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 43816.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 44180.1 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:mc:intel] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 36 + num_tasks: 1 performance: - - Copy: 52240.0 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 49426.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 56988.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 56457.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 52603.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 49793.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 57158.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 56795.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:mc:nvidia] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 36 + num_tasks: 1 performance: - - Copy: 46798.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 40481.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 44143.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 44570.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 47397.3 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 40625.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 44391.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 44786.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) [StreamMultiSysTest /eec1c676 @daint:mc:cray] - num_tasks: 1 num_gpus_per_node: 0 num_cpus_per_task: 36 + num_tasks: 1 performance: - - Copy: 47068.4 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Scale: 40086.2 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Add: 43688.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) - - Triad: 44106.8 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Copy: 51607.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Scale: 44579.5 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Add: 48547.6 MB/s (r: 0 MB/s l: -inf% u: +inf%) + - Triad: 49056.7 MB/s (r: 0 MB/s l: -inf% u: +inf%) -------------------------------------------------------------------------------- -Run report saved in '/home/user/.reframe/reports/run-report-71.json' -Log file(s) saved in '/tmp/rfm-c9f_ne8m.log' +Run report saved in '/home/user/.reframe/reports/run-report-75.json' +Log file(s) saved in '/tmp/rfm-k4x8yojn.log' From eea196832beda9e07ac73f25025a6f48671e542a Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Sat, 8 Oct 2022 10:03:11 +0200 Subject: [PATCH 25/42] Fix typo --- docs/manpage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manpage.rst b/docs/manpage.rst index c290e8eb8e..1cdf60cc54 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -784,7 +784,7 @@ Miscellaneous options This option can also be set using the :envvar:`RFM_CONFIG_FILE` environment variable. ReFrame first loads the builtin config unconditionally and then starts to look for configs in the :envvar:`RFM_CONFIG_PATH` and starts chaining them. - :envvar:`RFM_CONFIG_PATH` containe directories where a file named ``setting.py`` or ``setting.json`` is. + :envvar:`RFM_CONFIG_PATH` contains directories where a file named ``setting.py`` or ``setting.json`` is. If both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. Then accumulates the configs of the command line option, potentially replacing completely those from the :envvar:`RFM_CONFIG_PATH`. From a2e9e8e242b926e6a73d4394458ac11556df20af Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Sat, 8 Oct 2022 18:09:51 +0200 Subject: [PATCH 26/42] Use RFM_CONFIG_FILES and update docs --- docs/configure.rst | 2 +- docs/manpage.rst | 56 +++++++++++++++++++++++++++++++------ docs/tutorial_basics.rst | 9 ++++-- reframe/core/config.py | 2 +- reframe/frontend/cli.py | 19 +++++++++++-- unittests/test_argparser.py | 2 +- 6 files changed, 73 insertions(+), 17 deletions(-) diff --git a/docs/configure.rst b/docs/configure.rst index 44dcd4908f..6f6a3ff0db 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -33,7 +33,7 @@ This contains everything that ReFrame needs to run on a generic system, as well ReFrame continues on looking for configuration files in the directories defined in :envvar:`RFM_CONFIG_PATH`. For each directory, will look within it for a ``settings.py`` or ``settings.json`` file (in that order), and if it finds one, it will load it. -Finally, ReFrame processes the :option:`--config-file` option or the :envvar:`RFM_CONFIG_FILE` to load any specific configuration files passed from the command line. +Finally, ReFrame processes the :option:`--config-file` option or the :envvar:`RFM_CONFIG_FILES` environment variable to load any specific configuration files passed from the command line. Anatomy of the Configuration File diff --git a/docs/manpage.rst b/docs/manpage.rst index 1cdf60cc54..6f3f0f6edb 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -775,18 +775,23 @@ It does so by leveraging the selected system's environment modules system. Miscellaneous options --------------------- -.. option:: -C --config-file=FILE +.. option:: -C, --config-file=FILE Use ``FILE`` as configuration file for ReFrame. - The user can pass multiple configuration files that will be added on top of the ``${RFM_INSTALL_PREFIX}/reframe/core/settings.py``. - To ignore previous configuration files you need to pass ``-C :new_config.py`` - This option can also be set using the :envvar:`RFM_CONFIG_FILE` environment variable. + This option can be passed multiple times, in which case multiple configuration files will be read and loaded successively. + The base of the configuration chain is always the builtin configuration file, namely the ``${RFM_INSTALL_PREFIX}/reframe/core/settings.py``. + At any point, the user can "break" the chain of configuration files by prefixing the configuration file name with a colon as in the following example: ``-C :/path/to/new_config.py``. + This will ignore any previously loaded configuration file and will only load the one specified. + Note, however, that the builtin configuration file cannot be overriden; + It will always be loaded first in the chain. - ReFrame first loads the builtin config unconditionally and then starts to look for configs in the :envvar:`RFM_CONFIG_PATH` and starts chaining them. - :envvar:`RFM_CONFIG_PATH` contains directories where a file named ``setting.py`` or ``setting.json`` is. - If both ``settings.py`` and ``settings.json`` are found, the Python file is preferred. - Then accumulates the configs of the command line option, potentially replacing completely those from the :envvar:`RFM_CONFIG_PATH`. + This option can also be set using the :envvar:`RFM_CONFIG_FILES` environment variable. + + In order to determine its final configuration, ReFrame first loads the builtin configuration file unconditionally and then starts looking for configuration files in the :envvar:`RFM_CONFIG_PATH`. + For each directory in the :envvar:`RFM_CONFIG_PATH`, ReFrame looks for files named ``setting.py`` or ``setting.json`` and loads them. + If both a ``settings.py`` and a ``settings.json`` file are found, the Python configuration will be preferred. + ReFrame, finally, processes any configuration files specified in the command line or in the :envvar:`RFM_CONFIG_FILES` environment variable. .. versionchanged:: 4.0.0 @@ -1181,6 +1186,41 @@ Here is an alphabetical list of the environment variables recognized by ReFrame: Associated configuration parameter N/A ================================== ================== + .. deprecated:: 4.0.0 + Please use the :envvar:`RFM_CONFIG_FILES` instead. + + +.. envvar:: RFM_CONFIG_FILES + + A colon-separated list of configuration files to load. + Refer to the documentation of the :option:`--config-file` option for a detailed description on how ReFrame loads its configuration. + + + .. table:: + :align: left + + ================================== ================== + Associated command line option :option:`-C` + Associated configuration parameter N/A + ================================== ================== + + .. versionadded:: 4.0.0 + +.. envvar:: RFM_CONFIG_PATH + + A colon-separated list of directories that contain ReFrame configuration files. + Refer to the documentation of the :option:`--config-file` option for a detailed description on how ReFrame loads its configuration. + + .. table:: + :align: left + + ================================== ================== + Associated command line option N/A + Associated configuration parameter N/A + ================================== ================== + + .. versionadded:: 4.0.0 + .. envvar:: RFM_GIT_TIMEOUT diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index 9feb0986d8..76c1531fd0 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -262,11 +262,14 @@ Let's now rerun our "Hello, World!" tests: Notice how the same tests are now tried with both the ``gnu`` and ``clang`` programming environments, without having to touch them at all! That's one of the powerful features of ReFrame and we shall see later on, how easily we can port our tests to an HPC cluster with minimal changes. In order to instruct ReFrame to use our configuration file, we use the ``-C`` command line option. -Since we don't want to type it throughout the tutorial, we will now set it in the environment: +Since we don't want to type it throughout the tutorial, we could set the :envvar:`RFM_CONFIG_PATH` environment variable, which sets the path where ReFrame will look for configuration files. .. code-block:: console - export RFM_CONFIG_PATH=$(pwd)/tutorials/config=$(pwd)/tutorials/config + export RFM_CONFIG_PATH=$(pwd)/tutorials/config + + +Alternatively, we could have set the :envvar:`RFM_CONFIG_FILES` environment variable which takes a list of the configuration files to load. A Multithreaded "Hello, World!" @@ -652,7 +655,7 @@ We will only do so with the final versions of the tests from the previous sectio .. code-block:: console - export RFM_CONFIG_FILE=$(pwd)/tutorials/config/settings.py + export RFM_CONFIG_PATH=$(pwd)/tutorials/config ./bin/reframe -c tutorials/basics/ -R -n 'HelloMultiLangTest|HelloThreadedExtended2Test|StreamWithRefTest' --performance-report -r .. literalinclude:: listings/alltests_daint.txt diff --git a/reframe/core/config.py b/reframe/core/config.py index e10afa933e..ed2dcb5854 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -455,7 +455,7 @@ def find_config_files(config_path=None, config_file=None): if config_file: for f in config_file: - # If the user sets RFM_CONFIG_FILE=:conf1:conf2 the list will + # If the user sets RFM_CONFIG_FILES=:conf1:conf2 the list will # include one empty string in the beginning if f == '': res = [] diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 190f30a5a9..152b0ffb8b 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -503,9 +503,9 @@ def main(): # Miscellaneous options misc_options.add_argument( '-C', '--config-file', action='append', metavar='FILE', - dest='config_file', + dest='config_files', help='Set configuration file', - envvar='RFM_CONFIG_FILE :' + envvar='RFM_CONFIG_FILES :' ) misc_options.add_argument( '--detect-host-topology', action='store', nargs='?', const='-', @@ -708,9 +708,22 @@ def restrict_logging(): # Now configure ReFrame according to the user configuration file try: + # Issue a deprecation warning if the old `RFM_CONFIG_FILE` is used + config_file = os.getenv('RFM_CONFIG_FILE') + if config_file is not None: + printer.warning('RFM_CONFIG_FILE is deprecated; ' + 'please use RFM_CONFIG_FILES instead') + if os.getenv('RFM_CONFIG_FILES'): + printer.warning( + 'both RFM_CONFIG_FILE and RFM_CONFIG_FILES are specified; ' + 'the former will be ignored' + ) + else: + os.environ['RFM_CONFIG_FILES'] = config_file + printer.debug('Loading user configuration') conf_files = config.find_config_files( - options.config_path, options.config_file + options.config_path, options.config_files ) site_config = config.load_config(*conf_files) site_config.validate() diff --git a/unittests/test_argparser.py b/unittests/test_argparser.py index 032490a04a..4e5518f9d9 100644 --- a/unittests/test_argparser.py +++ b/unittests/test_argparser.py @@ -120,7 +120,7 @@ def extended_parser(): envvar='RFM_TIMESTAMP_DIRS', configvar='general/timestamp_dirs' ) foo_options.add_argument( - '-C', '--config-file', action='store', envvar='RFM_CONFIG_FILE' + '-C', '--config-file', action='store', envvar='RFM_CONFIG_FILES' ) foo_options.add_argument( '--check-path', action='append', envvar='RFM_CHECK_SEARCH_PATH :' From 22420c5dc3fa7e52d5e5dbf7bca97cf71a0aa5b8 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Sat, 8 Oct 2022 21:58:48 +0200 Subject: [PATCH 27/42] Update tutorial --- docs/configure.rst | 4 ++-- docs/tutorial_basics.rst | 7 ++----- reframe/core/settings.py | 2 ++ tutorials/config/settings.py | 38 ------------------------------------ 4 files changed, 6 insertions(+), 45 deletions(-) diff --git a/docs/configure.rst b/docs/configure.rst index 6f6a3ff0db..7de96f2873 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -153,9 +153,9 @@ Logging configuration ReFrame has a powerful logging mechanism that gives fine grained control over what information is being logged, where it is being logged and how this information is formatted. Additionally, it allows for logging performance data from performance tests into different channels. -Let's see how logging is defined in our example configuration, which also represents a typical one for logging: +Let's see how logging is defined in the builtin configuration: -.. literalinclude:: ../tutorials/config/settings.py +.. literalinclude:: ../reframe/core/settings.py :start-after: # rfmdocstart: logging :end-before: # rfmdocend: logging diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index 76c1531fd0..acfd53e68b 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -210,16 +210,13 @@ In this case, the stage directory contains only the "Hello, World" source files, Let's go on and fix this failure by defining a new system and programming environments for the machine we are running on. -We start off by copying the generic configuration file that ReFrame uses. -Note that you should *not* edit this configuration file in place. .. code-block:: console - cp reframe/core/settings.py tutorials/config/mysettings.py - + vi tutorials/config/mysettings.py .. note:: - You may also use edit directly the supplied ``tutorials/config/settings.py`` file, which is the actual configuration file against which the various tutorials have been evaluated. + You may also edit directly the supplied ``tutorials/config/settings.py`` file, which is the actual configuration file against which the various tutorials have been evaluated. Here is how the new configuration file looks like with the needed additions highlighted: diff --git a/reframe/core/settings.py b/reframe/core/settings.py index 341e3e32e4..0a50215c64 100644 --- a/reframe/core/settings.py +++ b/reframe/core/settings.py @@ -31,6 +31,7 @@ 'ftn': '' }, ], + # rfmdocstart: logging 'logging': [ { 'handlers': [ @@ -66,4 +67,5 @@ ] } ], + # rfmdocend: logging } diff --git a/tutorials/config/settings.py b/tutorials/config/settings.py index 4ae5113935..ba34324b0d 100644 --- a/tutorials/config/settings.py +++ b/tutorials/config/settings.py @@ -174,43 +174,5 @@ } ], # rfmdocend: environments - # rfmdocstart: logging - 'logging': [ - { - 'level': 'debug', - 'handlers': [ - { - 'type': 'stream', - 'name': 'stdout', - 'level': 'info', - 'format': '%(message)s' - }, - { - 'type': 'file', - 'level': 'debug', - 'format': '[%(asctime)s] %(levelname)s: %(check_info)s: %(message)s', # noqa: E501 - 'append': False - } - ], - 'handlers_perflog': [ - { - 'type': 'filelog', - 'prefix': '%(check_system)s/%(check_partition)s', - 'level': 'info', - 'format': ( - '%(check_job_completion_time)s|reframe %(version)s|' - '%(check_info)s|jobid=%(check_jobid)s|' - '%(check_perf_var)s=%(check_perf_value)s|' - 'ref=%(check_perf_ref)s ' - '(l=%(check_perf_lower_thres)s, ' - 'u=%(check_perf_upper_thres)s)|' - '%(check_perf_unit)s' - ), - 'append': True - } - ] - } - ], - # rfmdocend: logging } # rfmdocend: site-configuration From 4c6756a4283d6479fecae0ff18c3cc6b4e843ba6 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Sun, 9 Oct 2022 22:04:12 +0200 Subject: [PATCH 28/42] Add unit tests to expose corner cases --- unittests/test_config.py | 98 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/unittests/test_config.py b/unittests/test_config.py index 720f812ec2..27e7adc6ab 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -17,7 +17,8 @@ def generate_partial_configs(tmp_path): part1 = tmp_path / 'settings-part1.py' part2 = tmp_path / 'settings-part2.py' part3 = tmp_path / 'settings-part3.py' - mod = util.import_module_from_file('unittests/resources/config/settings.py') + mod = util.import_module_from_file( + 'unittests/resources/config/settings.py') full_config = mod.site_configuration config_1 = { @@ -341,6 +342,101 @@ def test_sticky_options(site_config): assert site_config.get('environments/@PrgEnv-cray/cc') == 'cc' +@pytest.fixture +def write_config(tmp_path): + def _write_config(config): + filename = (tmp_path / 'settings.json') + filename.touch() + with open(filename, 'w') as fp: + json.dump(config, fp) + + return str(filename) + + return _write_config + + +def test_multi_config_redefine_system(write_config): + config_file = write_config({ + 'systems': [ + { + 'name': 'generic', + 'hostnames': ['foo'], + 'partitions': [ + { + 'name': 'local', + 'scheduler': 'local', + 'launcher': 'mpirun', + 'environs': ['builtin'] + } + ] + } + ] + }) + with pytest.raises( + ConfigError, + match=f"'generic' system is already defined in ''" + ): + site_config = config.load_config(config_file) + + +def test_multi_config_redefine_environment(write_config): + config_file = write_config({ + 'environments': [ + { + 'name': 'builtin', + 'cc': 'gcc' + } + ] + }) + with pytest.raises( + ConfigError, + match=f"'builtin' environment is already defined in ''" + ): + site_config = config.load_config(config_file) + + +def test_multi_config_combine_general_options(write_config): + config_file = write_config({ + 'general': [ + { + 'pipeline_timeout': 10, + 'target_systems': ['testsys:login'] + }, + { + 'colorize': False + } + ] + }) + site_config = config.load_config('unittests/resources/config/settings.py', + config_file) + site_config.validate() + site_config.select_subconfig('testsys:login') + assert site_config.get('general/0/check_search_path') == ['a:b'] + assert site_config.get('general/0/pipeline_timeout') == 10 + assert site_config.get('general/0/colorize') == False + + +# FIXME: Adapt this to the new syntax of logging config. +def _test_multi_config_combine_logging_options(write_config): + config_file = write_config({ + 'logging': [{ + 'level': 'debug', + 'handlers': [ + { + 'type': 'file', + 'level': 'info', + 'format': '%(message)s' + } + ], + }] + }) + site_config = config.load_config(config_file) + site_config.validate() + site_config.select_subconfig('generic') + assert site_config.get('logging/0/level') == 'debug' + assert len(site_config.get('logging/0/handlers')) == 3 + + def test_system_create(site_config): site_config.select_subconfig('testsys:gpu') system = System.create(site_config) From 034b86768c35481863cf8a9ee33ea6407586bea8 Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 21 Oct 2022 14:47:18 +0200 Subject: [PATCH 29/42] Validate system and partition names are unique --- reframe/core/config.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/reframe/core/config.py b/reframe/core/config.py index e10afa933e..623cae3814 100644 --- a/reframe/core/config.py +++ b/reframe/core/config.py @@ -332,6 +332,25 @@ def validate(self): raise ConfigError(f"could not validate configuration files: " f"'{self._sources}'") from e + # Make sure that system and partition names are unique + system_names = set() + for system in self._site_config['systems']: + sysname = system['name'] + if sysname in system_names: + raise ConfigError(f"system '{sysname}' already defined") + + system_names.add(sysname) + partition_names = set() + for part in system['partitions']: + partname = part['name'] + if partname in partition_names: + raise ConfigError( + f"partition '{partname}' already defined " + f"for system '{sysname}'" + ) + + partition_names.add(partname) + def select_subconfig(self, system_fullname=None, ignore_resolve_errors=False): # First look for the current subconfig in the cache; if not found, From 2ecea039bdbc3eba0db85cac7eec74f9ff16057c Mon Sep 17 00:00:00 2001 From: Eirini Koutsaniti Date: Fri, 21 Oct 2022 14:51:06 +0200 Subject: [PATCH 30/42] Fix unittests --- unittests/resources/config/settings.py | 2 +- unittests/test_autodetect.py | 2 +- unittests/test_config.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/unittests/resources/config/settings.py b/unittests/resources/config/settings.py index 8ded35dc48..f79b2ec385 100644 --- a/unittests/resources/config/settings.py +++ b/unittests/resources/config/settings.py @@ -10,7 +10,7 @@ site_configuration = { 'systems': [ { - 'name': 'generic', + 'name': 'generic1', 'descr': 'Generic example system', 'hostnames': ['.*'], 'partitions': [ diff --git a/unittests/test_autodetect.py b/unittests/test_autodetect.py index f961a77f68..d36cf6de64 100644 --- a/unittests/test_autodetect.py +++ b/unittests/test_autodetect.py @@ -20,7 +20,7 @@ def temp_topo(tmp_path, monkeypatch): monkeypatch.setattr(autodetect, '_TREAT_WARNINGS_AS_ERRORS', True) # Create a devices file manually, since it is not auto-generated - meta_prefix = tmp_path / '.reframe' / 'topology' / 'generic-default' + meta_prefix = tmp_path / '.reframe' / 'topology' / 'generic1-default' os.makedirs(meta_prefix) with open(meta_prefix / 'devices.json', 'w') as fp: json.dump([ diff --git a/unittests/test_config.py b/unittests/test_config.py index 720f812ec2..a104f9fbf4 100644 --- a/unittests/test_config.py +++ b/unittests/test_config.py @@ -121,7 +121,7 @@ def test_load_config_unknown_filetype(tmp_path): def test_validate_fallback_config(): - site_config = config.load_config('reframe/core/settings.py') + site_config = config.load_config() site_config.validate() From 5ea6b7a61c9109e5380e15da75c3b2f367743906 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Sat, 5 Nov 2022 21:51:14 +0100 Subject: [PATCH 31/42] Enhance how multiple configuration files are handled - We warn on system, partition and environment redefinitions - All sections with unnamed objects are merged and resolved based on the selected system. As a result, this sections can be combined arbitrarily through as the chain of configuration files is loaded and the resulting internal config will always has a single such object, so that it is guaranteed that calls, such as `get('general/0/