5
5
import os
6
6
import pwd
7
7
8
- from jupyterhub .spawner import LocalProcessSpawner
8
+ from jupyterhub .spawner import LocalProcessSpawner , set_user_setuid
9
9
from subprocess import run , CalledProcessError
10
10
from traitlets import default , Dict , Unicode
11
11
from urllib .parse import urlparse
12
12
13
13
class NextflowSpawner (LocalProcessSpawner ):
14
14
15
- @property
16
- def nxf_home (self ):
17
- print (self .user .name )
18
- user_home = pwd .getpwnam (self .user .name ).pw_dir
19
- print (user_home )
20
- return os .getenv ('NXF_HOME' , f"{ user_home } /.nextflow" )
21
-
22
15
default_url = Unicode ('/nextflow' , help = "entrypoint for https://github.com/phue/jupyter-nextflow-proxy" )
23
16
workflow_url = Unicode (config = True , help = "The url of the pipeline repository." )
24
-
17
+
18
+ home_dir = Unicode (help = "The user home directory" )
19
+
20
+ @default ('home_dir' )
21
+ def _default_home_dir (self ):
22
+ return pwd .getpwnam (self .user .name ).pw_dir
23
+
24
+ nxf_home = Unicode (help = "The directory where nextflow assets are stored." )
25
+
26
+ @default ('nxf_home' )
27
+ def _default_nxf_home (self ):
28
+ return os .getenv ('NXF_HOME' , f"{ self .home_dir } /.nextflow" )
29
+
30
+ nxf_launch = Unicode (help = "The directory where the pipeline is launched." )
31
+
32
+ @default ('nxf_launch' )
33
+ def _default_nxf_launch (self ):
34
+ path = f"{ self .home_dir } /{ self .workflow_url .split ('/' ).pop ()} "
35
+ if not os .path .exists (path ):
36
+ os .makedirs (path )
37
+ os .chown (path , pwd .getpwnam (self .user .name ).pw_uid , pwd .getpwnam (self .user .name ).pw_uid )
38
+ return path
39
+
40
+ popen_kwargs = Dict (help = "Extra keyword arguments to pass to Popen." )
41
+
42
+ @default ('popen_kwargs' )
43
+ def _default_popen_kwargs (self ):
44
+ return {'cwd' : self .nxf_launch }
45
+
25
46
schema = Dict (config = True , help = "The pipeline JSON schema." )
26
47
27
48
@default ('schema' )
28
49
def _default_schema (self ):
29
50
path = f"{ self .nxf_home } /assets/{ urlparse (self .workflow_url ).path [1 :]} /nextflow_schema.json"
30
51
31
52
try :
32
- run (['nextflow' , 'pull' , self .workflow_url ], check = True )
53
+ run (
54
+ args = ['nextflow' , 'pull' , self .workflow_url ],
55
+ check = True ,
56
+ user = self .user .name ,
57
+ cwd = self .home_dir ,
58
+ env = {** os .environ , 'NXF_HOME' : self .nxf_home }
59
+ )
33
60
with open (path ) as nxf_schema :
34
61
return json .load (nxf_schema )
35
62
except CalledProcessError :
36
63
print (f"{ self .workflow_url } does not seem to exist" )
37
64
except FileNotFoundError :
38
65
print (f"{ self .workflow_url } does not seem to provide a nextflow_schema.json" )
39
66
40
- # def make_preexec_fn(self, name):
41
- # if os.getuid():
42
- # # if we are already running as non-root user, do nothing
43
- # pass
44
- # else:
45
- # # otherwise drop privileges
46
- # return super().set_user_setuid(name, chdir=True)
67
+ def make_preexec_fn (self , name ):
68
+ return set_user_setuid (name , chdir = False )
47
69
48
70
def _get_params_from_schema (self , schema , key = None ):
49
71
params = {}
@@ -93,10 +115,10 @@ def _write_params_file(self, config):
93
115
# generate sha-1 hash from json payload for use as unique filename
94
116
json_sha = hashlib .sha1 (json_string .encode ()).hexdigest ()
95
117
96
- with open (f'{ json_sha } .json' , 'w' , encoding = 'utf-8' ) as fout :
118
+ with open (f'{ self . nxf_home } /nextflowspawner_ { json_sha } .json' , 'w' , encoding = 'utf-8' ) as fout :
97
119
fout .write (json_string )
98
120
99
- return f'{ json_sha } .json'
121
+ return f'{ self . nxf_home } /nextflowspawner_ { json_sha } .json'
100
122
101
123
def _options_form_default (self ):
102
124
params = self ._get_params_from_schema (self .schema )
@@ -139,4 +161,4 @@ def get_env(self):
139
161
env ['NXF_HOME' ] = self .nxf_home
140
162
env ['NXF_USER_WORKFLOW' ] = self .workflow_url
141
163
env ['NXF_USER_PARAMS' ] = self ._write_params_file (self .user_options )
142
- return env
164
+ return env
0 commit comments