Skip to content

Commit

Permalink
Merge pull request #783 from ratt-ru/apptainer
Browse files Browse the repository at this point in the history
apptainer support init commit
  • Loading branch information
SpheMakh authored Jul 5, 2023
2 parents 136fc5e + c33f843 commit 7a1c2e9
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 62 deletions.
6 changes: 5 additions & 1 deletion Jenkinsfile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ cp -r $TEST_DATA_DIR/beams $TEST_OUTPUT_DIR/input/beams

# Load newer version of singularity
source /etc/profile.d/modules.sh
module load singularity/3.8.4

# TODO(Ben) Singularity seems to be broken; testing with apptainer
#module load singularity/3.8.4

module load apptainer/1.2.0-rc.1

# Check version
docker -v
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import glob

PACKAGE_NAME = "stimela"
__version__ = "1.7.8"
__version__ = "1.7.9"
build_root = os.path.dirname(__file__)


Expand Down
10 changes: 7 additions & 3 deletions stimela/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@
from logging import StreamHandler
import re
from pathlib import Path
import getpass
import time

try:
__version__ = pkg_resources.require("stimela")[0].version
except pkg_resources.DistributionNotFound:
__version__ = "dev"

# Get to know user
USER = os.environ["USER"]
UID = os.getuid()
GID = os.getgid()
try:
USER = getpass.getuser()
except:
# The point is to avoid containers with the same name when using there multiple users using docker
USER = hex(id(time.ctime()))
CAB_USERNAME = re.sub('[^0-9a-zA-Z]+', '_', USER).lower()

root = os.path.dirname(__file__)
Expand Down
1 change: 0 additions & 1 deletion stimela/cargo/cab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"mount": "/stimela_mount",
}

USER_HOME = os.environ["HOME"]

for item in list(__vol.keys()):
val = __vol[item]
Expand Down
2 changes: 1 addition & 1 deletion stimela/cargo/cab/casa_listobs/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@
"name": "cachesize"
}
]
}
}
12 changes: 8 additions & 4 deletions stimela/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@

BASE = stimela.BASE
CAB = stimela.CAB
USER = stimela.USER
UID = stimela.UID
GID = stimela.GID
GLOBALS = stimela.GLOBALS
CAB_USERNAME = stimela.CAB_USERNAME

Expand Down Expand Up @@ -230,6 +227,9 @@ def pull(argv):
add("-cb", "--cab-base", nargs="+",
help="Pull base image for specified cab")

add("-at", "--all-tags", action="store_true",
help="Pull all tags for this image")

add("-pf", "--pull-folder",
help="Images will be placed in this folder. Else, if the environmnental variable 'STIMELA_PULLFOLDER' is set, then images will be placed there. "
"Else, images will be placed in the current directory")
Expand Down Expand Up @@ -294,8 +294,12 @@ def pull(argv):
cabdir = "{:s}/{:s}".format(stimela.CAB_PATH, cab_)
_cab = info(cabdir, display=False)
tags = _cab.tag
if not isinstance(tags, list):
if isinstance(tags, list):
if not args.all_tags:
tags = [tags[-1]]
else:
tags = [tags]

for tag in tags:
base.append(f"{_cab.base}:{tag}")
repository_.append(param["hub"] if "hub" in param.keys() else args.repository)
Expand Down
2 changes: 1 addition & 1 deletion stimela/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ def setup_job(self, image, config,
cont.execdir = self.workdir
else:
cont.RUNSCRIPT = f"/{self.jtype}_run"
cont.add_environ('HOME', cont.IODEST["output"])

runscript = shutil.which("stimela_runscript")
if runscript:
Expand All @@ -349,7 +350,6 @@ def setup_job(self, image, config,
raise OSError

cont.add_environ('CONFIG', f'{cab.MOUNT}/configfile')
cont.add_environ('HOME', cont.IODEST["output"])
cont.add_environ('STIMELA_MOUNT', cab.MOUNT)

if msdir:
Expand Down
35 changes: 20 additions & 15 deletions stimela/singularity.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: future_fstrings -*-
import subprocess
import os
import sys
Expand All @@ -12,16 +11,20 @@
import hashlib
from shutil import which

binary = which("singularity")
if binary:
__version_string = subprocess.check_output([binary, "--version"]).decode("utf8")
version = __version_string.strip().split()[-1]
if version < "3.0.0":
suffix = ".img"
else:
suffix = ".sif"
else:
version = None

version = None

for item in ["apptainer", "singularity"]:
BINARY = which(item)
BINARY_NAME = item
if BINARY:
__version_string = subprocess.check_output([BINARY, "--version"]).decode("utf8")
version = __version_string.strip().split()[-1]
if BINARY_NAME == "singularity" and version < "3.0.0":
suffix = ".img"
else:
suffix = ".sif"
break

class SingularityError(Exception):
pass
Expand All @@ -41,7 +44,7 @@ def pull(image, name, docker=True, directory=".", force=False):
if os.path.exists(image_path) and not force:
stimela.logger().info(f"Singularity image already exists at '{image_path}'. To replace it, please re-run with the 'force' option")
else:
utils.xrun(f"cd {directory} && singularity", ["pull",
utils.xrun(f"cd {directory} && {BINARY}", ["pull",
"--force" if force else "", "--name",
name, fp])

Expand All @@ -55,7 +58,8 @@ def __init__(self, image, name,
runscript="/singularity",
environs=None,
workdir=None,
execdir="."):
execdir=".",
):
"""
Python wrapper to singularity tools for managing containers.
"""
Expand Down Expand Up @@ -95,7 +99,7 @@ def add_environ(self, key, value):
self.logger.debug("Adding environ varaible [{0}={1}] "\
"in container {2}".format(key, value, self.name))
self.environs.append("=".join([key, value]))
key_ = f"SINGULARITYENV_{key}"
key_ = f"{BINARY_NAME.upper()}ENV_{key}"

self.logger.debug(f"Setting singularity environmental variable {key_}={value} on host")
self._env[key_] = value
Expand All @@ -118,9 +122,10 @@ def run(self, *args, output_wrangler=None):
raise SystemExit from None

self.status = "running"
extras = "--userns" if BINARY_NAME == "singularity" else "--writable-tmpfs"
self._print("Starting container [{0:s}]. Timeout set to {1:d}. The container ID is printed below.".format(
self.name, self.time_out))
utils.xrun(f"cd {self.execdir} && singularity run --userns --workdir {self.execdir} --containall",
utils.xrun(f"{BINARY} run --workdir {self.execdir} --containall {extras}",
list(args) + [volumes, self.image, self.RUNSCRIPT],
log=self.logger, timeout=self.time_out, output_wrangler=output_wrangler,
env=self._env, logfile=self.logfile)
Expand Down
75 changes: 40 additions & 35 deletions stimela/tests/unit_tests/test-containertech.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ def setUpClass(cls):
global SINGULARITY, PODMAN
SINGULARITY = False
PODMAN = False
SINGULARITY = singularity.version and singularity.version >= "2.6.0"
if singularity.version:
if singularity.BINARY_NAME == "singularity":
SINGULARITY = singularity.version >= "2.6.0"
else:
SINGULARITY = True


@classmethod
def tearDownClass(cls):
Expand All @@ -55,40 +60,40 @@ def setUp(self):
if not os.path.isdir(INPUT):
os.mkdir(INPUT)

# def test_singularity(self):
# global MSDIR
# global INPUT
# global OUTPUT
# global SINGULARITY
#
# if SINGULARITY is False:
# return
#
# stimela.register_globals()
# rrr = stimela.Recipe("singularitypaths",
# ms_dir=MSDIR,
# JOB_TYPE="singularity",
# cabpath="cab/",
# singularity_image_dir=os.environ["STIMELA_PULLFOLDER"],
# log_dir="logs")
# rrr.add("cab/custom", "test1", {
# "bla1": "a", # only accepts a, b or c
# "bla5": ["testinput2.txt:input",
# "testinput3.txt:msfile",
# spf("{}hello\{reim\}.fits,{}to.fits,{}world.fits", "input", "msfile", "output")],
# }, input=INPUT, output=OUTPUT)
# rrr.run() #validate and run
#
# assert rrr.jobs[0].job._cab.parameters[4].value[0] == os.path.join(rrr.jobs[0].job.IODEST["input"],
# "testinput2.txt")
# assert rrr.jobs[0].job._cab.parameters[4].value[1] == os.path.join(rrr.jobs[0].job.IODEST["msfile"],
# "testinput3.txt")
# assert rrr.jobs[0].job._cab.parameters[4].value[2] == \
# "{}/hello{{reim}}.fits,{}/to.fits,{}/world.fits".format(
# rrr.jobs[0].job.IODEST["input"],
# rrr.jobs[0].job.IODEST["msfile"],
# rrr.jobs[0].job.IODEST["output"]
# )
def test_singularity(self):
global MSDIR
global INPUT
global OUTPUT
global SINGULARITY

if SINGULARITY is False:
return

stimela.register_globals()
rrr = stimela.Recipe("singularitypaths",
ms_dir=MSDIR,
JOB_TYPE="singularity",
cabpath="cab/",
singularity_image_dir=os.environ["STIMELA_PULLFOLDER"],
log_dir="logs")
rrr.add("cab/custom", "test1", {
"bla1": "a", # only accepts a, b or c
"bla5": ["testinput2.txt:input",
"testinput3.txt:msfile",
spf("{}hello\{reim\}.fits,{}to.fits,{}world.fits", "input", "msfile", "output")],
}, input=INPUT, output=OUTPUT)
rrr.run() #validate and run

assert rrr.jobs[0].job._cab.parameters[4].value[0] == os.path.join(rrr.jobs[0].job.IODEST["input"],
"testinput2.txt")
assert rrr.jobs[0].job._cab.parameters[4].value[1] == os.path.join(rrr.jobs[0].job.IODEST["msfile"],
"testinput3.txt")
assert rrr.jobs[0].job._cab.parameters[4].value[2] == \
"{}/hello{{reim}}.fits,{}/to.fits,{}/world.fits".format(
rrr.jobs[0].job.IODEST["input"],
rrr.jobs[0].job.IODEST["msfile"],
rrr.jobs[0].job.IODEST["output"]
)

def test_podman(self):
global MSDIR
Expand Down

0 comments on commit 7a1c2e9

Please sign in to comment.