diff --git a/docs/configure.rst b/docs/configure.rst index 304b711958..72d5af85e9 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -315,3 +315,18 @@ If this cannot be found the hostname will be obtained from the standard ``hostna The detection process stops at the first match found, and the system it belongs to is considered as the current system. If the system cannot be auto-detected, ReFrame will fail with an error message. You can override completely the auto-detection process by specifying a system or a system partition with the ``--system`` option (e.g., ``--system daint`` or ``--system daint:gpu``). + + +Showing configuration +--------------------- + +.. versionadded:: 2.16 + +It is possible to ask ReFrame to print the configuration of the current system or the configuration of any programming environment defined for the current system. +There are two command-line options for performing these operations: + +* ``--show-config``: This option shows the current system's configuration and exits. + It can be combined with the ``--system`` option in order to show the configuration of another system. +* ``--show-config-env ENV``: This option shows the configuration of the programming environment ``ENV`` and exits. + The environment ``ENV`` must be defined for any of the partitions of the current system. + This option can also be combined with ``--system`` in order to show the configuration of a programming environment defined for another system. diff --git a/reframe/core/environments.py b/reframe/core/environments.py index 1b3a862d98..04a5c5c037 100644 --- a/reframe/core/environments.py +++ b/reframe/core/environments.py @@ -161,7 +161,21 @@ def __eq__(self, other): set(self._modules) == set(other._modules) and self._variables == other._variables) + def details(self): + """Return a detailed description of this environment.""" + variables = '\n'.join(' '*8 + '- %s=%s' % (k, v) + for k, v in self.variables.items()) + lines = [ + self._name + ':', + ' modules: ' + ', '.join(self.modules), + ' variables:' + ('\n' if variables else '') + variables + ] + return '\n'.join(lines) + def __str__(self): + return self.name + + def __repr__(self): ret = "{0}(name='{1}', modules={2}, variables={3})" return ret.format(type(self).__name__, self.name, self.modules, self.variables) diff --git a/reframe/core/runtime.py b/reframe/core/runtime.py index 13406bbd70..27c700e64a 100644 --- a/reframe/core/runtime.py +++ b/reframe/core/runtime.py @@ -70,7 +70,16 @@ def partition(self, name): return None def __str__(self): - return str(self._system) + partitions = '\n'.join(re.sub('(?m)^', 6*' ', '- ' + str(p)) + for p in self.partitions) + lines = [ + '%s [%s]:' % (self._name, self._descr), + ' hostnames: ' + ', '.join(self._hostnames), + ' modules_system: ' + str(self._modules_system), + ' resourcesdir: ' + self._resourcesdir, + ' partitions:\n' + partitions, + ] + return '\n'.join(lines) def __repr__(self): return 'HostSystem(%r, %r)' % (self._system, self._partname) @@ -93,13 +102,13 @@ class HostResources: #: prefix = fields.AbsolutePathField('prefix') outputdir = fields.AbsolutePathField('outputdir', type(None)) - stagedir = fields.AbsolutePathField('stagedir', type(None)) + stagedir = fields.AbsolutePathField('stagedir', type(None)) perflogdir = fields.AbsolutePathField('perflogdir', type(None)) def __init__(self, prefix=None, stagedir=None, outputdir=None, perflogdir=None, timefmt=None): self.prefix = prefix or '.' - self.stagedir = stagedir + self.stagedir = stagedir self.outputdir = outputdir self.perflogdir = perflogdir self.timefmt = timefmt @@ -251,6 +260,10 @@ def modules_system(self): """ return self._modules_system + def show_config(self): + """Return a textual representation of the current runtime.""" + return str(self._system) + # Global resources for the current host _runtime_context = None diff --git a/reframe/core/systems.py b/reframe/core/systems.py index ea663f0f7c..969c9d1319 100644 --- a/reframe/core/systems.py +++ b/reframe/core/systems.py @@ -1,3 +1,5 @@ +import re + import reframe.core.debug as debug import reframe.core.fields as fields import reframe.utility.typecheck as typ @@ -136,7 +138,17 @@ def __eq__(self, other): self._local_env == other._local_env) def __str__(self): - return self._name + local_env = re.sub('(?m)^', 6*' ', ' - ' + self._local_env.details()) + lines = [ + '%s [%s]:' % (self._name, self._descr), + ' fullname: ' + self.fullname, + ' scheduler: ' + self._scheduler.registered_name, + ' launcher: ' + self._launcher.registered_name, + ' access: ' + ' '.join(self._access), + ' local_env:\n' + local_env, + ' environs: ' + ', '.join(str(e) for e in self._environs) + ] + return '\n'.join(lines) def __repr__(self): return debug.repr(self) @@ -247,7 +259,3 @@ def __eq__(self, other): def __repr__(self): return debug.repr(self) - - def __str__(self): - return '%s (partitions: %s)' % (self._name, - [str(p) for p in self._partitions]) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 2d56c2d619..dd3da0205a 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -1,5 +1,6 @@ import os import inspect +import json import socket import sys @@ -217,6 +218,12 @@ def main(): help='Specify a custom config-file for the machine. ' '(default: %s' % os.path.join(reframe.INSTALL_PREFIX, 'reframe/settings.py')) + misc_options.add_argument( + '--show-config', action='store_true', + help='Print configuration of the current system and exit') + misc_options.add_argument( + '--show-config-env', action='store', metavar='ENV', + help='Print configuration of environment ENV and exit') misc_options.add_argument('-V', '--version', action='version', version=reframe.VERSION) @@ -320,6 +327,25 @@ def main(): logging.LOG_CONFIG_OPTS['handlers.filelog.prefix'] = (rt.resources. perflog_prefix) + # Show configuration after everything is set up + if options.show_config: + printer.info(rt.show_config()) + sys.exit(0) + + if options.show_config_env: + envname = options.show_config_env + for p in rt.system.partitions: + env = p.environment(envname) + if env: + break + + if env is None: + printer.error('no such environment: ' + envname) + sys.exit(1) + + printer.info(env.details()) + sys.exit(0) + if hasattr(settings, 'perf_logging_config'): try: logging.configure_perflogging(settings.perf_logging_config) diff --git a/unittests/test_cli.py b/unittests/test_cli.py index 41691fea5b..21f9bb8537 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -360,3 +360,30 @@ def test_list_with_details(self): self.assertNotIn('Traceback', stdout) self.assertNotIn('Traceback', stderr) self.assertEqual(0, returncode) + + def test_show_config(self): + # Just make sure that this option does not make the frontend crash + self.more_options = ['--show-config'] + self.system = 'testsys' + returncode, stdout, stderr = self._run_reframe() + self.assertNotIn('Traceback', stdout) + self.assertNotIn('Traceback', stderr) + self.assertEqual(0, returncode) + + def test_show_env_config(self): + # Just make sure that this option does not make the frontend crash + self.more_options = ['--show-config-env', 'PrgEnv-gnu'] + self.system = 'testsys' + returncode, stdout, stderr = self._run_reframe() + self.assertNotIn('Traceback', stdout) + self.assertNotIn('Traceback', stderr) + self.assertEqual(0, returncode) + + def test_show_env_config_unknown_env(self): + # Just make sure that this option does not make the frontend crash + self.more_options = ['--show-config-env', 'foobar'] + self.system = 'testsys' + returncode, stdout, stderr = self._run_reframe() + self.assertNotIn('Traceback', stdout) + self.assertNotIn('Traceback', stderr) + self.assertEqual(1, returncode)