diff --git a/src/DIRAC/Core/scripts/dirac_apptainer_exec.py b/src/DIRAC/Core/scripts/dirac_apptainer_exec.py index e7c8c6303f9..2daafbab2ff 100644 --- a/src/DIRAC/Core/scripts/dirac_apptainer_exec.py +++ b/src/DIRAC/Core/scripts/dirac_apptainer_exec.py @@ -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") @@ -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 @@ -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)