mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-07 10:04:07 +00:00
jupyterhub-1219 Enhancement: automatically create a directory for the user after successful login
This commit is contained in:
130
examples/bootstrap-script/README.md
Normal file
130
examples/bootstrap-script/README.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Bootstrapping your users
|
||||
|
||||
Before spawning a notebook to the user, it could be useful to
|
||||
do some preparation work in a bootstrapping process.
|
||||
|
||||
Common use cases are:
|
||||
|
||||
*Providing writeable storage for LDAP users*
|
||||
|
||||
Your Jupyterhub is configured to use the LDAPAuthenticator and DockerSpawer.
|
||||
|
||||
* The user has no file directory on the host since your are using LDAP.
|
||||
* When a user has no directory and DockerSpawner wants to mount a volume,
|
||||
the spawner will use docker to create a directory.
|
||||
Since the docker daemon is running as root, the generated directory for the volume
|
||||
mount will not be writeable by the `jovyan` user inside of the container.
|
||||
For the directory to be useful to the user, the permissions on the directory
|
||||
need to be modified for the user to have write access.
|
||||
|
||||
*Prepopulating Content*
|
||||
|
||||
Another use would be to copy initial content, such as tutorial files or reference
|
||||
material, into the user's space when a notebook server is newly spawned.
|
||||
|
||||
You can define your own bootstrap process by implementing a `pre_spawn_hook` on any spawner.
|
||||
The Spawner itself is passed as parameter to your hook and you can easily get the contextual information out of the spawning process.
|
||||
|
||||
If you implement a hook, make sure that it is *idempotent*. It will be executed every time
|
||||
a notebook server is spawned to the user. That means you should somehow
|
||||
ensure that things which should run only once are not running again and again.
|
||||
For example, before you create a directory, check if it exists.
|
||||
|
||||
Bootstrapping examples:
|
||||
|
||||
### Example #1 - Create a user directory
|
||||
|
||||
Create a directory for the user, if none exists
|
||||
|
||||
```python
|
||||
|
||||
# in jupyterhub_config.py
|
||||
import os
|
||||
def create_dir_hook(spawner):
|
||||
username = spawner.user.name # get the username
|
||||
volume_path = os.path.join('/volumes/jupyterhub', username)
|
||||
if not os.path.exists(volume_path):
|
||||
# create a directory with umask 0755
|
||||
# hub and container user must have the same UID to be writeable
|
||||
# still readable by other users on the system
|
||||
os.mkdir(volume_path, 0o755)
|
||||
# now do whatever you think your user needs
|
||||
# ...
|
||||
pass
|
||||
|
||||
# attach the hook function to the spawner
|
||||
c.Spawner.pre_spawn_hook = create_dir_hook
|
||||
```
|
||||
|
||||
### Example #2 - Run a shell script
|
||||
|
||||
You can specify a plain ole' shell script (or any other executable) to be run
|
||||
by the bootstrap process.
|
||||
|
||||
For example, you can execute a shell script and as first parameter pass the name
|
||||
of the user:
|
||||
|
||||
```python
|
||||
|
||||
# in jupyterhub_config.py
|
||||
from subprocess import check_call
|
||||
import os
|
||||
def my_script_hook(spawner):
|
||||
username = spawner.user.name # get the username
|
||||
script = os.path.join(os.path.dirname(__file__), 'bootstrap.sh')
|
||||
check_call([script, username])
|
||||
|
||||
# attach the hook function to the spawner
|
||||
c.Spawner.pre_spawn_hook = my_script_hook
|
||||
|
||||
```
|
||||
|
||||
Here's an example on what you could do in your shell script. See also
|
||||
`/examples/bootstrap-script/`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Bootstrap example script
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
# - The first parameter for the Bootstrap Script is the USER.
|
||||
USER=$1
|
||||
if ["$USER" == ""]; then
|
||||
exit 1
|
||||
fi
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# This example script will do the following:
|
||||
# - create one directory for the user $USER in a BASE_DIRECTORY (see below)
|
||||
# - create a "tutorials" directory within and download and unzip
|
||||
# the PythonDataScienceHandbook from GitHub
|
||||
|
||||
# Start the Bootstrap Process
|
||||
echo "bootstrap process running for user $USER ..."
|
||||
|
||||
# Base Directory: All Directories for the user will be below this point
|
||||
BASE_DIRECTORY=/volumes/jupyterhub/
|
||||
|
||||
# User Directory: That's the private directory for the user to be created, if none exists
|
||||
USER_DIRECTORY=$BASE_DIRECTORY/$USER
|
||||
|
||||
if [ -d "$USER_DIRECTORY" ]; then
|
||||
echo "...directory for user already exists. skipped"
|
||||
exit 0 # all good. nothing to do.
|
||||
else
|
||||
echo "...creating a directory for the user: $USER_DIRECTORY"
|
||||
mkdir $USER_DIRECTORY
|
||||
|
||||
echo "...initial content loading for user ..."
|
||||
mkdir $USER_DIRECTORY/tutorials
|
||||
cd $USER_DIRECTORY/tutorials
|
||||
wget https://github.com/jakevdp/PythonDataScienceHandbook/archive/master.zip
|
||||
unzip -o master.zip
|
||||
rm master.zip
|
||||
fi
|
||||
|
||||
exit 0
|
||||
```
|
48
examples/bootstrap-script/bootstrap.sh
Executable file
48
examples/bootstrap-script/bootstrap.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bootstrap example script
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
# - The first parameter for the Bootstrap Script is the USER.
|
||||
USER=$1
|
||||
if ["$USER" == ""]; then
|
||||
exit 1
|
||||
fi
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# This example script will do the following:
|
||||
# - create one directory for the user $USER in a BASE_DIRECTORY (see below)
|
||||
# - create a "tutorials" directory within and download and unzip the PythonDataScienceHandbook from GitHub
|
||||
|
||||
# Start the Bootstrap Process
|
||||
echo "bootstrap process running for user $USER ..."
|
||||
|
||||
# Base Directory: All Directories for the user will be below this point
|
||||
BASE_DIRECTORY=/volumes/jupyterhub
|
||||
|
||||
# User Directory: That's the private directory for the user to be created, if none exists
|
||||
USER_DIRECTORY=$BASE_DIRECTORY/$USER
|
||||
|
||||
if [ -d "$USER_DIRECTORY" ]; then
|
||||
echo "...directory for user already exists. skipped"
|
||||
exit 0 # all good. nothing to do.
|
||||
else
|
||||
echo "...creating a directory for the user: $USER_DIRECTORY"
|
||||
mkdir $USER_DIRECTORY
|
||||
|
||||
# mkdir did not succeed?
|
||||
if [ $? -ne 0 ] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "...initial content loading for user ..."
|
||||
mkdir $USER_DIRECTORY/tutorials
|
||||
cd $USER_DIRECTORY/tutorials
|
||||
wget https://github.com/jakevdp/PythonDataScienceHandbook/archive/master.zip
|
||||
unzip -o master.zip
|
||||
rm master.zip
|
||||
fi
|
||||
|
||||
exit 0
|
26
examples/bootstrap-script/jupyterhub_config.py
Normal file
26
examples/bootstrap-script/jupyterhub_config.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Example for a Spawner.pre_spawn_hook
|
||||
# create a directory for the user before the spawner starts
|
||||
|
||||
import os
|
||||
def create_dir_hook(spawner):
|
||||
username = spawner.user.name # get the username
|
||||
volume_path = os.path.join('/volumes/jupyterhub', username)
|
||||
if not os.path.exists(volume_path):
|
||||
os.mkdir(volume_path, 0o755)
|
||||
# now do whatever you think your user needs
|
||||
# ...
|
||||
|
||||
# attach the hook function to the spawner
|
||||
c.Spawner.pre_spawn_hook = create_dir_hook
|
||||
|
||||
# Use the DockerSpawner to serve your users' notebooks
|
||||
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
|
||||
from jupyter_client.localinterfaces import public_ips
|
||||
c.JupyterHub.hub_ip = public_ips()[0]
|
||||
c.DockerSpawner.hub_ip_connect = public_ips()[0]
|
||||
c.DockerSpawner.container_ip = "0.0.0.0"
|
||||
|
||||
# You can now mount the volume to the docker container as we've
|
||||
# made sure the directory exists
|
||||
c.DockerSpawner.volumes = { '/volumes/jupyterhub/{username}/': '/home/jovyan/work' }
|
||||
|
Reference in New Issue
Block a user