1+ #!/usr/bin/env python
12""" Starts a DIRAC command inside an apptainer container.
23"""
34
45import os
56import sys
7+ from pathlib import Path
68
79import DIRAC
810from DIRAC import S_ERROR , gConfig , gLogger
911from DIRAC .Core .Base .Script import Script
1012from DIRAC .Core .Security .Locations import getCAsLocation , getProxyLocation , getVOMSLocation
1113from DIRAC .Core .Utilities .Subprocess import systemCall
1214
13- CONTAINER_WRAPPER = """#!/bin/bash
1415
15- export DIRAC=%(dirac_env_var)s
16- export DIRACOS=%(diracos_env_var)s
17- export X509_USER_PROXY=/etc/proxy
18- export X509_CERT_DIR=/etc/grid-security/certificates
19- export X509_VOMS_DIR=/etc/grid-security/vomsdir
20- export DIRACSYSCONFIG=%(etc_dir)s/dirac.cfg
21- source %(rc_script)s
22- %(command)s
23- """
16+ def generate_container_wrapper (dirac_env_var , diracos_env_var , etc_dir , rc_script , command , include_proxy = True ):
17+ lines = [
18+ "#!/bin/bash" ,
19+ f"export DIRAC={ dirac_env_var } " ,
20+ f"export DIRACOS={ diracos_env_var } " ,
21+ ]
22+
23+ if include_proxy :
24+ lines .append ("export X509_USER_PROXY=/etc/proxy" )
25+
26+ lines .extend (
27+ [
28+ "export X509_CERT_DIR=/etc/grid-security/certificates" ,
29+ "export X509_VOMS_DIR=/etc/grid-security/vomsdir" ,
30+ "export X509_VOMSES=/etc/grid-security/vomses" ,
31+ f"export DIRACSYSCONFIG={ etc_dir } /dirac.cfg" ,
32+ f"source { rc_script } " ,
33+ command ,
34+ ]
35+ )
36+
37+ return "\n " .join (lines )
38+
2439
2540CONTAINER_DEFROOT = "" # Should add something like "/cvmfs/dirac.egi.eu/container/apptainer/alma9/x86_64"
2641
@@ -36,28 +51,36 @@ def main():
3651 if switch [0 ].lower () == "i" or switch [0 ].lower () == "image" :
3752 user_image = switch [1 ]
3853
54+ dirac_env_var = os .environ .get ("DIRAC" , os .getcwd ())
55+ diracos_env_var = os .environ .get ("DIRACOS" , os .getcwd ())
3956 etc_dir = os .path .join (DIRAC .rootPath , "etc" )
57+ rc_script = os .path .join (os .path .realpath (sys .base_prefix ), "diracosrc" )
4058
41- wrapSubs = {
42- "dirac_env_var" : os .environ .get ("DIRAC" , os .getcwd ()),
43- "diracos_env_var" : os .environ .get ("DIRACOS" , os .getcwd ()),
44- "etc_dir" : etc_dir ,
45- }
46- wrapSubs ["rc_script" ] = os .path .join (os .path .realpath (sys .base_prefix ), "diracosrc" )
47- wrapSubs ["command" ] = command
59+ include_proxy = True
60+ proxy_location = getProxyLocation ()
61+ if not proxy_location :
62+ include_proxy = False
4863
49- rawfd = os .open ("dirac_container.sh" , os .O_WRONLY | os .O_CREAT , 0o700 )
50- fd = os .fdopen (rawfd , "w" )
51- fd .write (CONTAINER_WRAPPER % wrapSubs )
52- fd .close ()
64+ with open ("dirac_container.sh" , "w" , encoding = "utf-8" ) as fd :
65+ script = generate_container_wrapper (
66+ dirac_env_var , diracos_env_var , etc_dir , rc_script , command , include_proxy = include_proxy
67+ )
68+ fd .write (script )
69+ os .chmod ("dirac_container.sh" , 0o755 )
5370
71+ # Now let's construct the apptainer command
5472 cmd = ["apptainer" , "exec" ]
5573 cmd .extend (["--contain" ]) # use minimal /dev and empty other directories (e.g. /tmp and $HOME)
5674 cmd .extend (["--ipc" ]) # run container in a new IPC namespace
75+ cmd .extend (["--pid" ]) # run container in a new PID namespace
5776 cmd .extend (["--bind" , f"{ os .getcwd ()} :/mnt" ]) # bind current directory for dirac_container.sh
58- cmd .extend (["--bind" , f"{ getProxyLocation ()} :/etc/proxy" ]) # bind proxy file
77+ if proxy_location :
78+ cmd .extend (["--bind" , f"{ proxy_location } :/etc/proxy" ]) # bind proxy file
5979 cmd .extend (["--bind" , f"{ getCAsLocation ()} :/etc/grid-security/certificates" ]) # X509_CERT_DIR
60- cmd .extend (["--bind" , f"{ getVOMSLocation ()} :/etc/grid-security/vomsdir" ]) # X509_VOMS_DIR
80+ voms_location = Path (getVOMSLocation ())
81+ cmd .extend (["--bind" , f"{ voms_location } :/etc/grid-security/vomsdir" ]) # X509_VOMS_DIR
82+ vomses_location = voms_location .parent / "vomses"
83+ cmd .extend (["--bind" , f"{ vomses_location } :/etc/grid-security/vomses" ]) # X509_VOMSES
6184 cmd .extend (["--bind" , "{0}:{0}:ro" .format (etc_dir )]) # etc dir for dirac.cfg
6285 cmd .extend (["--bind" , "{0}:{0}:ro" .format (os .path .join (os .path .realpath (sys .base_prefix )))]) # code dir
6386
@@ -73,7 +96,11 @@ def main():
7396 gLogger .debug (f"Execute Apptainer command: { ' ' .join (cmd )} " )
7497 result = systemCall (0 , cmd )
7598 if not result ["OK" ]:
99+ gLogger .error (result ["Message" ])
76100 DIRAC .exit (1 )
101+ if result ["Value" ][0 ] != 0 :
102+ gLogger .error (result ["Value" ][2 ])
103+ DIRAC .exit (2 )
77104 gLogger .notice (result ["Value" ][1 ])
78105
79106
0 commit comments