# The spawner is based on PRP's https://gitlab.nrp-nautilus.io/vpeddu/jupyterlab-west.git # This file is managed by [youngsu.kim|dung.vu]@csusb.edu from kubespawner import KubeSpawner class MySpawner(KubeSpawner): with open('/etc/jupyterhub/custom/my_spawner.html', 'r') as f: profile_form_template = f.readlines() profile_form_template = "".join(profile_form_template) def options_from_form(self, formdata): # cephfs_pvc_users = {"dvu@csusb.edu":"dvu", "youngsu.kim@csusb.edu":"ykim", "x5he@eng.ucsd.edu":"x5he" } cephfs_pvc_users = {"youngsu.kim@csusb.edu":"ykim", "x5he@eng.ucsd.edu":"x5he" } if not self.profile_list or not hasattr(self, '_profile_list'): return formdata #https://github.com/jupyterhub/kubespawner/blob/main/kubespawner/spawner.py#L3046 profile_slug = formdata.get('profile', [None])[0] # initialize a dictionary to return user_options = {} # if a profile is declared, add a dictionary key for the profile, and # dictionary keys for the formdata related to the profile's # profile_options, as recognized by being named like: # # profile-option-{profile_slug}--{profile_option_slug} # if profile_slug: user_options["profile"] = profile_slug prefix = f'profile-option-{profile_slug}--' for k, v in formdata.items(): if k.startswith(prefix): profile_option_slug = k[len(prefix) :] user_options[profile_option_slug] = v[0] gpus = int(formdata.get('gpus', [0])[0]) for k, v in kubespawner_override.items(): if callable(v): v = v(self) self.log.info(".. overriding KubeSpawner value %s=%s (callable result)", k, v) else: self.log.info(".. overriding KubeSpawner value %s=%s", k, v) if k != "image": setattr(self, k, v) else: image = v if isinstance(v, dict): if gpus > 0: image = v["cuda"] else: image = v["cpu"] if not (":" in image): self.log.info(".. adding tag %s to image %s", formdata.get('tag', [0])[0], image) image += ":"+formdata.get('tag', [0])[0] setattr(self, k, image) setattr(self, "tag", formdata.get('tag', [0])[0]) setattr(self, "extra_resource_limits", {"nvidia.com/gpu": gpus}) setattr(self, "mem_guarantee", formdata.get('ram', [0])[0]+"G") setattr(self, "cpu_guarantee", float(formdata.get('cores', [0])[0])) setattr(self, "mem_limit", formdata.get('ram', [0])[0]+"G") setattr(self, "cpu_limit", float(formdata.get('cores', [0])[0])) nodeSelectorTermsExpressions = [ { 'key': 'topology.kubernetes.io/region', 'operator': 'In', 'values': ["us-west","us-central","us-east"] }, { 'key': 'kubernetes.io/arch', 'operator': 'In', 'values': ["amd64"] } # , # { # 'key': 'kubernetes.io/hostname', # 'operator': 'In', # 'values': ["node-2-1.sdsc.optiputer.net", "node-2-6.sdsc.optiputer.net", "node-2-7.sdsc.optiputer.net", "node-2-8.sdsc.optiputer.net", # "ry-gpu-13.sdsc.optiputer.net"] # 'values': ["node-2-1.sdsc.optiputer.net", "node-2-6.sdsc.optiputer.net", "node-2-7.sdsc.optiputer.net", "node-2-8.sdsc.optiputer.net", # "ry-gpu-13.sdsc.optiputer.net", "gpu-01.csusb.edu","k8s-chase-ci-10.calit2.optiputer.net","npr-g1.nysernet.org", # "k8s-bharadia-01.sdsc.optiputer.net", "k8s-bharadia-02.sdsc.optiputer.net", # "k8s-bharadia-03.sdsc.optiputer.net","k8s-3090-01.calit2.optiputer.net","k8s-4090-01.calit2.optiputer.net", # "gpu-01.nrp.mghpcc.org", "gpu-02.nrp.mghpcc.org","gpu-03.nrp.mghpcc.org","gpu-04.nrp.mghpcc.org", # "gpu-06.nrp.mghpcc.org", "gpu-07.nrp.mghpcc.org","gpu-08.nrp.mghpcc.org","gpu-09.nrp.mghpcc.org"] # # } ] if formdata.get('gputype', [0])[0]: nodeSelectorTermsExpressions.append({ 'key': 'nvidia.com/gpu.product', 'operator': 'In', 'values': formdata.get('gputype', [0]) }) if gpus == 0: nodeSelectorTermsExpressions.append({ 'key': 'nvidia.com/gpu.product', 'operator': 'NotIn', 'values': [ "NVIDIA-GeForce-RTX-3090", "NVIDIA-A100-80GB-PCIe-MIG-1g.10gb", "NVIDIA-L40", "NVIDIA-A10", "NVIDIA-RTX-A4000", "NVIDIA-RTX-A5000", "NVIDIA-RTX-A5000", "NVIDIA-A100-SXM4-80GB", "NVIDIA-GeForce-GTX-1080-Ti", "NVIDIA-A100-PCIE-40GB", "NVIDIA-A100-80GB-PCIe", "NVIDIA-GeForce-RTX-2080-Ti"] }) tolerationsExpression = [{ 'key': 'nautilus.io/csu-tide', 'operator': 'Exists', 'effect': 'NoSchedule', }, { 'key': 'nautilus.io/csusb', 'operator': 'Exists', 'effect': 'NoSchedule', } ] setattr(self, 'extra_pod_config', { 'affinity': { 'nodeAffinity': { 'requiredDuringSchedulingIgnoredDuringExecution': { 'nodeSelectorTerms': [{ 'matchExpressions': nodeSelectorTermsExpressions, }], }, }, }, 'tolerations': tolerationsExpression, 'priorityClassName': 'owner', # 'imagePullPolicy': 'IfNotPresent', }) if self.user.name in cephfs_pvc_users: self.volume_mounts.append({ 'name': 'vasp', 'mountPath': '/home/jovyan/.vasp', }) self.volumes.append({ 'name': 'vasp', 'persistentVolumeClaim': { 'claimName': 'csusb-hub-dev-vasp-south-east', } }) if formdata.get('shared', [0])[0]: self.volume_mounts.append({ 'name': 'csusb-hpc-share', 'mountPath': '/home/jovyan/shared', }) self.volumes.append({ 'name': 'csusb-hpc-share', 'persistentVolumeClaim': { 'claimName': 'csusb-hub-dev-share-south-east', } }) setattr(self, 'startTimeout', 1200) self.log.info(options) return user_options profile_list = [ { 'display_name': 'Nrp-Stack Minimal', }, { 'display_name': 'Nrp-Stack Desktop v1.1', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/5g-desktop:ab90e952', # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prism-desktop:0addcd15', 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/desktop:v1.1', # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/relion-desktop', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack Desktop - Visual Code, mutiple Apps', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/5g-desktop:v1.3.1', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } } , { 'display_name': 'CSUSB Desktop- Pgadmin4', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/desktop-plus:3c6c7a4a', 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/desktop-plus:v1.3.1', # OS 22.04 pdadmin only # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/desktop-plus:1e93e6b6', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } } , { 'display_name': 'CSUSB-Stack Blender', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/r-studio', # without metashape & 22.04 OS 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/desktop-blender:v1.3.1', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/tensorflow:d525d538', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack Datascience', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/datascience:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'Nrp-Stack Tensorflow + PRP Packages', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prp:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'Nrp-Stack R-Studio', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/r-studio:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'Nrp-Stack PySpark', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/pyspark:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': "Nrp-Stack Matlab", 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/matlab:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': "Nrp-Stack OSGEO", 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/osgeo-notebook:v1.3.1', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack Desktop - Visual Studio', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/5g-desktop', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack wcsng-desktop', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/wcsng-desktop:v1.3.1', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack Prism Desktop', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prism-desktop:v1.3.1', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Nrp-Stack u55c-desktop', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/u55c-desktop:v1.3.1', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'Tensorflow 2.9.1 with open-python', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/tensorflow:v1.0', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'Nrp-Scipy', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/scipy:v1.3.1', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'PyTorch2', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prp-pytorch2:v1.0', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'YoungSu- becerra-class', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-rstudio-becerra-class', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'YoungSu-Stack SageMath', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-sagemath', 'imagePullPolicy': 'IfNotPresent', } } , { 'display_name': 'NRP Desktop- Pgadmin4', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/desktop:11-add-pgadmin4', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } } , { 'display_name': 'CSUSB Desktop', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/r-studio', 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/desktop:latest', 'imagePullPolicy': 'IfNotPresent', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio:latest', } }, { 'display_name': 'CSUSB Minimal', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/r-studio', 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/minimal:latest', 'imagePullPolicy': 'IfNotPresent', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio:latest', } }, { 'display_name': 'CSUSB Desktop - 5g', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/5g-desktop', 'imagePullPolicy': 'IfNotPresent', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [ 'sh', '-c', 'mkdir -p /home/jovyan/Desktop && cp /home/jovyan/shared/.software/desktopInit.desktop /home/jovyan/Desktop/ || true' ] } } } } }, { 'display_name': 'CSUSB-Stack R-Studio', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio-notebook:v1.3.1', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio', 'imagePullPolicy': 'IfNotPresent', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio:latest', } }, { 'display_name': 'CSUSB-Stack base 1.0', 'kubespawner_override': { # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/r-studio', # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prp:10-rebuild-stack-tf-image-with-tf-cudnn-8-5', 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/base:v1.0', 'imagePullPolicy': 'IfNotPresent', # 'image': 'gitlab-registry.nrp-nautilus.io/csusb-prp/csusb-jupyter-stacks/r-studio:latest', } } , { 'display_name': 'Nrp-Stack Tensorflow + PRP Packages. v1.0', 'kubespawner_override': { 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prp:10-rebuild-stack-tf-image-with-tf-cudnn-8-5', # 'image': 'gitlab-registry.nrp-nautilus.io/prp/jupyter-stack/prp:v1.0', 'imagePullPolicy': 'IfNotPresent', } } , { 'display_name': 'jupyter/minimal-notebook', 'kubespawner_override': { 'image': 'jupyter/minimal-notebook', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'jupyter/scipy-notebook', 'kubespawner_override': { 'image': 'jupyter/scipy-notebook', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'jupyter/tensorflow-notebook', 'kubespawner_override': { 'image': 'jupyter/tensorflow-notebook', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'jupyter/pyspark-notebook', 'kubespawner_override': { 'image': 'jupyter/pyspark-notebook', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'jupyter/datascience-notebook', 'kubespawner_override': { 'image': 'jupyter/datascience-notebook', 'imagePullPolicy': 'IfNotPresent', } }, { 'display_name': 'jupyter/all-spark-notebook', 'kubespawner_override': { 'image': 'jupyter/all-spark-notebook', 'imagePullPolicy': 'IfNotPresent', } }, ] c.JupyterHub.spawner_class = MySpawner