Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
  • 2 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Commits on Dec 02, 2016
Alexander Tiunov limit for running users e30a211
Alexander Tiunov added param to config 37599d3
Showing with 32 additions and 3 deletions.
  1. +1 −0 etc/base_config.py
  2. +19 −3 everware/spawner.py
  3. +12 −0 everware/user_spawn_handler.py
View
@@ -10,6 +10,7 @@
c.Spawner.debug = True
c.Spawner.start_timeout = 1000
c.Spawner.http_timeout = 60
+c.Spawner.max_users_running = 60
c.Spawner.remove_containers = True
c.Spawner.tls_assert_hostname = False
c.Spawner.use_docker_client_env = True
View
@@ -18,6 +18,7 @@
import ssl
import json
import os
+import sys
from .image_handler import ImageHandler
from .git_processor import GitMixin
@@ -29,6 +30,10 @@
class CustomDockerSpawner(DockerSpawner, GitMixin, EmailNotificator):
+ max_users_running = Integer(
+ config=True
+ )
+
def __init__(self, **kwargs):
self._user_log = []
self._is_failed = False
@@ -144,7 +149,7 @@ def options_from_form(self, formdata):
def form_repo_url(self):
"""Repository URL as submitted by the user."""
return self.user_options.get('repo_url', '')
-
+
@property
def container_name(self):
return "{}-{}".format(self.container_prefix,
@@ -283,6 +288,12 @@ def remove_old_container(self):
except APIError as e:
self.log.info("Can't erase container %s due to %s" % (self.container_name, e))
+ def are_too_many_users(self):
+ if not hasattr(self, 'max_users_running'):
+ return False
+ running_users = self.user_options.get('running_users', -1)
+ self.log.info('{} running_users'.format(running_users))
+ return running_users >= self.max_users_running
@gen.coroutine
def start(self, image=None):
@@ -292,6 +303,8 @@ def start(self, image=None):
self._is_building = True
self._is_empty = False
try:
+ if self.are_too_many_users():
+ raise Exception('Sorry, there are too many users')
f = self.build_image()
image_name = yield gen.with_timeout(
timedelta(seconds=self.start_timeout),
@@ -327,7 +340,10 @@ def start(self, image=None):
message = "Container doesn't have jupyter-singleuser inside"
elif 'Cannot locate specified Dockerfile' in message:
message = "Your repo doesn't include Dockerfile"
- self._add_to_log('Something went wrong during building. Error: %s' % message)
+ if message.startswith('Sorry'):
+ self._add_to_log(message)
+ else:
+ self._add_to_log('Something went wrong during building. Error: %s' % message)
yield self.notify_about_fail(message)
raise e
finally:
@@ -379,7 +395,7 @@ def stop(self, now=False):
"Removing container %s (id: %s)",
self.container_name, self.container_id[:7])
# remove the container, as well as any associated volumes
- yield self.docker('remove_container', self.container_id, v=True)
+ yield self.docker('remove_container', self.container_id, v=True, force=True)
self.clear_state()
@@ -6,6 +6,14 @@
class SpawnHandler(default_handlers.SpawnHandler):
+ @gen.coroutine
+ def count_running_users(self):
+ running_users = 0
+ for user_id, user in self.users.items():
+ if user.running:
+ running_users += 1
+ return running_users
+
def _render_form(self, message=''):
user = self.get_current_user()
metrica = MetricaIdsMixin()
@@ -22,9 +30,13 @@ def _render_form(self, message=''):
@gen.coroutine
def _spawn(self, user, form_options):
+ running_users = yield self.count_running_users()
self.redirect('/user/%s' % user.name)
try:
options = user.spawner.options_from_form(form_options)
+ options.update({
+ 'running_users': running_users
+ })
yield self.spawn_single_user(user, options=options)
# if user set another access token (for example he logged with github
# and clones from bitbucket)

No commit comments for this range