1
+ """Support for executing Docker containers using Singularity."""
1
2
from __future__ import absolute_import
2
-
3
3
import logging
4
4
import os
5
5
import re
6
6
import shutil
7
- import subprocess
8
7
import sys
9
- from io import open
10
-
11
- from typing import (Dict , List , Text , Optional , MutableMapping , Any )
12
-
8
+ from io import open # pylint: disable=redefined-builtin
9
+ from typing import (Dict , List , Text , Optional , MutableMapping )
13
10
from .errors import WorkflowException
14
11
from .job import ContainerCommandLineJob
15
12
from .pathmapper import PathMapper , ensure_writable
16
13
from .process import (UnsupportedRequirement )
17
14
from .utils import docker_windows_path_adjust
15
+ if os .name == 'posix' and sys .version_info [0 ] < 3 :
16
+ from subprocess32 import (check_call , check_output , # pylint: disable=import-error
17
+ CalledProcessError , DEVNULL , PIPE , Popen ,
18
+ TimeoutExpired )
19
+ elif os .name == 'posix' :
20
+ from subprocess import (check_call , check_output , # type: ignore
21
+ CalledProcessError , DEVNULL , PIPE , Popen ,
22
+ TimeoutExpired )
23
+ else : # we're not on Unix, so none of this matters
24
+ pass
18
25
19
26
_logger = logging .getLogger ("cwltool" )
27
+ _USERNS = None
28
+
29
+ def _singularity_supports_userns (): # type: ()->bool
30
+ global _USERNS # pylint: disable=global-statement
31
+ if _USERNS is None :
32
+ try :
33
+ _USERNS = "No valid /bin/sh" in Popen (
34
+ [u"singularity" , u"exec" , u"--userns" , u"/etc" , u"true" ],
35
+ stderr = PIPE , stdout = DEVNULL ).communicate (timeout = 60 )[1 ]
36
+ except TimeoutExpired :
37
+ _USERNS = False
38
+ return _USERNS
20
39
21
40
22
41
class SingularityCommandLineJob (ContainerCommandLineJob ):
@@ -82,7 +101,7 @@ def get_image(dockerRequirement, # type: Dict[Text, Text]
82
101
str (dockerRequirement ["dockerPull" ])]
83
102
_logger .info (Text (cmd ))
84
103
if not dry_run :
85
- subprocess . check_call (cmd , stdout = sys .stderr )
104
+ check_call (cmd , stdout = sys .stderr )
86
105
found = True
87
106
88
107
return found
@@ -107,8 +126,8 @@ def get_from_requirements(self,
107
126
if r :
108
127
errmsg = None
109
128
try :
110
- subprocess . check_output (["singularity" , "--version" ])
111
- except subprocess . CalledProcessError as err :
129
+ check_output (["singularity" , "--version" ])
130
+ except CalledProcessError as err :
112
131
errmsg = "Cannot execute 'singularity --version' {}" .format (err )
113
132
except OSError as err :
114
133
errmsg = "'singularity' executable not found: {}" .format (err )
@@ -154,7 +173,7 @@ def add_volumes(self, pathmapper, runtime, stage_output):
154
173
elif vol .type == "WritableFile" :
155
174
if self .inplace_update :
156
175
runtime .append (u"--bind" )
157
- runtime .append ("{}:{}:rw" .format (
176
+ runtime .append (u "{}:{}:rw" .format (
158
177
docker_windows_path_adjust (vol .resolved ),
159
178
docker_windows_path_adjust (containertgt )))
160
179
else :
@@ -166,7 +185,7 @@ def add_volumes(self, pathmapper, runtime, stage_output):
166
185
else :
167
186
if self .inplace_update :
168
187
runtime .append (u"--bind" )
169
- runtime .append ("{}:{}:rw" .format (
188
+ runtime .append (u "{}:{}:rw" .format (
170
189
docker_windows_path_adjust (vol .resolved ),
171
190
docker_windows_path_adjust (containertgt )))
172
191
else :
@@ -176,7 +195,7 @@ def add_volumes(self, pathmapper, runtime, stage_output):
176
195
with open (createtmp , "wb" ) as tmp :
177
196
tmp .write (vol .resolved .encode ("utf-8" ))
178
197
runtime .append (u"--bind" )
179
- runtime .append ("{}:{}:ro" .format (
198
+ runtime .append (u "{}:{}:ro" .format (
180
199
docker_windows_path_adjust (createtmp ),
181
200
docker_windows_path_adjust (vol .target )))
182
201
@@ -192,7 +211,9 @@ def create_runtime(self,
192
211
""" Returns the Singularity runtime list of commands and options."""
193
212
194
213
runtime = [u"singularity" , u"--quiet" , u"exec" , u"--contain" , u"--pid" ,
195
- u"--ipc" ] # , u"--userns"]
214
+ u"--ipc" ]
215
+ if _singularity_supports_userns ():
216
+ runtime .append (u"--userns" )
196
217
runtime .append (u"--bind" )
197
218
runtime .append (u"{}:{}:rw" .format (
198
219
docker_windows_path_adjust (os .path .realpath (self .outdir )),
0 commit comments