Skip to content

Commit 8633785

Browse files
committed
Merge remote-tracking branch 'upstream/pr/100' into dev
Conflicts: batchspawner/batchspawner.py
2 parents b8d43de + 5a9d6e8 commit 8633785

File tree

1 file changed

+50
-42
lines changed

1 file changed

+50
-42
lines changed

batchspawner/batchspawner.py

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"""
1818
import pwd
1919
import os
20+
import re
2021

2122
import xml.etree.ElementTree as ET
2223

@@ -46,7 +47,7 @@ def format_template(template, *args, **kwargs):
4647
"""
4748
if isinstance(template, Template):
4849
return template.render(*args, **kwargs)
49-
elif '{{' in template or '{%' in template:
50+
elif '{{' in template or '{%' in template:
5051
return Template(template).render(*args, **kwargs)
5152
return template.format(*args, **kwargs)
5253

@@ -78,52 +79,52 @@ class BatchSpawnerBase(Spawner):
7879
# override default server ip since batch jobs normally running remotely
7980
ip = Unicode("0.0.0.0", help="Address for singleuser server to listen at").tag(config=True)
8081

81-
exec_prefix = Unicode('sudo -E -u {username}', \
82+
exec_prefix = Unicode('sudo -E -u {username}',
8283
help="Standard executon prefix (e.g. the default sudo -E -u {username})"
8384
).tag(config=True)
8485

8586
# all these req_foo traits will be available as substvars for templated strings
86-
req_queue = Unicode('', \
87+
req_queue = Unicode('',
8788
help="Queue name to submit job to resource manager"
8889
).tag(config=True)
8990

90-
req_host = Unicode('', \
91+
req_host = Unicode('',
9192
help="Host name of batch server to submit job to resource manager"
9293
).tag(config=True)
9394

94-
req_memory = Unicode('', \
95+
req_memory = Unicode('',
9596
help="Memory to request from resource manager"
9697
).tag(config=True)
9798

98-
req_nprocs = Unicode('', \
99+
req_nprocs = Unicode('',
99100
help="Number of processors to request from resource manager"
100101
).tag(config=True)
101102

102-
req_ngpus = Unicode('', \
103+
req_ngpus = Unicode('',
103104
help="Number of GPUs to request from resource manager"
104105
).tag(config=True)
105106

106-
req_runtime = Unicode('', \
107+
req_runtime = Unicode('',
107108
help="Length of time for submitted job to run"
108109
).tag(config=True)
109110

110-
req_partition = Unicode('', \
111+
req_partition = Unicode('',
111112
help="Partition name to submit job to resource manager"
112113
).tag(config=True)
113114

114-
req_account = Unicode('', \
115+
req_account = Unicode('',
115116
help="Account name string to pass to the resource manager"
116117
).tag(config=True)
117118

118-
req_options = Unicode('', \
119+
req_options = Unicode('',
119120
help="Other options to include into job submission script"
120121
).tag(config=True)
121122

122-
req_prologue = Unicode('', \
123+
req_prologue = Unicode('',
123124
help="Script to run before single user server starts."
124125
).tag(config=True)
125126

126-
req_epilogue = Unicode('', \
127+
req_epilogue = Unicode('',
127128
help="Script to run after single user server ends."
128129
).tag(config=True)
129130

@@ -148,8 +149,7 @@ def _req_keepvars_default(self):
148149
"added to the defaults in keepvars, "
149150
"comma separated list.")
150151

151-
152-
batch_script = Unicode('', \
152+
batch_script = Unicode('',
153153
help="Template for job submission script. Traits on this class named like req_xyz "
154154
"will be substituted in the template for {xyz} using string.Formatter. "
155155
"Must include {cmd} which will be replaced with the jupyterhub-singleuser command line."
@@ -174,7 +174,7 @@ def get_req_subvars(self):
174174
subvars['keepvars'] += ',' + subvars['keepvars_extra']
175175
return subvars
176176

177-
batch_submit_cmd = Unicode('', \
177+
batch_submit_cmd = Unicode('',
178178
help="Command to run to submit batch scripts. Formatted using req_xyz traits as {xyz}."
179179
).tag(config=True)
180180

@@ -244,7 +244,7 @@ def submit_batch_script(self):
244244
return self.job_id
245245

246246
# Override if your batch system needs something more elaborate to read the job status
247-
batch_query_cmd = Unicode('', \
247+
batch_query_cmd = Unicode('',
248248
help="Command to run to read job status. Formatted using req_xyz traits as {xyz} "
249249
"and self.job_id as {job_id}."
250250
).tag(config=True)
@@ -335,7 +335,7 @@ def poll(self):
335335
self.clear_state()
336336
return 1
337337

338-
startup_poll_interval = Float(0.5, \
338+
startup_poll_interval = Float(0.5,
339339
help="Polling interval (seconds) to check job state during startup"
340340
).tag(config=True)
341341

@@ -345,8 +345,9 @@ def start(self):
345345
if self.user and self.user.server and self.user.server.port:
346346
self.port = self.user.server.port
347347
self.db.commit()
348-
elif (jupyterhub.version_info < (0,7) and not self.user.server.port) or \
349-
(jupyterhub.version_info >= (0,7) and not self.port):
348+
elif (jupyterhub.version_info < (0,7) and not self.user.server.port) or (
349+
jupyterhub.version_info >= (0,7) and not self.port
350+
):
350351
self.port = random_port()
351352
self.db.commit()
352353
job = yield self.submit_batch_script()
@@ -367,8 +368,8 @@ def start(self):
367368
else:
368369
self.log.warn('Job ' + self.job_id + ' neither pending nor running.\n' +
369370
self.job_status)
370-
raise RuntimeError('The Jupyter batch job has disappeared '
371-
' while pending in the queue or died immediately '
371+
raise RuntimeError('The Jupyter batch job has disappeared'
372+
' while pending in the queue or died immediately'
372373
' after starting.')
373374
yield gen.sleep(self.startup_poll_interval)
374375

@@ -405,7 +406,6 @@ def stop(self, now=False):
405406
self.job_id, self.current_ip, self.port)
406407
)
407408

408-
import re
409409

410410
class BatchSpawnerRegexStates(BatchSpawnerBase):
411411
"""Subclass of BatchSpawnerBase that uses config-supplied regular expressions
@@ -442,13 +442,15 @@ def state_ispending(self):
442442
assert self.state_pending_re, "Misconfigured: define state_running_re"
443443
if self.job_status and re.search(self.state_pending_re, self.job_status):
444444
return True
445-
else: return False
445+
else:
446+
return False
446447

447448
def state_isrunning(self):
448449
assert self.state_running_re, "Misconfigured: define state_running_re"
449450
if self.job_status and re.search(self.state_running_re, self.job_status):
450451
return True
451-
else: return False
452+
else:
453+
return False
452454

453455
def state_gethost(self):
454456
assert self.state_exechost_re, "Misconfigured: define state_exechost_re"
@@ -461,6 +463,7 @@ def state_gethost(self):
461463
else:
462464
return match.expand(self.state_exechost_exp)
463465

466+
464467
class TorqueSpawner(BatchSpawnerRegexStates):
465468
batch_script = Unicode("""#!/bin/sh
466469
#PBS -q {queue}@{host}
@@ -486,6 +489,7 @@ class TorqueSpawner(BatchSpawnerRegexStates):
486489
state_running_re = Unicode(r'<job_state>R</job_state>').tag(config=True)
487490
state_exechost_re = Unicode(r'<exec_host>((?:[\w_-]+\.?)+)/\d+').tag(config=True)
488491

492+
489493
class MoabSpawner(TorqueSpawner):
490494
# outputs job id string
491495
batch_submit_cmd = Unicode('msub').tag(config=True)
@@ -496,6 +500,7 @@ class MoabSpawner(TorqueSpawner):
496500
state_running_re = Unicode(r'State="Running"').tag(config=True)
497501
state_exechost_re = Unicode(r'AllocNodeList="([^\r\n\t\f :"]*)').tag(config=True)
498502

503+
499504
class UserEnvMixin:
500505
"""Mixin class that computes values for USER, SHELL and HOME in the environment passed to
501506
the job submission subprocess in case the batch system needs these for the batch script."""
@@ -522,23 +527,8 @@ def get_env(self):
522527
env = self.user_env(env)
523528
return env
524529

525-
class SlurmSpawner(UserEnvMixin,BatchSpawnerRegexStates):
526-
"""A Spawner that just uses Popen to start local processes."""
527-
528-
# all these req_foo traits will be available as substvars for templated strings
529-
req_cluster = Unicode('', \
530-
help="Cluster name to submit job to resource manager"
531-
).tag(config=True)
532-
533-
req_qos = Unicode('', \
534-
help="QoS name to submit job to resource manager"
535-
).tag(config=True)
536-
537-
req_srun = Unicode('srun',
538-
help="Job step wrapper, default 'srun'. Set to '' you do not want "
539-
"to run in job step (affects environment handling)"
540-
).tag(config=True)
541530

531+
class SlurmSpawner(UserEnvMixin,BatchSpawnerRegexStates):
542532
batch_script = Unicode("""#!/bin/bash
543533
#SBATCH --output={{homedir}}/jupyterhub_slurmspawner_%j.log
544534
#SBATCH --job-name=spawner-jupyterhub
@@ -558,6 +548,21 @@ class SlurmSpawner(UserEnvMixin,BatchSpawnerRegexStates):
558548
echo "jupyterhub-singleuser ended gracefully"
559549
{{epilogue}}
560550
""").tag(config=True)
551+
552+
# all these req_foo traits will be available as substvars for templated strings
553+
req_cluster = Unicode('',
554+
help="Cluster name to submit job to resource manager"
555+
).tag(config=True)
556+
557+
req_qos = Unicode('',
558+
help="QoS name to submit job to resource manager"
559+
).tag(config=True)
560+
561+
req_srun = Unicode('srun',
562+
help="Job step wrapper, default 'srun'. Set to '' you do not want "
563+
"to run in job step (affects environment handling)"
564+
).tag(config=True)
565+
561566
# outputs line like "Submitted batch job 209"
562567
batch_submit_cmd = Unicode('sbatch --parsable').tag(config=True)
563568
# outputs status and exec node like "RUNNING hostname"
@@ -579,6 +584,7 @@ def parse_job_id(self, output):
579584
raise e
580585
return id
581586

587+
582588
class MultiSlurmSpawner(SlurmSpawner):
583589
'''When slurm has been compiled with --enable-multiple-slurmd, the
584590
administrator sets the name of the slurmd instance via the slurmd -N
@@ -591,6 +597,7 @@ def state_gethost(self):
591597
host = SlurmSpawner.state_gethost(self)
592598
return self.daemon_resolver.get(host, host)
593599

600+
594601
class GridengineSpawner(BatchSpawnerBase):
595602
batch_script = Unicode("""#!/bin/bash
596603
#$ -j yes
@@ -640,6 +647,7 @@ def state_gethost(self):
640647
self.log.error("Spawner unable to match host addr in job {0} with status {1}".format(self.job_id, self.job_status))
641648
return
642649

650+
643651
class CondorSpawner(UserEnvMixin,BatchSpawnerRegexStates):
644652
batch_script = Unicode("""
645653
Executable = /bin/sh
@@ -677,6 +685,7 @@ def parse_job_id(self, output):
677685
def cmd_formatted_for_batch(self):
678686
return super(CondorSpawner,self).cmd_formatted_for_batch().replace('"','""').replace("'","''")
679687

688+
680689
class LsfSpawner(BatchSpawnerBase):
681690
'''A Spawner that uses IBM's Platform Load Sharing Facility (LSF) to launch notebooks.'''
682691

@@ -723,7 +732,6 @@ def state_isrunning(self):
723732
if self.job_status:
724733
return self.job_status.split(' ')[0].upper() == 'RUN'
725734

726-
727735
def state_gethost(self):
728736
if self.job_status:
729737
return self.job_status.split(' ')[1].strip()

0 commit comments

Comments
 (0)