ReFrame 3.4 (rev: 08e45881)
Source code for reframe.core.containers
# Copyright 2016-2021 Swiss National Supercomputing Centre (CSCS/ETH Zurich)
# ReFrame Project Developers. See the top-level LICENSE file for details.
#
# SPDX-License-Identifier: BSD-3-Clause
import abc
import reframe.core.fields as fields
import reframe.utility.typecheck as typ
from reframe.core.exceptions import ContainerError
[docs]class Docker(ContainerPlatform):
'''Container platform backend for running containers with `Docker
<https://www.docker.com/>`__.'''
def emit_prepare_commands(self):
return []
def launch_command(self):
super().launch_command()
run_opts = ['-v "%s":"%s"' % mp for mp in self.mount_points]
run_opts += self.options
run_cmd = 'docker run --rm %s %s bash -c ' % (' '.join(run_opts),
self.image)
return run_cmd + "'" + '; '.join(
['cd ' + self.workdir] + self.commands) + "'"
[docs]class Sarus(ContainerPlatform):
'''Container platform backend for running containers with `Sarus
<https://sarus.readthedocs.io>`__.'''
#: Enable MPI support when launching the container.
#:
#: :type: boolean
#: :default: :class:`False`
with_mpi = fields.TypedField(bool)
def __init__(self):
super().__init__()
self.with_mpi = False
self._command = 'sarus'
def emit_prepare_commands(self):
# The format that Sarus uses to call the images is
# <reposerver>/<user>/<image>:<tag>. If an image was loaded
# locally from a tar file, the <reposerver> is 'load'.
if self.image.startswith('load/'):
return []
return [self._command + ' pull %s' % self.image]
def launch_command(self):
super().launch_command()
run_opts = ['--mount=type=bind,source="%s",destination="%s"' %
mp for mp in self.mount_points]
if self.with_mpi:
run_opts.append('--mpi')
run_opts += self.options
run_cmd = self._command + ' run %s %s bash -c ' % (' '.join(run_opts),
self.image)
return run_cmd + "'" + '; '.join(
['cd ' + self.workdir] + self.commands) + "'"
[docs]class Shifter(Sarus):
'''Container platform backend for running containers with `Shifter
<https://www.nersc.gov/research-and-development/user-defined-images/>`__.
'''
def __init__(self):
super().__init__()
self._command = 'shifter'
[docs]class Singularity(ContainerPlatform):
'''Container platform backend for running containers with `Singularity
<https://sylabs.io/>`__.'''
#: Enable CUDA support when launching the container.
#:
#: :type: boolean
#: :default: :class:`False`
with_cuda = fields.TypedField(bool)
def __init__(self):
super().__init__()
self.with_cuda = False
def emit_prepare_commands(self):
return []
def launch_command(self):
super().launch_command()
run_opts = ['-B"%s:%s"' % mp for mp in self.mount_points]
if self.with_cuda:
run_opts.append('--nv')
run_opts += self.options
run_cmd = 'singularity exec %s %s bash -c ' % (' '.join(run_opts),
self.image)
return run_cmd + "'" + '; '.join(
['cd ' + self.workdir] + self.commands) + "'"
class ContainerPlatformField(fields.TypedField):
def __init__(self, *other_types):
super().__init__(ContainerPlatform, *other_types)
def __set__(self, obj, value):
if isinstance(value, str):
try:
value = globals()[value]()
except KeyError:
raise ValueError(
'unknown container platform: %s' % value) from None
super().__set__(obj, value)