import re
import reframe.core.debug as debug
import reframe.core.fields as fields
import reframe.utility as utility
import reframe.utility.typecheck as typ
from reframe.core.environments import Environment
[docs]class SystemPartition:
'''A representation of a system partition inside ReFrame.
This class is immutable.
'''
_name = fields.TypedField('_name', typ.Str[r'(\w|-)+'])
_descr = fields.TypedField('_descr', str)
_access = fields.TypedField('_access', typ.List[str])
_environs = fields.TypedField('_environs', typ.List[Environment])
_resources = fields.TypedField('_resources', typ.Dict[str, typ.List[str]])
_local_env = fields.TypedField('_local_env', Environment, type(None))
_container_environs = fields.TypedField('_container_environs',
typ.Dict[str, Environment])
# maximum concurrent jobs
_max_jobs = fields.TypedField('_max_jobs', int)
def __init__(self, name, descr=None, scheduler=None, launcher=None,
access=[], environs=[], resources={}, local_env=None,
max_jobs=1):
self._name = name
self._descr = descr or name
self._scheduler = scheduler
self._launcher = launcher
self._access = list(access)
self._environs = list(environs)
self._resources = dict(resources)
self._max_jobs = max_jobs
self._local_env = local_env
self._container_environs = {}
# Parent system
self._system = None
@property
def access(self):
return utility.SequenceView(self._access)
@property
def descr(self):
'''A detailed description of this partition.'''
return self._descr
@property
def environs(self):
return utility.SequenceView(self._environs)
@property
def container_environs(self):
return utility.MappingView(self._container_environs)
@property
def fullname(self):
'''Return the fully-qualified name of this partition.
The fully-qualified name is of the form
``<parent-system-name>:<partition-name>``.
:type: `str`
'''
if self._system is None:
return self._name
else:
return '%s:%s' % (self._system.name, self._name)
@property
def local_env(self):
return self._local_env
@property
def max_jobs(self):
return self._max_jobs
@property
def name(self):
'''The name of this partition.
:type: `str`
'''
return self._name
@property
def resources(self):
return utility.MappingView(self._resources)
@property
def scheduler(self):
'''The type of the backend scheduler of this partition.
:returns: a subclass of :class:`reframe.core.schedulers.Job`.
.. note::
.. versionchanged:: 2.8
Prior versions returned a string representing the scheduler and job
launcher combination.
'''
return self._scheduler
@property
def launcher(self):
'''The type of the backend launcher of this partition.
:returns: a subclass of :class:`reframe.core.launchers.JobLauncher`.
.. note::
.. versionadded:: 2.8
'''
return self._launcher
def add_container_env(self, env_name, environ):
self._container_environs[env_name] = environ
# Instantiate managed resource `name` with `value`.
def get_resource(self, name, **values):
ret = []
for r in self._resources.get(name, []):
try:
ret.append(r.format(**values))
except KeyError:
pass
return ret
def environment(self, name):
for e in self._environs:
if e.name == name:
return e
return None
def __eq__(self, other):
if not isinstance(other, type(self)):
return NotImplemented
return (self._name == other.name and
self._scheduler == other._scheduler and
self._launcher == other._launcher and
self._access == other._access and
self._environs == other._environs and
self._resources == other._resources and
self._local_env == other._local_env)
def __str__(self):
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)
[docs]class System:
'''A representation of a system inside ReFrame.'''
_name = fields.TypedField('_name', typ.Str[r'(\w|-)+'])
_descr = fields.TypedField('_descr', str)
_hostnames = fields.TypedField('_hostnames', typ.List[str])
_partitions = fields.TypedField('_partitions', typ.List[SystemPartition])
_modules_system = fields.TypedField('_modules_system',
typ.Str[r'(\w|-)+'], type(None))
_preload_env = fields.TypedField('_preload_env', Environment, type(None))
_prefix = fields.TypedField('_prefix', str)
_stagedir = fields.TypedField('_stagedir', str, type(None))
_outputdir = fields.TypedField('_outputdir', str, type(None))
_perflogdir = fields.TypedField('_perflogdir', str, type(None))
_resourcesdir = fields.TypedField('_resourcesdir', str)
def __init__(self, name, descr=None, hostnames=[], partitions=[],
preload_env=None, prefix='.', stagedir=None, outputdir=None,
perflogdir=None, resourcesdir='.', modules_system=None):
self._name = name
self._descr = descr or name
self._hostnames = list(hostnames)
self._partitions = list(partitions)
self._modules_system = modules_system
self._preload_env = preload_env
self._prefix = prefix
self._stagedir = stagedir
self._outputdir = outputdir
self._perflogdir = perflogdir
self._resourcesdir = resourcesdir
# Set parent system for the given partitions
for p in partitions:
p._system = self
@property
def name(self):
'''The name of this system.'''
return self._name
@property
def descr(self):
'''The description of this system.'''
return self._descr
@property
def hostnames(self):
'''The hostname patterns associated with this system.'''
return self._hostnames
@property
def modules_system(self):
'''The modules system name associated with this system.'''
return self._modules_system
@property
def preload_environ(self):
'''The environment to load whenever ReFrame runs on this system.
.. note::
.. versionadded:: 2.19
'''
return self._preload_env
@property
def prefix(self):
'''The ReFrame prefix associated with this system.'''
return self._prefix
@property
def stagedir(self):
'''The ReFrame stage directory prefix associated with this system.'''
return self._stagedir
@property
def outputdir(self):
'''The ReFrame output directory prefix associated with this system.'''
return self._outputdir
@property
def perflogdir(self):
'''The ReFrame log directory prefix associated with this system.'''
return self._perflogdir
@property
def resourcesdir(self):
'''Global resources directory for this system.
You may use this directory for storing large resource files of your
regression tests.
See `here <configure.html#system-configuration>`__ on how to configure
this.
:type: :class:`str`
'''
return self._resourcesdir
@property
def partitions(self):
'''All the system partitions associated with this system.'''
return utility.SequenceView(self._partitions)
def add_partition(self, partition):
partition._system = self
self._partitions.append(partition)
def __eq__(self, other):
if not isinstance(other, type(self)):
return NotImplemented
return (self._name == other._name and
self._hostnames == other._hostnames and
self._partitions == other._partitions)
def __repr__(self):
return debug.repr(self)