Skip to content
This repository has been archived by the owner on Apr 29, 2021. It is now read-only.

Commit

Permalink
Merge pull request #45 from NERSC/18-12
Browse files Browse the repository at this point in the history
Branch for 18-12 deployment
  • Loading branch information
rcthomas authored Dec 13, 2018
2 parents 8692a73 + fc489b6 commit 35b6e88
Show file tree
Hide file tree
Showing 48 changed files with 458 additions and 143 deletions.
4 changes: 0 additions & 4 deletions base/build.sh

This file was deleted.

9 changes: 5 additions & 4 deletions base/Dockerfile → jupyter-base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ RUN \

RUN \
curl -s -o /tmp/miniconda3.sh https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
bash /tmp/miniconda3.sh -f -b -p /opt/anaconda3 && \
rm -rf /tmp/anaconda3.sh && \
/opt/anaconda3/bin/conda update --yes conda && \
/opt/anaconda3/bin/conda install --yes \
bash /tmp/miniconda3.sh -f -b -p /opt/anaconda3 && \
rm -rf /tmp/miniconda3.sh && \
echo "python 3.6.*" >> /opt/anaconda3/conda-meta/pinned && \
/opt/anaconda3/bin/conda update --yes conda && \
/opt/anaconda3/bin/conda install --yes \
alembic \
decorator \
jinja2 \
Expand Down
7 changes: 7 additions & 0 deletions jupyter-base/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

branch=$(git symbolic-ref --short HEAD)

docker build \
--no-cache \
--tag registry.spin.nersc.gov/das/jupyter-base.$branch:latest .
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG branch=unknown

FROM registry.spin.nersc.gov/das/jupyterhub-base.${branch}:latest
FROM registry.spin.nersc.gov/das/jupyter-base.${branch}:latest
LABEL maintainer="Rollin Thomas <rcthomas@lbl.gov>"
WORKDIR /srv

Expand Down
4 changes: 2 additions & 2 deletions jupyter-dev/build.sh → jupyter-dev-nersc/web/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ branch=$(git symbolic-ref --short HEAD)

docker build \
--build-arg branch=$branch \
--no-cache \
--tag registry.spin.nersc.gov/das/jupyterhub-jupyter-dev.$branch:latest .
"$@" \
--tag registry.spin.nersc.gov/das/jupyter-dev-nersc-web.$branch:latest .
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Configuration file for jupyterhub.

import os
import sys

import requests

def comma_split(string):
"""Handle env variables that may be None, empty string, or have spaces"""
Expand All @@ -13,6 +16,13 @@ def comma_split(string):
else:
return list()

ip = requests.get('https://v4.ifconfig.co/json').json()['ip']

#bindir = '/global/common/gerty/software/python/3.6-anaconda-5.2/bin/'
bindir = '/global/common/cori/software/python/3.6-anaconda-5.2/bin/'
if 'BASE_PATH' in os.environ:
bindir = os.path.join(os.environ['BASE_PATH'], 'bin')

#------------------------------------------------------------------------------
# Application(SingletonConfigurable) configuration
#------------------------------------------------------------------------------
Expand Down Expand Up @@ -91,6 +101,7 @@ def comma_split(string):
# where `handler` is the calling web.RequestHandler,
# and `data` is the POST form data from the login page.
#c.JupyterHub.authenticator_class = 'jupyterhub.auth.PAMAuthenticator'
c.JupyterHub.authenticator_class = 'sshapiauthenticator.auth.SSHAPIAuthenticator'

## The base URL of the entire application.
#
Expand Down Expand Up @@ -155,6 +166,7 @@ def comma_split(string):

## Number of days for a login cookie to be valid. Default is two weeks.
#c.JupyterHub.cookie_max_age_days = 14
c.JupyterHub.cookie_max_age_days = 0.5

## The cookie secret to use to encrypt cookies.
#
Expand All @@ -175,6 +187,9 @@ def comma_split(string):

## url for the database. e.g. `sqlite:///jupyterhub.sqlite`
#c.JupyterHub.db_url = 'sqlite:///jupyterhub.sqlite'
c.JupyterHub.db_url = 'postgresql://jupyterhub:{}@db:5432/jupyterhub'.format(
os.getenv('POSTGRES_PASSWORD')
)

## log all database transactions. This has A LOT of output
#c.JupyterHub.debug_db = False
Expand Down Expand Up @@ -265,6 +280,7 @@ def comma_split(string):
# See `hub_connect_ip` for cases where the bind and connect address should
# differ, or `hub_bind_url` for setting the full bind URL.
#c.JupyterHub.hub_ip = '127.0.0.1'
c.JupyterHub.hub_ip = '0.0.0.0'

## The internal port for the Hub process.
#
Expand All @@ -286,7 +302,6 @@ def comma_split(string):
# .. deprecated: 0.9
# Use JupyterHub.bind_url
#c.JupyterHub.ip = ''
c.JupyterHub.ip = '0.0.0.0'

## Supply extra arguments that will be passed to Jinja environment.
#c.JupyterHub.jinja_environment_options = {}
Expand Down Expand Up @@ -320,7 +335,6 @@ def comma_split(string):

## DEPRECATED since version 0.8 : Use ConfigurableHTTPProxy.api_url
#c.JupyterHub.proxy_api_ip = ''
c.JupyterHub.proxy_api_ip = '127.0.0.1'

## DEPRECATED since version 0.8 : Use ConfigurableHTTPProxy.api_url
#c.JupyterHub.proxy_api_port = 0
Expand Down Expand Up @@ -377,13 +391,19 @@ def comma_split(string):
'name': 'cull-idle',
'admin': True,
'command': 'cull_idle_servers.py --timeout=43200'.split(),
},
{
'name': 'announcement',
'url': 'http://127.0.0.1:8888',
'command': ["python", "-m", "announcement"],
}
]

## The class to use for spawning single-user servers.
#
# Should be a subclass of Spawner.
#c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'
c.JupyterHub.spawner_class = 'sshspawner.sshspawner.SSHSpawner'

## Path to SSL certificate file for the public facing interface of the proxy
#
Expand Down Expand Up @@ -422,6 +442,7 @@ def comma_split(string):

## Paths to search for jinja templates, before using the default templates.
#c.JupyterHub.template_paths = []
c.JupyterHub.template_paths = ["templates"]

## Extra variables to be passed into jinja templates
#c.JupyterHub.template_vars = {}
Expand Down Expand Up @@ -488,7 +509,7 @@ def comma_split(string):
# environment variables. Most, including the default, do not. Consult the
# documentation for your spawner to verify!
#c.Spawner.cmd = ['jupyterhub-singleuser']
c.Spawner.cmd = ['/opt/anaconda3/bin/jupyter-labhub']
c.Spawner.cmd = [os.path.join(bindir, 'jupyter-labhub')]

## Maximum number of consecutive failures to allow before shutting down
# JupyterHub.
Expand Down Expand Up @@ -592,7 +613,7 @@ def comma_split(string):
# The JupyterHub proxy implementation should be able to send packets to this
# interface.
#c.Spawner.ip = ''
c.Spawner.ip = '127.0.0.1'
c.Spawner.ip = '0.0.0.0'

## Minimum number of bytes a single-user notebook server is guaranteed to have
# available.
Expand Down Expand Up @@ -676,6 +697,7 @@ def comma_split(string):
# JupyterHub modifies its own state accordingly and removes appropriate routes
# from the configurable proxy.
#c.Spawner.poll_interval = 30
c.Spawner.poll_interval = 900

## The port for single-user servers to listen on.
#
Expand Down Expand Up @@ -930,7 +952,6 @@ def comma_split(string):

## The name of the PAM service to use for authentication
#c.PAMAuthenticator.service = 'login'
c.PAMAuthenticator.service = 'jupyterhub'

#------------------------------------------------------------------------------
# CryptKeeper(SingletonConfigurable) configuration
Expand All @@ -945,3 +966,51 @@ def comma_split(string):

## The number of threads to allocate for encryption
#c.CryptKeeper.n_threads = 2

#------------------------------------------------------------------------------
# SSHAPIAuthenticator(Authenticator) configuration
#------------------------------------------------------------------------------

c.SSHAPIAuthenticator.server = 'https://sshproxy.nersc.gov/create_pair/jupyter/'
c.SSHAPIAuthenticator.skey = os.environ.get('SKEY')
c.SSHAPIAuthenticator.cert_path = '/certs'

#------------------------------------------------------------------------------
# SSHSpawner(Spawner) configuration
#------------------------------------------------------------------------------

c.SSHSpawner.hub_api_url = "http://{}:8081/hub/api".format(ip)
c.SSHSpawner.path = bindir + ':/global/common/cori/das/jupyterhub/:/usr/common/usg/bin:/usr/bin:/bin'
c.SSHSpawner.ssh_keyfile = '/certs/{username}.key'

import asyncssh, random
from tornado import web

c.SSHSpawner.remote_hosts = ['cori19-224.nersc.gov']
#c.SSHSpawner.remote_host = ['gert01-224.nersc.gov']
c.SSHSpawner.remote_port_command = "python -c 'import socket; s=socket.socket(); s.bind((\"\", 0)); print(s.getsockname()[1]); s.close()'"

# async def setup(spawner):
# username = spawner.user.name
# remote_host = random.choice(spawner.remote_hosts)
# keyfile = spawner.ssh_keyfile.format(username=username)
# certfile = keyfile + "-cert.pub"
# k = asyncssh.read_private_key(keyfile)
# c = asyncssh.read_certificate(certfile)
# print(username, remote_host, keyfile, certfile)
# async with asyncssh.connect(remote_host,
# username=username,
# client_keys=[(k,c)],
# known_hosts=None) as conn:
# result = await conn.run("myquota -c")
# retcode = result.exit_status
# result = await conn.run(spawner.remote_port_command)
# remote_port = int(result.stdout)
# if retcode:
# e = web.HTTPError(507,reason="Insufficient Storage")
# e.my_message = "There is insufficient space in your home directory; please clear up some files and try again."
# raise e
# spawner.remote_host = remote_host
# spawner.port = remote_port
#
# c.Spawner.pre_spawn_hook = setup
2 changes: 1 addition & 1 deletion jupyter-localhost/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.spin.nersc.gov/das/jupyterhub-base:latest
FROM registry.spin.nersc.gov/das/jupyter-base:latest
MAINTAINER Rollin Thomas <rcthomas@lbl.com>

# Python 3 Anaconda and additional packages
Expand Down
73 changes: 47 additions & 26 deletions jupyter-spin/Dockerfile → jupyter-nersc/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
FROM registry.spin.nersc.gov/das/jupyterhub-base.gaffer:latest
ARG branch=unknown

FROM registry.spin.nersc.gov/das/jupyter-base.${branch}:latest
LABEL maintainer="Rollin Thomas <rcthomas@lbl.gov>"
WORKDIR /srv

# Additional Ubuntu packages

RUN \
apt-get update && \
apt-get install --yes \
csh \
dvipng \
ldap-utils \
libnss-ldapd \
libpam-ldap \
nscd \
rsyslog \
supervisor \
texlive-xetex \
zsh
apt-get --yes install \
csh \
ldap-utils \
libnss-ldapd \
libpam-ldap \
nscd \
openssh-server \
supervisor

# Python 3 Anaconda and additional packages

##### RUN \
##### /opt/anaconda3/bin/conda update --yes conda && \
##### /opt/anaconda3/bin/conda install --yes \
##### ipykernel \
##### ipywidgets \
##### jupyterlab \
##### notebook && \
##### /opt/anaconda3/bin/ipython kernel install && \
##### /opt/anaconda3/bin/conda clean --yes --all
#####
##### # Typical extension
#####
##### RUN \
##### /opt/anaconda3/bin/jupyter nbextension enable --sys-prefix --py widgetsnbextension

ADD packages3.txt /tmp/packages3.txt
RUN \
/opt/anaconda3/bin/conda update --yes conda && \
Expand All @@ -31,7 +45,7 @@ RUN \

ADD packages2.txt /tmp/packages2.txt
RUN \
curl -s -o /tmp/miniconda2.sh https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh && \
wget -q -O /tmp/miniconda2.sh https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh && \
bash /tmp/miniconda2.sh -f -b -p /opt/anaconda2 && \
rm /tmp/miniconda2.sh && \
/opt/anaconda2/bin/conda update --yes conda && \
Expand All @@ -40,7 +54,20 @@ RUN \
/opt/anaconda2/bin/ipython kernel install && \
/opt/anaconda2/bin/conda clean --yes --all

# PAM, LDAP
# For ssh auth API

ADD NERSC-keys-api /usr/lib/nersc-ssh-keys/
RUN chmod a+x /usr/lib/nersc-ssh-keys/NERSC-keys-api

# For sshd

RUN \
mkdir -p /var/run/sshd && \
echo "AuthorizedKeysCommand /usr/lib/nersc-ssh-keys/NERSC-keys-api" >> /etc/ssh/sshd_config && \
echo "AuthorizedKeysCommandUser nobody" >> /etc/ssh/sshd_config && \
echo "TrustedUserCAKeys /etc/user_ca.pub" >> /etc/ssh/sshd_config

# For PAM/LDAP

COPY etc/ /etc/

Expand All @@ -53,10 +80,9 @@ RUN \
ln -s /global/common/datatran /usr/common && \
echo "datatran" > /etc/clustername

# Jupyterhub/lab features
# JupyterHub/lab features

RUN \
conda install --yes jupyterlab=0.33.8 && \
pip install --no-cache-dir ipympl && \
jupyter nbextension enable --sys-prefix --py widgetsnbextension && \
jupyter labextension install \
Expand All @@ -66,19 +92,14 @@ RUN \
@jupyterlab/toc \
jupyterlab_bokeh

# Not sure we need this

RUN \
/opt/anaconda2/bin/jupyter nbextension enable --sys-prefix --py widgetsnbextension

# Config and entrypoint script

ADD docker-entrypoint.sh jupyterhub_config.py /srv/

WORKDIR /srv
# Get port script

# TEMPORARILY HERE: Set up supervisord
ADD get_port.py /opt/anaconda3/bin/

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Supervisord to launch sshd and nslcd

ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
7 changes: 7 additions & 0 deletions jupyter-nersc/app/NERSC-keys-api
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

URL=https://sshproxy.nersc.gov/get_keys
USER=$1


curl $URL/$USER
4 changes: 2 additions & 2 deletions jupyter-spin/build.sh → jupyter-nersc/app/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ branch=$(git symbolic-ref --short HEAD)

docker build \
--build-arg branch=$branch \
--no-cache \
--tag registry.spin.nersc.gov/das/jupyterhub-jupyter-spin.$branch:latest .
"$@" \
--tag registry.spin.nersc.gov/das/jupyter-nersc-app.$branch:latest .
2 changes: 2 additions & 0 deletions jupyter-nersc/app/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
exec "$@"
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,3 @@ nss_initgroups_ignoreusers ALLLOCAL
idle_timelimit 240

filter passwd (&(objectClass=posixAccount)(authorizedService=ssh))

log syslog debug
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions jupyter-nersc/app/etc/user_ca.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2yKBpvRbdD9MWiu+7wg17vBsKy46AjjuL27DmdpDYiCqRE2mN0om9b0jn4eI91RGykbcRa9wUKJ2qaD0zsD08A8HM+R14H4UsZ5hi7S+xGqscJH7uTmXy5Igo5xEOahS9Z+ecgonDCgWKJnbd/FRu4vITYXrvTlIIGHGRBYj0GzbgLHBzedoMaGNRwhVyadH2SGRaZCgbH+Swevzy0GwYfZJA9zd7EX0jiAClkSYcflIOsygmI3gHv+b35mrvXcHDeQOR/wg8knfpSiFLCkVDpfgnj27Lemzxe6k61Brhv9CUiq+t7WApVDBovhdXZn6pBg+OKeDk1G1OLvRbxJ2bw== dunford@muppet.nersc.gov
8 changes: 8 additions & 0 deletions jupyter-nersc/app/get_port.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env python

import socket

sock = socket.socket()
sock.bind(('', 0))
print(sock.getsockname()[1])
sock.close()
File renamed without changes.
Loading

0 comments on commit 35b6e88

Please sign in to comment.