Skip to content

Commit

Permalink
fix: creating the correct environment inside the container
Browse files Browse the repository at this point in the history
  • Loading branch information
fstagni committed Feb 13, 2025
1 parent 50d498d commit 86798ea
Showing 1 changed file with 13 additions and 26 deletions.
39 changes: 13 additions & 26 deletions src/DIRAC/Core/scripts/dirac_apptainer_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,27 @@
"""

import os
import shutil
import sys

import DIRAC
from DIRAC import S_ERROR, gConfig, gLogger
from DIRAC.Core.Base.Script import Script
from DIRAC.Core.Security.Locations import getProxyLocation
from DIRAC.Core.Utilities.Subprocess import systemCall

CONTAINER_WRAPPER = """#!/bin/bash
echo "Starting inner container wrapper scripts (no install) at `date`."
export DIRAC=%(dirac_env_var)s
export DIRACOS=%(diracos_env_var)s
# In any case we need to find a bashrc, and a cfg
export X509_USER_PROXY=/etc/proxy
export DIRACSYSCONFIG=%(etc_dir)s/dirac.cfg
source %(rc_script)s
%(command)s
echo "Finishing inner container wrapper scripts at `date`."
"""

CONTAINER_DEFROOT = "" # Should add something like "/cvmfs/dirac.egi.eu/container/apptainer/alma9/x86_64"


def getEnv():
"""Gets the environment for use within the container.
We blank almost everything to prevent contamination from the host system.
"""

payloadEnv = {k: v for k, v in os.environ.items()}
payloadEnv["TMP"] = "/tmp"
payloadEnv["TMPDIR"] = "/tmp"
payloadEnv["X509_USER_PROXY"] = os.path.join("tmp", "proxy")
payloadEnv["DIRACSYSCONFIG"] = os.path.join("tmp", "dirac.cfg")

return payloadEnv


@Script()
def main():
Script.registerArgument(" command: Command to execute inside the container")
Expand All @@ -50,26 +35,28 @@ def main():
if switch[0].lower() == "i" or switch[0].lower() == "image":
user_image = switch[1]

etc_dir = os.path.realpath(os.path.join(os.environ.get("DIRAC"), "..", "..", "..", "etc"))

wrapSubs = {
"dirac_env_var": os.environ.get("DIRAC", os.getcwd()),
"diracos_env_var": os.environ.get("DIRACOS", os.getcwd()),
"etc_dir": etc_dir,
}
wrapSubs["rc_script"] = os.path.join(os.path.realpath(sys.base_prefix), "diracosrc")
wrapSubs["command"] = command
shutil.copyfile("dirac.cfg", os.path.join("tmp", "dirac.cfg"))

wrapLoc = os.path.join("tmp", "dirac_container.sh")
rawfd = os.open(wrapLoc, os.O_WRONLY | os.O_CREAT, 0o700)
rawfd = os.open("dirac_container.sh", os.O_WRONLY | os.O_CREAT, 0o700)
fd = os.fdopen(rawfd, "w")
fd.write(CONTAINER_WRAPPER % wrapSubs)
fd.close()

innerCmd = os.path.join("tmp", "dirac_container.sh")
innerCmd = os.path.join("/tmp", "dirac_container.sh")
cmd = ["apptainer", "exec"]
cmd.extend(["--contain"]) # use minimal /dev and empty other directories (e.g. /tmp and $HOME)
cmd.extend(["--ipc"]) # run container in a new IPC namespace
cmd.extend(["--workdir", "/tmp"]) # working directory to be used for /tmp, /var/tmp and $HOME
cmd.extend(["--home", "/tmp"]) # Avoid using small tmpfs for default $HOME and use scratch /tmp instead
cmd.extend(["--bind", f"{os.getcwd()}:/mnt"])
cmd.extend(["--bind", f"{getProxyLocation()}:/etc/proxy"])
cmd.extend(["--bind", "{0}:{0}:ro".format(etc_dir)])
cmd.extend(["--bind", "{0}:{0}:ro".format(os.path.join(os.path.realpath(sys.base_prefix)))])

rootImage = user_image or gConfig.getValue("/Resources/Computing/Singularity/ContainerRoot") or CONTAINER_DEFROOT
Expand All @@ -81,8 +68,8 @@ def main():
gLogger.error("Apptainer image to exec not found: ", rootImage)
return S_ERROR("Failed to find Apptainer image to exec")

gLogger.debug(f"Execute Apptainer command: {cmd}")
result = systemCall(0, cmd, env=getEnv())
gLogger.debug(f"Execute Apptainer command: {' '.join(cmd)}")
result = systemCall(0, cmd)
if not result["OK"]:
DIRAC.exit(1)

Expand Down

0 comments on commit 86798ea

Please sign in to comment.