Skip to content

Commit add550a

Browse files
authored
Merge pull request #8245 from fstagni/90_apptainer_bind
[9.0] dirac-apptainer-exec : bind optional paths
2 parents f6d1af3 + 5ec61d3 commit add550a

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

src/DIRAC/Core/Utilities/Os.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
by default on Error they return None
44
"""
55
import os
6+
import threading
67

78
import DIRAC
8-
from DIRAC.Core.Utilities.Subprocess import shellCall, systemCall
99
from DIRAC.Core.Utilities import List
10+
from DIRAC.Core.Utilities.Subprocess import shellCall, systemCall
1011

1112
DEBUG = 0
1213

@@ -128,3 +129,33 @@ def sourceEnv(timeout, cmdTuple, inputEnv=None):
128129
result["stderr"] = stderr
129130

130131
return result
132+
133+
134+
def safe_listdir(directory, timeout=60):
135+
"""This is a "safe" list directory,
136+
for lazily-loaded File Systems like CVMFS.
137+
There's by default a 60 seconds timeout.
138+
139+
.. warning::
140+
There is no distinction between an empty directory, and a non existent one.
141+
It will return `[]` in both cases.
142+
143+
:param str directory: directory to list
144+
:param int timeout: optional timeout, in seconds. Defaults to 60.
145+
"""
146+
147+
def listdir(directory):
148+
try:
149+
return os.listdir(directory)
150+
except FileNotFoundError:
151+
print(f"{directory} not found")
152+
return []
153+
154+
contents = []
155+
t = threading.Thread(target=lambda: contents.extend(listdir(directory)))
156+
t.daemon = True # don't delay program's exit
157+
t.start()
158+
t.join(timeout)
159+
if t.is_alive():
160+
return None # timeout
161+
return contents

src/DIRAC/Core/scripts/dirac_apptainer_exec.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from DIRAC import S_ERROR, gConfig, gLogger
1111
from DIRAC.Core.Base.Script import Script
1212
from DIRAC.Core.Security.Locations import getCAsLocation, getProxyLocation, getVOMSLocation
13+
from DIRAC.Core.Utilities.Os import safe_listdir
1314
from DIRAC.Core.Utilities.Subprocess import systemCall
1415

1516

@@ -73,7 +74,7 @@ def main():
7374
cmd.extend(["--contain"]) # use minimal /dev and empty other directories (e.g. /tmp and $HOME)
7475
cmd.extend(["--ipc"]) # run container in a new IPC namespace
7576
cmd.extend(["--pid"]) # run container in a new PID namespace
76-
cmd.extend(["--bind", f"{os.getcwd()}:/mnt"]) # bind current directory for dirac_container.sh
77+
cmd.extend(["--bind", f"{os.getcwd()}"]) # bind current directory for dirac_container.sh
7778
if proxy_location:
7879
cmd.extend(["--bind", f"{proxy_location}:/etc/proxy"]) # bind proxy file
7980
cmd.extend(["--bind", f"{getCAsLocation()}:/etc/grid-security/certificates"]) # X509_CERT_DIR
@@ -83,12 +84,18 @@ def main():
8384
cmd.extend(["--bind", f"{vomses_location}:/etc/grid-security/vomses"]) # X509_VOMSES
8485
cmd.extend(["--bind", "{0}:{0}:ro".format(etc_dir)]) # etc dir for dirac.cfg
8586
cmd.extend(["--bind", "{0}:{0}:ro".format(os.path.join(os.path.realpath(sys.base_prefix)))]) # code dir
86-
cmd.extend(["--cwd", "/mnt"]) # set working directory to /mnt
87+
# here bind optional paths
88+
for bind_path in gConfig.getValue("/Resources/Computing/Singularity/BindPaths", []):
89+
if safe_listdir(bind_path):
90+
cmd.extend(["--bind", f"{bind_path}:{bind_path}"])
91+
else:
92+
gLogger.warning(f"Bind path {bind_path} does not exist, skipping")
93+
cmd.extend(["--cwd", f"{os.getcwd()}"]) # set working directory
8794

8895
rootImage = user_image or gConfig.getValue("/Resources/Computing/Singularity/ContainerRoot") or CONTAINER_DEFROOT
8996

9097
if os.path.isdir(rootImage) or os.path.isfile(rootImage):
91-
cmd.extend([rootImage, "/mnt/dirac_container.sh"])
98+
cmd.extend([rootImage, f"{os.getcwd()}/dirac_container.sh"])
9299
else:
93100
# if we are here is because there's no image, or it is not accessible (e.g. not on CVMFS)
94101
gLogger.error("Apptainer image to exec not found: ", rootImage)

0 commit comments

Comments
 (0)