From f35ca954d3a4259b90e62aeda18cd0383bed182c Mon Sep 17 00:00:00 2001 From: garciagenrique Date: Thu, 4 Sep 2025 10:08:24 +0200 Subject: [PATCH] update vre-swan-cern to 1.4.0 and clean repo --- vre-swan-cern/Dockerfile | 6 +- vre-swan-cern/python/jupyter_server_config.py | 46 ----- vre-swan/Dockerfile | 163 ------------------ vre-swan/README.md | 15 -- vre-swan/config/kernel.json | 11 -- vre-swan/patches/jupyter_server_proxy.diff | 26 --- .../python/configure_kernels_and_terminal.py | 75 -------- vre-swan/python/jupyter_server_config.py | 135 --------------- .../scripts/before-notebook.d/00_tools.sh | 10 -- .../scripts/before-notebook.d/01_storage.sh | 44 ----- .../before-notebook.d/02_environment.sh | 148 ---------------- vre-swan/scripts/others/userconfig.sh | 106 ------------ 12 files changed, 1 insertion(+), 784 deletions(-) delete mode 100644 vre-swan-cern/python/jupyter_server_config.py delete mode 100644 vre-swan/Dockerfile delete mode 100644 vre-swan/README.md delete mode 100644 vre-swan/config/kernel.json delete mode 100644 vre-swan/patches/jupyter_server_proxy.diff delete mode 100644 vre-swan/python/configure_kernels_and_terminal.py delete mode 100644 vre-swan/python/jupyter_server_config.py delete mode 100644 vre-swan/scripts/before-notebook.d/00_tools.sh delete mode 100644 vre-swan/scripts/before-notebook.d/01_storage.sh delete mode 100755 vre-swan/scripts/before-notebook.d/02_environment.sh delete mode 100644 vre-swan/scripts/others/userconfig.sh diff --git a/vre-swan-cern/Dockerfile b/vre-swan-cern/Dockerfile index c52f3e47..8637667c 100644 --- a/vre-swan-cern/Dockerfile +++ b/vre-swan-cern/Dockerfile @@ -5,7 +5,7 @@ LABEL maintainer="swan-admins@cern.ch" ARG NB_UID="1000" ARG BUILD_TAG=daily ENV VERSION_DOCKER_IMAGE=$BUILD_TAG -ENV RUCIO_JUPYTERLAB_VERSION="1.3.1" +ENV RUCIO_JUPYTERLAB_VERSION="1.4.0" RUN echo "Building swan-cern image with tag ${VERSION_DOCKER_IMAGE} from parent tag ${VERSION_PARENT}." @@ -34,10 +34,6 @@ RUN pip install --no-deps --no-cache-dir rucio-jupyterlab==${RUCIO_JUPYTERLAB_VE RUN pip install --no-deps --no-cache-dir --target ${SWAN_LIB_DIR}/nb_term_lib \ swandaskcluster==3.1.0 -# Overwrite Python configuration, including section for the VRE -# Add jupyter notebook configuration -ADD python/jupyter_server_config.py /home/${NB_USER}/.jupyter/jupyter_server_config.py - # Add helper scripts COPY scripts/others/* /srv/singleuser/ diff --git a/vre-swan-cern/python/jupyter_server_config.py b/vre-swan-cern/python/jupyter_server_config.py deleted file mode 100644 index e3f867db..00000000 --- a/vre-swan-cern/python/jupyter_server_config.py +++ /dev/null @@ -1,46 +0,0 @@ -import os -from site import getsitepackages - -home = os.environ.get("HOME") -jupyter_path = os.environ.get("JUPYTER_PATH", f"{home}/.local/share/jupyter") - -c.NotebookNotary.db_file = f"{jupyter_path}/nbsignatures.db" -c.NotebookNotary.secret_file = f"{jupyter_path}/notebook_secret" - -# Configure jupyter lab to start in the HOME of the user -# which is usually EOS for CERN users. -c.ServerApp.root_dir = home - -c.ServerApp.contents_manager_class = "swancontents.filemanager.SwanEosFileManager" -# To allow deleting Projects, which are never empty because of .swancontents -c.FileContentsManager.always_delete_dir = True - -cernbox_oauth_id = os.environ.get("CERNBOX_OAUTH_ID", "cernbox-service") -eos_oauth_id = os.environ.get("EOS_OAUTH_ID", "eos-service") -oauth2_file = os.environ.get("OAUTH2_FILE", "") -oauth_inspection_endpoint = os.environ.get("OAUTH_INSPECTION_ENDPOINT", "") -c.SwanOauthRenew.files = [ - ("/tmp/swan_oauth.token", "access_token", "{token}"), - ("/tmp/cernbox_oauth.token", f"exchanged_tokens/{cernbox_oauth_id}", "{token}"), - (oauth2_file, f"exchanged_tokens/{eos_oauth_id}", "oauth2:{token}:" + oauth_inspection_endpoint) -] - -# Toggle JupyterLab based on user preference -use_jupyterlab = os.environ.get('SWAN_USE_JUPYTERLAB', 'false').lower() == 'true' -if use_jupyterlab: - c.ServerApp.default_url = '/lab' -else: - c.ServerApp.default_url = '/projects' - -user = os.environ.get('USER') -# Change the HOME environment variable to the local user home instead of EOS -# to prevent xelatex from touching EOS during the PDF conversion and so -# reduce the time it takes to convert a PDF (including preventing timeouts). -c.PDFExporter.latex_command = ['env', f'HOME=/home/{user}' , 'xelatex', '-quiet', '{filename}'] - -# Configure path to SwanCustomenvironments template -for path in getsitepackages(): - candidate = os.path.join(path, "swancustomenvironments", "templates") - if os.path.isdir(candidate): - c.ServerApp.extra_template_paths = [candidate] - break diff --git a/vre-swan/Dockerfile b/vre-swan/Dockerfile deleted file mode 100644 index a434180e..00000000 --- a/vre-swan/Dockerfile +++ /dev/null @@ -1,163 +0,0 @@ -# Author: Danilo Piparo, Enric Tejedor, Pedro Maximino, Diogo Castro 2023 -# Copyright CERN -# This installs the SWAN packages to enable -# using Jupyter with EOS and CVMFS - -ARG VERSION_PARENT=v0.0.5 - -FROM gitlab-registry.cern.ch/swan/docker-images/jupyter/base:${VERSION_PARENT} - -LABEL maintainer="swan-admins@cern.ch" - -ARG NB_USER="jovyan" -ARG NB_UID="1000" -ARG BUILD_TAG=daily -ENV VERSION_DOCKER_IMAGE=$BUILD_TAG - -RUN echo "Building swan image with tag ${VERSION_DOCKER_IMAGE} from parent tag ${VERSION_PARENT}." - -# Directory to expose SWAN extensions and libraries -ENV SWAN_LIB_DIR=/usr/local/lib/swan - -# Switch to superuser to install packages -USER root - -# Install required dnf packages -RUN dnf install -y \ - # Required by before-notebook scripts - bc \ - # Required for key4hep - environment-modules \ - # The R configuration of the LCG release requires - # the en_US.UTF-8 encoding - glibc-langpack-en \ - # General utilities - file \ - git \ - htop \ - nano \ - patch \ - unzip \ - which \ - # Texlive and fontconfig packages are used to convert - # notebooks into different formats - texlive \ - # Texlive packages necessary to convert notebooks - # into different formats that are not installed - # automatically as dependencies of texlive - texlive-adjustbox \ - texlive-tcolorbox \ - texlive-titling \ - texlive-type1cm \ - texlive-upquote \ - texlive-ulem \ - # Added to allow tex outputs to be converted to png - texlive-dvipng \ - fontconfig && \ - # Clear the dnf cache as we no longer need to install packages - dnf clean all && \ - rm -rf /var/cache/dnf - -# Install HEP_OSlibs -# This installs system packages for LCGs to work -RUN dnf --repofrompath=wlcg,'https://linuxsoft.cern.ch/wlcg/el9/$basearch/' install -y --nogpgcheck wlcg-repo -RUN dnf -y install HEP_OSlibs-9.2.3-1.el9 - -# Switch back to jovyan to avoid accidental container runs as root -USER ${NB_UID} - -# Pip is used to install this package because conda forge -# does not contain the latest version (v0.6.3) -RUN pip install --no-deps --no-cache-dir \ - jupyter_nbextensions_configurator==0.6.3 - -# Install python pip packages -RUN mamba install --yes \ - 'voila==0.5.5' \ - 'ipyparallel==8.6.1' \ - 'jupyter-server-proxy==4.1.0' \ - 'jupyter-resource-usage==1.1.0' \ - 'jupyterlab-git==0.51.1' \ - # Extensions required by jupyter server - 'webio-jupyter-extension==0.1.0' - -# Install all of our extensions -# Ignore (almost all) dependencies because they have already been installed or come from CVMFS -RUN pip install --no-deps --no-cache-dir \ - swancontents==2.1.14 \ - swanhelp==3.0.3 \ - swankernelenv==1.0.0 \ - swanoauthrenew==1.0.2 \ - swanshare==2.0.3 \ - swancustomenvironments==0.0.28 - -RUN pip install \ - # Required dependency for swanoauthrenew - PyJWT - -# Add Python 3 kernel configuration -RUN mkdir -p /home/${NB_USER}/.local/share/jupyter/kernels/python3 -ADD config/kernel.json /home/${NB_USER}/.local/share/jupyter/kernels/python3/kernel.json -RUN cp /opt/conda/share/jupyter/kernels/python3/logo* /home/${NB_USER}/.local/share/jupyter/kernels/python3/ - -# Python configuration -# Add jupyter notebook configuration -ADD python/jupyter_server_config.py /home/${NB_USER}/.jupyter/jupyter_server_config.py - -USER root - -# Create directories where we will store: -# - SWAN extensions and their dependencies (this path gets removed from -# notebooks by swankernelenv) -# - Libraries to be exposed to notebooks and terminals and their -# dependencies -RUN mkdir -p $SWAN_LIB_DIR/extensions && \ - mkdir -p $SWAN_LIB_DIR/nb_term_lib && \ - fix-permissions $SWAN_LIB_DIR && \ - chown ${NB_USER}:${NB_GID} $SWAN_LIB_DIR/nb_term_lib - -# Expose swankernelenv to the user environment in notebooks. -# swankernelenv removes the $SWAN_LIB_DIR/extensions directory from the PYTHONPATH -# when the notebook starts. Check EOF of userconfig.sh -RUN ln -s $(pip show swankernelenv | grep 'Location:' | awk '{print $2}')/swankernelenv $SWAN_LIB_DIR/extensions/ - -# Expose ipykernel and some of its dependencies to the user environment in -# notebooks, to enforce an ipykernel version that comes from the image, -# instead of from the LCG release. This ensures we run the Python kernels -# with the same package versions as the Jupyter server. -RUN ln -s $(pip show ipykernel | grep -oP 'Location: \K.*')/ipykernel ${SWAN_LIB_DIR}/extensions/ -RUN ln -s $(pip show jupyter_core | grep -oP 'Location: \K.*')/jupyter_core ${SWAN_LIB_DIR}/extensions/ -RUN ln -s $(pip show comm | grep -oP 'Location: \K.*')/comm ${SWAN_LIB_DIR}/extensions/ -RUN ln -s $(pip show debugpy | grep -oP 'Location: \K.*')/debugpy ${SWAN_LIB_DIR}/extensions/ - -# Enable extensions for classic UI -RUN jupyter nbclassic-extension install --py --system swanhelp && \ - jupyter nbclassic-extension enable --py --system swanhelp -RUN jupyter nbclassic-extension install --py --system swanshare && \ - jupyter nbclassic-extension enable --py --system swanshare -RUN jupyter nbclassic-extension install --py --system jupyter_nbextensions_configurator && \ - jupyter nbclassic-extension enable --py --system jupyter_nbextensions_configurator - -# User session configuration scripts -# Add scripts -COPY scripts/before-notebook.d/* /usr/local/bin/before-notebook.d/ - -# Grant scripts execution permissions -RUN chmod +x /usr/local/bin/before-notebook.d/* - -# Add python scripts -ADD python/configure_kernels_and_terminal.py /srv/singleuser/configure_kernels_and_terminal.py - -# Add scripts that are not executed automatically but are -# instead called by our scripts internally -RUN mkdir /srv/singleuser/scripts -COPY scripts/others/* /srv/singleuser/scripts - -# TEMPORARY: apply a patch to the jupyter server proxy handlers, -# while we wait for the release of a new version with it -ADD patches/jupyter_server_proxy.diff /tmp/jupyter_server_proxy.diff -RUN patch $(pip show jupyter-server-proxy | grep -oP 'Location: \K.*')/jupyter_server_proxy/handlers.py /tmp/jupyter_server_proxy.diff && \ - rm -f /tmp/jupyter_server_proxy.diff - -# Switch back to jovyan to avoid accidental container runs as root -USER ${NB_UID} \ No newline at end of file diff --git a/vre-swan/README.md b/vre-swan/README.md deleted file mode 100644 index ab5019a8..00000000 --- a/vre-swan/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## VRE-SWAN - - -This folder clones the content of the -[SWAN](https://github.com/swan-cern/jupyter-images/tree/main/swan) -directory within the [swan-cern/jupyter-images](https://github.com/swan-cern/jupyter-images) -repository, solely for VRE tessting purposes and the integration of the -[rucio-jupyterlab](https://github.com/rucio/jupyterlab-extension) within -SWAN infrastructure. - -The repository is cloned at commit [28cc817](https://github.com/swan-cern/jupyter-images/commit/28cc817573674ee7287bd077eacd35752e4747b5). - -Changes to the original project: - - `/scripts/others/userconfig.sh` --> Sourcing ESCAPE CVMFS repo - - `python/jupyter_server_config.py` --> workaround to add rucio instances configurations \ No newline at end of file diff --git a/vre-swan/config/kernel.json b/vre-swan/config/kernel.json deleted file mode 100644 index 48e2fa3a..00000000 --- a/vre-swan/config/kernel.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "display_name": "Python 3", - "language": "python", - "argv": [ - "python", - "-m", - "ipykernel", - "-f", - "{connection_file}" - ] -} \ No newline at end of file diff --git a/vre-swan/patches/jupyter_server_proxy.diff b/vre-swan/patches/jupyter_server_proxy.diff deleted file mode 100644 index 70cf761b..00000000 --- a/vre-swan/patches/jupyter_server_proxy.diff +++ /dev/null @@ -1,26 +0,0 @@ -From 40a37b3698ab1dfa6b5688312721262008196bb5 Mon Sep 17 00:00:00 2001 -From: Diogo Castro -Date: Thu, 7 Dec 2023 12:30:49 +0100 -Subject: [PATCH] Only format a proxy environment once - -It was doing double formatting, which broke when passing environment variables with escaped strings (i.e {{var}}). ---- - jupyter_server_proxy/handlers.py | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/jupyter_server_proxy/handlers.py b/jupyter_server_proxy/handlers.py -index db57222b..2890dc3a 100644 ---- a/jupyter_server_proxy/handlers.py -+++ b/jupyter_server_proxy/handlers.py -@@ -654,9 +654,7 @@ def _render_template(self, value): - def _realize_rendered_template(self, attribute): - """Call any callables, then render any templated values.""" - if callable(attribute): -- attribute = self._render_template( -- call_with_asked_args(attribute, self.process_args) -- ) -+ attribute = call_with_asked_args(attribute, self.process_args) - return self._render_template(attribute) - - @web.authenticated - diff --git a/vre-swan/python/configure_kernels_and_terminal.py b/vre-swan/python/configure_kernels_and_terminal.py deleted file mode 100644 index ff3a3de1..00000000 --- a/vre-swan/python/configure_kernels_and_terminal.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -Writes kernel.json and terminal .bash_profile environment variables -from the current process environment -""" - -import json -import logging -import os -import re -import shutil - -SWAN_ENV_FILE = os.environ["SWAN_ENV_FILE"] -KERNEL_DIR = os.environ["KERNEL_DIR"] -HOME = os.environ["HOME"] -PYTHONEXECPATH = shutil.which(f"python3") - - -def modify_python_argv(kernel_json): - """Make sure that `python` points to the correct binary from CVMFS""" - if re.match(r"python[0-9.]*", kernel_json["argv"][0]): - kernel_json["argv"][0] = PYTHONEXECPATH - - -def configure_kernels(): - """Writes kernel.json with env and argv from software stack""" - kernel_json_file_names = [ - f"{KERNEL_DIR}/{kernel_name}/kernel.json" - for kernel_name in os.listdir(KERNEL_DIR) - ] - for kernel_json_file in kernel_json_file_names: - kernel_json = None - with open(kernel_json_file, "r") as file: - kernel_json = json.loads(file.read()) - - kernel_json["env"] = kernel_json.get("env", {}) | dict(os.environ) - modify_python_argv(kernel_json) - with open(kernel_json_file, "w") as file: - file.write(json.dumps(kernel_json, indent=4)) - - -def configure_terminal(): - """Writes bash profile with environment from software stack""" - with open(SWAN_ENV_FILE, "w") as terminal_environment_file: - for key, val in dict(os.environ).items(): - if key == "SUDO_COMMAND": - continue - if key == "TERM": # prevent TERM=unknown from being injected in the env - continue - if key == "PYTHONPATH": - val = re.sub("/usr/local/lib/swan/(extensions/)?:", "", val) - terminal_environment_file.write(f'export {key}="{val}"\n') - - terminal_environment_file.writelines( - [ - f'alias python="{PYTHONEXECPATH}"\n', - # Setting up colors - "alias ls='ls --color'\n", - "alias grep='grep --color'\n", - # There's no JupyterLab setting for the terminal directory, so we - # set it here to always be HOME - f"cd {HOME}\n" - ] - ) - - -if __name__ == "__main__": - logging.basicConfig( - format="[%(levelname)s %(asctime)s.%(msecs)03d %(filename)s:%(lineno)d] %(message)s", - level=logging.INFO, - datefmt="%Y-%m-%d %H:%M:%S", - ) - - logging.info("Configuring kernelspecs and terminal profiles") - configure_terminal() - configure_kernels() diff --git a/vre-swan/python/jupyter_server_config.py b/vre-swan/python/jupyter_server_config.py deleted file mode 100644 index 56ebf521..00000000 --- a/vre-swan/python/jupyter_server_config.py +++ /dev/null @@ -1,135 +0,0 @@ -import os -import json -from site import getsitepackages - -home = os.environ.get("HOME") -jupyter_path = os.environ.get("JUPYTER_PATH", f"{home}/.local/share/jupyter") - -c.NotebookNotary.db_file = f"{jupyter_path}/nbsignatures.db" -c.NotebookNotary.secret_file = f"{jupyter_path}/notebook_secret" - -# Configure jupyter lab to start in the HOME of the user -# which is usually EOS for CERN users. -c.ServerApp.root_dir = home - -c.ServerApp.contents_manager_class = "swancontents.filemanager.SwanEosFileManager" -# To allow deleting Projects, which are never empty because of .swancontents -c.FileContentsManager.always_delete_dir = True - -cernbox_oauth_id = os.environ.get("CERNBOX_OAUTH_ID", "cernbox-service") -eos_oauth_id = os.environ.get("EOS_OAUTH_ID", "eos-service") -oauth2_file = os.environ.get("OAUTH2_FILE", "") -oauth_inspection_endpoint = os.environ.get("OAUTH_INSPECTION_ENDPOINT", "") -c.SwanOauthRenew.files = [ - ("/tmp/swan_oauth.token", "access_token", "{token}"), - ("/tmp/cernbox_oauth.token", f"exchanged_tokens/{cernbox_oauth_id}", "{token}"), - (oauth2_file, f"exchanged_tokens/{eos_oauth_id}", "oauth2:{token}:" + oauth_inspection_endpoint) -] - -# Toggle JupyterLab based on user preference -use_jupyterlab = os.environ.get('SWAN_USE_JUPYTERLAB', 'false').lower() == 'true' -if use_jupyterlab: - c.ServerApp.default_url = '/lab' -else: - c.ServerApp.default_url = '/projects' - -user = os.environ.get('USER') -# Change the HOME environment variable to the local user home instead of EOS -# to prevent xelatex from touching EOS during the PDF conversion and so -# reduce the time it takes to convert a PDF (including preventing timeouts). -c.PDFExporter.latex_command = ['env', f'HOME=/home/{user}' , 'xelatex', '-quiet', '{filename}'] - -# Configure path to SwanCustomenvironments template -for path in getsitepackages(): - candidate = os.path.join(path, "swancustomenvironments", "templates") - if os.path.isdir(candidate): - c.ServerApp.extra_template_paths = [candidate] - break - -# CERN-VRE - Configure the JupyterLab server - TRIGGERED TO ALWAYS WORK -use_rucio_extension = os.environ.get('USE_RUCIO_EXTENSION', 'true').lower() == 'true' -if use_rucio_extension: - - def write_jupyterlab_config(): - dir_config_jupyterlab = os.getenv('JUPYTER_CONFIG_DIR', - os.path.join(os.getenv('HOME'), '.jupyter') - ) - file_server_config = os.path.join(dir_config_jupyterlab, 'jupyter_server_config.json') - - if not os.path.exists(dir_config_jupyterlab): - os.makedirs( dir_config_jupyterlab, exist_ok=True) - elif os.path.isfile(file_server_config) : - with open(file_server_config, "r") as config_file: - config_payload = config_file.read() - - try: - config_json = json.loads(config_payload) - except: - config_json = {} - - escape_config = { - "name": os.getenv('RUCIO_NAME', 'vre-rucio.cern.ch'), - "display_name": os.getenv('RUCIO_DISPLAY_NAME', 'ESCAPE Rucio instance'), - "rucio_base_url": os.getenv('RUCIO_BASE_URL', 'https://vre-rucio.cern.ch'), - "rucio_auth_url": os.getenv('RUCIO_AUTH_URL', 'https://vre-rucio-auth.cern.ch'), - "rucio_webui_url": os.getenv('RUCIO_WEBUI_URL', 'https://vre-rucio-ui.cern.ch'), - "rucio_ca_cert": os.getenv('RUCIO_CA_CERT', '/etc/rucio_ca.pem'), - "site_name": os.getenv('RUCIO_SITE_NAME', 'CERN'), - "vo": os.getenv('RUCIO_VO', 'escape'), - "voms_enabled": os.getenv('RUCIO_VOMS_ENABLED', '0') == '1', - "voms_vomses_path": os.getenv('RUCIO_VOMS_VOMSES_PATH', '/etc/vomses'), - "voms_certdir_path": os.getenv('RUCIO_VOMS_CERTDIR_PATH',), - "voms_vomsdir_path": os.getenv('RUCIO_VOMS_VOMSDIR_PATH', '/etc/grid-security/vomsdir'), - "destination_rse": os.getenv('RUCIO_DESTINATION_RSE', 'CERN-EOSPILOT'), - "rse_mount_path": os.getenv('RUCIO_RSE_MOUNT_PATH', '/eos/eulake'), - "replication_rule_lifetime_days": int(os.getenv('RUCIO_REPLICATION_RULE_LIFETIME_DAYS')) if os.getenv('RUCIO_REPLICATION_RULE_LIFETIME_DAYS') else None, - "path_begins_at": int(os.getenv('RUCIO_PATH_BEGINS_AT', '5')), - "mode": os.getenv('RUCIO_MODE', 'replica'), - "wildcard_enabled": os.getenv('RUCIO_WILDCARD_ENABLED', '1') == '1', - #"oidc_auth": os.getenv('RUCIO_OIDC_AUTH'), - #"oidc_env_name": os.getenv('RUCIO_OIDC_ENV_NAME'), - #"oidc_file_name": os.getenv('RUCIO_OIDC_FILE_NAME'), - } - atlas_config = { - "name": os.getenv('ATLAS_RUCIO_NAME', 'https://voatlasrucio-server-prod.cern.ch'), - "display_name": os.getenv('ATLAS_RUCIO_DISPLAY_NAME', 'ATLAS RUCIO'), - "rucio_base_url": os.getenv('ATLAS_RUCIO_BASE_URL', 'https://voatlasrucio-server-prod.cern.ch:443'), - "rucio_auth_url": os.getenv('ATLAS_RUCIO_AUTH_URL', 'https://atlas-rucio-auth.cern.ch:443'), - "rucio_webui_url": os.getenv('ATLAS_RUCIO_WEBUI_URL', 'https://rucio-ui.cern.ch'), - "rucio_ca_cert": os.getenv('RUCIO_CA_CERT', '/etc/rucio_ca.pem'), - "site_name": os.getenv('ATLAS_RUCIO_SITE_NAME', 'CERN'), - "vo": os.getenv('ATLAS_RUCIO_VO', 'atlas'), - "voms_enabled": os.getenv('RUCIO_VOMS_ENABLED', '0') == '1', - "voms_vomses_path": os.getenv('RUCIO_VOMS_VOMSES_PATH', '/etc/vomses'), - "voms_certdir_path": os.getenv('RUCIO_VOMS_CERTDIR_PATH',), - "voms_vomsdir_path": os.getenv('RUCIO_VOMS_VOMSDIR_PATH', '/etc/grid-security/vomsdir'), - "destination_rse": os.getenv('ATLAS_RUCIO_DESTINATION_RSE', 'CERN-PROD_PHYS-TOP'), - "rse_mount_path": os.getenv('ATLAS_RUCIO_RSE_MOUNT_PATH', '/eos/atlas/atlasscratchdisk/rucio'), - "replication_rule_lifetime_days": int(os.getenv('ATLAS_RUCIO_REPLICATION_RULE_LIFETIME_DAYS')) if os.getenv('ATLAS_RUCIO_REPLICATION_RULE_LIFETIME_DAYS') else None, - "path_begins_at": int(os.getenv('ATLAS_RUCIO_PATH_BEGINS_AT', '4')), - "mode": os.getenv('ATLAS_RUCIO_MODE', 'replica'), - "wildcard_enabled": os.getenv('ATLAS_RUCIO_WILDCARD_ENABLED', '1') == '1', - } - - - escape_config = {k: v for k, - v in escape_config.items() if v is not None} - - atlas_config = {k: v for k, - v in atlas_config.items() if v is not None} - - config_json['RucioConfig'] = { - 'instances': [escape_config, atlas_config], # cms, - "default_instance": os.getenv('RUCIO_DEFAULT_INSTANCE', escape_config['name']), - "default_auth_type": os.getenv('RUCIO_DEFAULT_AUTH_TYPE', 'x509_proxy'), - "log_level": os.getenv('RUCIO_LOG_LEVEL', 'debug'), - } - - config_file = open(file_server_config, 'w') - config_file.write(json.dumps(config_json, indent=2)) - config_file.close() - - write_jupyterlab_config() - -else: - pass diff --git a/vre-swan/scripts/before-notebook.d/00_tools.sh b/vre-swan/scripts/before-notebook.d/00_tools.sh deleted file mode 100644 index 9a170d35..00000000 --- a/vre-swan/scripts/before-notebook.d/00_tools.sh +++ /dev/null @@ -1,10 +0,0 @@ -# Useful functions to run in the build or startup - -run_as_user() { - if [ "$(whoami)" = "$NB_USER" ]; then - eval "$@" - else - local cmd="$@" - sudo -E -u $NB_USER sh -c "$cmd" - fi -} \ No newline at end of file diff --git a/vre-swan/scripts/before-notebook.d/01_storage.sh b/vre-swan/scripts/before-notebook.d/01_storage.sh deleted file mode 100644 index 3e4d549c..00000000 --- a/vre-swan/scripts/before-notebook.d/01_storage.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# Author: Danilo Piparo, Enric Tejedor, Pedro Maximino, Diogo Castro 2023 -# Copyright CERN -# Here the storage environment is prepared, to ensure the user is able to access -# their home directory (EOS for CERN users). - -# The $HOME directory is specified upstream in the Spawner -if [[ $HOME == /eos/* ]]; then export CERNBOX_HOME=$HOME; fi - -# Remove the last slash from HOME -export HOME="${HOME%/}" - -# Store the oAuth token given by the spawner inside a file -# so that EOS can use it -if [[ ! -z "$ACCESS_TOKEN" ]]; -then - _log "Storing oAuth token for EOS" - export OAUTH2_FILE=/tmp/eos_oauth.token - export OAUTH2_TOKEN="FILE:$OAUTH2_FILE" - echo -n oauth2:$ACCESS_TOKEN:$OAUTH_INSPECTION_ENDPOINT >& $OAUTH2_FILE - chown -R $NB_USER:$NB_GID $OAUTH2_FILE - chmod 600 $OAUTH2_FILE -fi - -set +e -run_as_user 'if [[ ! -d "$HOME" || ! -x "$HOME" ]]; then exit 1; fi' -if [ $? -ne 0 ] -then - _log "Error setting notebook working directory, $HOME not accessible by user $NB_USER." - exit 1 -fi -set -e - -# Change the user home to point to EOS. -if [[ ! -z "$CERNBOX_HOME" && ! $(usermod --home $HOME $NB_USER 2>&1 | grep "no changes" > /dev/null) ]]; -then - _log "Updated the user home to $HOME." -fi - -# Make sure the user has the SWAN_projects folder -run_as_user mkdir -p $HOME/SWAN_projects - -_log "Finished setting up user session storage" diff --git a/vre-swan/scripts/before-notebook.d/02_environment.sh b/vre-swan/scripts/before-notebook.d/02_environment.sh deleted file mode 100755 index b68e2e7c..00000000 --- a/vre-swan/scripts/before-notebook.d/02_environment.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash - -# Author: Danilo Piparo, Enric Tejedor, Pedro Maximino, Diogo Castro 2023 -# Copyright CERN -# Here the environment for the notebook server is prepared. Many of the commands are -# launched as regular user as it's this entity which is able to access -# eos and not the super user. - -# Set environment for the Jupyter process -LOCAL_HOME=/home/$NB_USER -export IPYTHONDIR=$LOCAL_HOME/.ipython -export JPY_DIR=$LOCAL_HOME/.jupyter - -# The Jupyter environment variables below are set to point to the local user -# home (/home/$USER), instead of the EOS path -export JUPYTER_CONFIG_DIR=$JPY_DIR -export JUPYTER_PATH=$LOCAL_HOME/.local/share/jupyter -export JUPYTER_RUNTIME_DIR=$JUPYTER_PATH/runtime -export JUPYTER_DATA_DIR=$JUPYTER_PATH - -# Set npm cache on the local user home, instead of the EOS path -export NPM_CONFIG_CACHE=$LOCAL_HOME/.npm - -# Set jupyterlab config directory -export JUPYTERLAB_SETTINGS_DIR=$HOME/.local/lab/user-settings/ - -# Set other environment variables -export KERNEL_DIR=$JUPYTER_PATH/kernels -export SWAN_ENV_FILE=$LOCAL_HOME/.bash_profile -export PROFILEPATH=$IPYTHONDIR/profile_default - -# Create missing directories -mkdir -p $IPYTHONDIR $PROFILEPATH - -# Create a gitignore file for ignoring all .sys. files and set it as global -# This will hide the checkpoint files created by EOS. -GLOBAL_GITIGNORE="$LOCAL_HOME/.gitignore_global" -echo ".sys.*" > "$GLOBAL_GITIGNORE" -# Set HOME to LOCAL_HOME to prevent git from internally touching EOS -run_as_user HOME=$LOCAL_HOME git config --global core.excludesfile "$GLOBAL_GITIGNORE" - -# Make the user the owner of the local home and subdirectories -chown -R $NB_USER:$NB_GID $LOCAL_HOME - -if [ "$SOFTWARE_SOURCE" == "lcg" ]; then - - # Setup the LCG View on CVMFS - _log "Setting up environment from CVMFS" - export LCG_VIEW=$ROOT_LCG_VIEW_PATH/$ROOT_LCG_VIEW_NAME/$ROOT_LCG_VIEW_PLATFORM - - # Configure nb and lab extensions from the LCG release - ln -s $LCG_VIEW/share/jupyter/nbextensions $JUPYTER_PATH - ln -s $LCG_VIEW/share/jupyter/labextensions $JUPYTER_PATH - - # Create directory for nb configuration - NBCONFIG=/etc/jupyter/nbconfig/notebook.d - mkdir -p $NBCONFIG - - # Enable jupyter-matplotlib extension for classic UI - jq -n --argjson jupyter-matplotlib/extension true \ - '{load_extensions: $ARGS.named}' > $NBCONFIG/jupyter-matplotlib.json - - # Enable widgets extension for classic UI - jq -n --argjson jupyter-js-widgets/extension true \ - '{load_extensions: $ARGS.named}' > $NBCONFIG/widgetsnbextension.json - - # Configure kernels and terminal - # The environment of the kernels and the terminal will combine the view and the user script (if any) - _log "Configuring kernels and terminal" - - # ROOT - ROOT_KERNEL_PATH=$LCG_VIEW/etc/notebook/kernels/root - if [ -d $ROOT_KERNEL_PATH ]; - then - cp -rL $ROOT_KERNEL_PATH $KERNEL_DIR - fi - - # R - R_KERNEL_PATH=$LCG_VIEW/share/jupyter/kernels/ir - if [ -d $R_KERNEL_PATH ]; - then - cp -rL $R_KERNEL_PATH $KERNEL_DIR - sed -i "s/IRkernel::main()/options(bitmapType='cairo');IRkernel::main()/g" $KERNEL_DIR/ir/kernel.json # Force cairo for graphics - fi - - # Octave - OCTAVE_KERNEL_PATH=$LCG_VIEW/share/jupyter/kernels/octave - if [[ -d $OCTAVE_KERNEL_PATH ]]; - then - cp -rL $OCTAVE_KERNEL_PATH $KERNEL_DIR - export OCTAVE_KERNEL_JSON=$KERNEL_DIR/octave/kernel.json - fi - - # Julia - JULIA_KERNEL_PATH=$LCG_VIEW/share/jupyter/kernels/julia-* - if [ -d $JULIA_KERNEL_PATH ]; - then - cp -rL $JULIA_KERNEL_PATH $KERNEL_DIR - fi - - # Make the user the owner of kernel files - chown -R $NB_USER:$NB_GID $KERNEL_DIR - - _log "Running user configuration script for user $NB_USER." - - set +e - run_as_user bash /srv/singleuser/scripts/userconfig.sh - - # Since the jupyter server is started with --preserve-env (in start.sh) - # other variables exported from this point on are also visible in the - # notebook/terminal environment unless overwritten by what appears in - # the kernel.json or .bash_profile. - - USERCONFIG_EXIT=$? - - if [ $USERCONFIG_EXIT -ne 0 ] - then - _log "Error configuring user environment. Exit code: $USERCONFIG_EXIT" - exit $USERCONFIG_EXIT - fi - set -e - - START_TIME_CONFIGURE_KERNEL_ENV=$( date +%s.%N ) - - # If there, source users' .bashrc after the SWAN environment - BASHRC_LOCATION=$HOME/.bashrc - printf "if [[ -f $BASHRC_LOCATION ]]; - then - source $BASHRC_LOCATION - fi\n" >> $SWAN_ENV_FILE - - if [ $? -ne 0 ] - then - _log "Error setting the environment for kernels" - exit 1 - else - CONFIGURE_KERNEL_ENV_TIME_SEC=$(echo $(date +%s.%N --date="$START_TIME_CONFIGURE_KERNEL_ENV seconds ago") | bc) - _log "user: $NB_USER, host: ${SERVER_HOSTNAME%%.*}, metric: configure_kernel_env.${ROOT_LCG_VIEW_NAME:-none}.${SPARK_CLUSTER_NAME:-none}.duration_sec, value: $CONFIGURE_KERNEL_ENV_TIME_SEC" - fi - - _log "Finished setting up CVMFS and user environment" -else - export KRB5CCNAME=$KRB5CCNAME_NB_TERM -fi - -# Set the terminal environment -#in jupyter 6.0.0 login shell (jupyter/notebook#4112) is set by default and /etc/profile.d is respected -echo "source $LOCAL_HOME/.bash_profile" > /etc/profile.d/swan.sh \ No newline at end of file diff --git a/vre-swan/scripts/others/userconfig.sh b/vre-swan/scripts/others/userconfig.sh deleted file mode 100644 index 22257250..00000000 --- a/vre-swan/scripts/others/userconfig.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - -# Author: Danilo Piparo, Enric Tejedor, Pedro Maximino, Diogo Castro 2023 -# Copyright CERN -# Here the software environment for notebooks and terminals is configured, -# using the LCG release as basis and (possibly) a user environment script. - -_log () { - if [[ "$*" == "ERROR:"* ]] || [[ "$*" == "WARNING:"* ]] || [[ "${JUPYTER_DOCKER_STACKS_QUIET}" == "" ]]; then - echo "$@" - fi -} - -START_TIME_SETUP_SWAN_HOME=$( date +%s.%N ) -SETUP_SWAN_HOME_TIME_SEC=$(echo $(date +%s.%N --date="$START_TIME_SETUP_SWAN_HOME seconds ago") | bc) -_log "user: $USER, host: ${SERVER_HOSTNAME%%.*}, metric: configure_user_env_swan_home.duration_sec, value: $SETUP_SWAN_HOME_TIME_SEC" - -# Persist enabled notebook nbextensions -SWAN_PROJECTS=$HOME/SWAN_projects -NBCONFIG=$JPY_DIR/nbconfig -mkdir -p $NBCONFIG -LOCAL_NB_NBEXTENSIONS=$SWAN_PROJECTS/.notebook_nbextensions -if [ ! -f $LOCAL_NB_NBEXTENSIONS ]; then - echo "{ - \"load_extensions\": { - } - }" > $LOCAL_NB_NBEXTENSIONS -fi -rm -f $NBCONFIG/notebook.json -ln -s $LOCAL_NB_NBEXTENSIONS $NBCONFIG/notebook.json - -START_TIME_SETUP_LCG=$( date +%s.%N ) -export JUPYTER_DATA_DIR=$LCG_VIEW/share/jupyter - -# Setup LCG -source $LCG_VIEW/setup.sh - -SETUP_LCG_TIME_SEC=$(echo $(date +%s.%N --date="$START_TIME_SETUP_LCG seconds ago") | bc) -_log "user: $USER, host: ${SERVER_HOSTNAME%%.*}, metric: configure_user_env_cvmfs.${ROOT_LCG_VIEW_NAME:-none}.duration_sec, value: $SETUP_LCG_TIME_SEC" - -# Prepend SWAN extensions path to PYTHONPATH to expose them -# to the notebook processes -export PYTHONPATH=$SWAN_LIB_DIR/extensions/:$PYTHONPATH - -# Append to PYTHONPATH a directory where to install libraries -# to be exposed to the user environment (notebooks, terminals) -export PYTHONPATH=$PYTHONPATH:$SWAN_LIB_DIR/nb_term_lib/ - -# Prepend the user site packages directory to PYTHONPATH, if they request it. -# This allows to use Python packages installed on CERNBox -if [ "$SWAN_USE_LOCAL_PACKAGES" == "true" ]; then - USER_SITE=$(python -m site --user-site) - export PYTHONPATH=$USER_SITE:$PYTHONPATH -fi - -# Run user startup script -TMP_SCRIPT=`mktemp` -if [[ ! -n $USER_ENV_SCRIPT ]]; -then - _log "User did not set a script"; -elif [[ $USER_ENV_SCRIPT && -f `eval echo $USER_ENV_SCRIPT` ]]; -then - START_TIME_SETUP_SCRIPT=$( date +%s.%N ) - - _log "Found user script: $USER_ENV_SCRIPT" - TMP_SCRIPT=`mktemp` - cat `eval echo $USER_ENV_SCRIPT` > $TMP_SCRIPT - source $TMP_SCRIPT - - SETUP_SCRIPT_TIME_SEC=$(echo $(date +%s.%N --date="$START_TIME_SETUP_SCRIPT seconds ago") | bc) - _log "user: $USER, host: ${SERVER_HOSTNAME%%.*}, metric: configure_user_env_script.duration_sec, value: $SETUP_SCRIPT_TIME_SEC" -else - _log "Cannot find user script: $USER_ENV_SCRIPT"; - exit 127 -fi - -# In k8s, $KRB5CCNAME_NB_TERM points to the location of the EOS kerberos ticket that notebook and terminal -# processes use. The Jupyter server uses the same ticket stored in another location ($KRB5CCNAME). With the -# code below, we force that $KRB5CCNAME becomes $KRB5CCNAME_NB_TERM only for notebook and terminal processes. -# This duality exists to prevent the user from overwriting the EOS kerberos ticket that the Jupyter server -# uses, e.g. by doing `kinit` from a notebook or a terminal. -# In puppet, $KRB5CCNAME_NB_TERM does not exist. Thus we give it a value and make $KRB5CCNAME point to that -# value. -# Both in k8s and puppet, renewals of the EOS kerberos tickets are automatically done to prevent expiration, -# both for the Jupyter server and the notebooks and terminals. However, if the user runs an explicit kinit -# and generates new kerberos credentials for notebooks and terminals, they are responsible for renewing those -# credentials from that point on. -if [[ -z $KRB5CCNAME_NB_TERM ]] -then - KRB5CCNAME_NB_TERM="/tmp/krb5cc_${USER_ID}_${RANDOM}" -fi -export KRB5CCNAME=$KRB5CCNAME_NB_TERM - -echo $PYTHONPATH -echo $PATH - - -# As the LCG setup might set PYTHONHOME, run python with -I (Isolated Mode) to prevent -# the lookup for modules in a Python 3 path and user site -python -I /srv/singleuser/configure_kernels_and_terminal.py - -# Remove our extra paths (where we install our extensions) in the kernel (via SwanKernelEnv kernel extension), -# leaving the user env cleaned. It should be the last one called to allow the kernel to load our extensions correctly. -export KERNEL_PROFILEPATH=$PROFILEPATH/ipython_kernel_config.py -echo "c.InteractiveShellApp.extensions.append('swankernelenv')" >> $KERNEL_PROFILEPATH -