Skip to content

Commit 4e4ec11

Browse files
committed
Add API handler to post remote server port number
1 parent 4747946 commit 4e4ec11

File tree

6 files changed

+56
-8
lines changed

6 files changed

+56
-8
lines changed

batchspawner/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
from .batchspawner import *
2+
from . import singleuser
3+
from . import api

batchspawner/api.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import json
2+
from tornado import web
3+
from jupyterhub.apihandlers import APIHandler, default_handlers
4+
5+
class BatchSpawnerAPIHandler(APIHandler):
6+
@web.authenticated
7+
def post(self):
8+
"""POST set user's spawner port number"""
9+
user = self.get_current_user()
10+
data = self.get_json_body()
11+
if user.spawner.port == 0:
12+
port = data.get('port', 0)
13+
user.spawner.port = int(port)
14+
self.finish(json.dumps({"message": "BatchSpawner port configured"}))
15+
self.set_status(201)
16+
17+
default_handlers.append((r"/api/batchspawner", BatchSpawnerAPIHandler))

batchspawner/batchspawner.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from tornado.iostream import StreamClosedError
3030

3131
from jupyterhub.spawner import Spawner
32+
from jupyterhub.traitlets import Command
3233
from traitlets import (
3334
Integer, Unicode, Float, Dict, default
3435
)
@@ -73,6 +74,9 @@ class BatchSpawnerBase(Spawner):
7374
state_gethost
7475
"""
7576

77+
# override default since will need to set the listening port using the api
78+
cmd = Command(['batchspawner-singleuser'], allow_none=True).tag(config=True)
79+
7680
# override default since batch systems typically need longer
7781
start_timeout = Integer(300).tag(config=True)
7882

@@ -342,14 +346,7 @@ def poll(self):
342346
@gen.coroutine
343347
def start(self):
344348
"""Start the process"""
345-
if self.user and self.user.server and self.user.server.port:
346-
self.port = self.user.server.port
347-
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
350-
):
351-
self.port = random_port()
352-
self.db.commit()
349+
self.port = self.server.port = 0
353350
job = yield self.submit_batch_script()
354351

355352
# We are called with a timeout, and if the timeout expires this function will
@@ -374,6 +371,9 @@ def start(self):
374371
yield gen.sleep(self.startup_poll_interval)
375372

376373
self.current_ip = self.state_gethost()
374+
while self.port == 0:
375+
yield gen.sleep(self.startup_poll_interval)
376+
377377
if jupyterhub.version_info < (0,7):
378378
# store on user for pre-jupyterhub-0.7:
379379
self.user.server.port = self.port

batchspawner/singleuser.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from jupyterhub.singleuser import SingleUserNotebookApp
2+
from jupyterhub.utils import random_port, url_path_join
3+
from traitlets import default
4+
5+
class BatchSingleUserNotebookApp(SingleUserNotebookApp):
6+
@default('port')
7+
def _port(self):
8+
return random_port()
9+
10+
def start(self):
11+
# Send Notebook app's port number to remote Spawner
12+
self.hub_auth._api_request(method='POST',
13+
url=url_path_join(self.hub_api_url, 'batchspawner'),
14+
json={'port' : self.port})
15+
super().start()
16+
17+
def main(argv=None):
18+
return BatchSingleUserNotebookApp.launch_instance(argv)
19+
20+
if __name__ == "__main__":
21+
main()

scripts/batchspawner-singleuser

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env python3
2+
3+
from batchspawner.singleuser import main
4+
5+
if __name__ == '__main__':
6+
main()

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import sys
1515

1616
from setuptools import setup
17+
from glob import glob
1718

1819
pjoin = os.path.join
1920
here = os.path.abspath(os.path.dirname(__file__))
@@ -28,6 +29,7 @@
2829

2930
setup_args = dict(
3031
name = 'batchspawner',
32+
scripts = glob(pjoin('scripts', '*')),
3133
packages = ['batchspawner'],
3234
version = version_ns['__version__'],
3335
description = """Batchspawner: A spawner for Jupyterhub to spawn notebooks using batch resource managers.""",

0 commit comments

Comments
 (0)