Skip to content

Commit

Permalink
introduce nxf_launch dir
Browse files Browse the repository at this point in the history
instead of writing to the root of the user home tree,
create a subdirectory based on the workflow name, and inject it
as the work dir of the jupyterhub-singleuser process via popen_kwargs
  • Loading branch information
phue committed Jun 26, 2024
1 parent 5144258 commit 0688553
Showing 1 changed file with 42 additions and 20 deletions.
62 changes: 42 additions & 20 deletions nextflowspawner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,67 @@
import os
import pwd

from jupyterhub.spawner import LocalProcessSpawner
from jupyterhub.spawner import LocalProcessSpawner, set_user_setuid
from subprocess import run, CalledProcessError
from traitlets import default, Dict, Unicode
from urllib.parse import urlparse

class NextflowSpawner(LocalProcessSpawner):

@property
def nxf_home(self):
print(self.user.name)
user_home = pwd.getpwnam(self.user.name).pw_dir
print(user_home)
return os.getenv('NXF_HOME', f"{user_home}/.nextflow")

default_url = Unicode('/nextflow', help="entrypoint for https://github.com/phue/jupyter-nextflow-proxy")
workflow_url = Unicode(config=True, help="The url of the pipeline repository.")


home_dir = Unicode(help="The user home directory")

@default('home_dir')
def _default_home_dir(self):
return pwd.getpwnam(self.user.name).pw_dir

nxf_home = Unicode(help="The directory where nextflow assets are stored.")

@default('nxf_home')
def _default_nxf_home(self):
return os.getenv('NXF_HOME', f"{self.home_dir}/.nextflow")

nxf_launch = Unicode(help="The directory where the pipeline is launched.")

@default('nxf_launch')
def _default_nxf_launch(self):
path = f"{self.home_dir}/{self.workflow_url.split('/').pop()}"
if not os.path.exists(path):
os.makedirs(path)
os.chown(path, pwd.getpwnam(self.user.name).pw_uid, pwd.getpwnam(self.user.name).pw_uid)
return path

popen_kwargs = Dict(help="Extra keyword arguments to pass to Popen.")

@default('popen_kwargs')
def _default_popen_kwargs(self):
return {'cwd': self.nxf_launch}

schema = Dict(config=True, help="The pipeline JSON schema.")

@default('schema')
def _default_schema(self):
path = f"{self.nxf_home}/assets/{urlparse(self.workflow_url).path[1:]}/nextflow_schema.json"

try:
run(['nextflow', 'pull', self.workflow_url], check=True)
run(
args=['nextflow', 'pull', self.workflow_url],
check=True,
user=self.user.name,
cwd=self.home_dir,
env={**os.environ, 'NXF_HOME': self.nxf_home}
)
with open(path) as nxf_schema:
return json.load(nxf_schema)
except CalledProcessError:
print(f"{self.workflow_url} does not seem to exist")
except FileNotFoundError:
print(f"{self.workflow_url} does not seem to provide a nextflow_schema.json")

# def make_preexec_fn(self, name):
# if os.getuid():
# # if we are already running as non-root user, do nothing
# pass
# else:
# # otherwise drop privileges
# return super().set_user_setuid(name, chdir=True)
def make_preexec_fn(self, name):
return set_user_setuid(name, chdir=False)

def _get_params_from_schema(self, schema, key=None):
params = {}
Expand Down Expand Up @@ -93,10 +115,10 @@ def _write_params_file(self, config):
# generate sha-1 hash from json payload for use as unique filename
json_sha = hashlib.sha1(json_string.encode()).hexdigest()

with open(f'{json_sha}.json', 'w', encoding='utf-8') as fout:
with open(f'{self.nxf_home}/nextflowspawner_{json_sha}.json', 'w', encoding='utf-8') as fout:
fout.write(json_string)

return f'{json_sha}.json'
return f'{self.nxf_home}/nextflowspawner_{json_sha}.json'

def _options_form_default(self):
params = self._get_params_from_schema(self.schema)
Expand Down Expand Up @@ -139,4 +161,4 @@ def get_env(self):
env['NXF_HOME'] = self.nxf_home
env['NXF_USER_WORKFLOW'] = self.workflow_url
env['NXF_USER_PARAMS'] = self._write_params_file(self.user_options)
return env
return env

0 comments on commit 0688553

Please sign in to comment.