diff --git a/jupyterhub/user.py b/jupyterhub/user.py index f974e097..5228f953 100644 --- a/jupyterhub/user.py +++ b/jupyterhub/user.py @@ -12,7 +12,7 @@ from tornado.log import app_log from sqlalchemy import inspect -from .utils import url_path_join +from .utils import url_path_join, default_server_name from . import orm from traitlets import HasTraits, Any, Dict, observe, default @@ -204,18 +204,20 @@ class User(HasTraits): """Start the user's spawner Because there could be more then one server per user - each server has to have a unique reference (UUID4) + each server has to have a unique name between the servers of a given user base_url is built using user's base url and adding /server/{name} where name is the server uuid urlsafed """ db = self.db - server_uuid = uuid4() - server_url = urlsafe_b64encode(server_uuid.bytes).decode() + if server_name in options: + server_name = options['server_name'] + else: + server_name = default_server_name(self) server = orm.Server( - name = server_uuid.hex, + name = server_name, cookie_name=self.cookie_name, - base_url=url_path_join(self.base_url, 'server', server_url[:10]), + base_url=url_path_join(self.base_url, 'server', server_name), ) self.servers.append(server) db.add(self) diff --git a/jupyterhub/utils.py b/jupyterhub/utils.py index f6c2de58..82b58151 100644 --- a/jupyterhub/utils.py +++ b/jupyterhub/utils.py @@ -214,3 +214,18 @@ def url_path_join(*pieces): result = '/' return result + + +def default_server_name(user): + """Return the default name for a new server for a given user. + + Will be the first available integer string, e.g. '1' or '2'. + """ + existing_names = { server.name for server in user.servers } + # if there are 5 servers, count from 1 to 6 + for n in range(1, len(existing_names) + 2): + name = str(n) + if name not in existing_names: + return name + raise RuntimeError("It should be impossible to get here") +