# 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): if not self.profile_list or not hasattr(self, '_profile_list'): return formdata selected_profile = int(formdata.get('profile', [0])[0]) options = self._profile_list[selected_profile] self.log.debug("Applying KubeSpawner override for profile '%s'", options['display_name']) kubespawner_override = options.get('kubespawner_override', {}) for k, v in kubespawner_override.items(): if callable(v): v = v(self) self.log.debug(".. overriding KubeSpawner value %s=%s (callable result)", k, v) else: self.log.debug(".. overriding KubeSpawner value %s=%s", k, v) setattr(self, k, v) gpus = int(formdata.get('gpus', [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"] }] if formdata.get('gputype', [0])[0]: nodeSelectorTermsExpressions.append({ 'key': 'nvidia.com/gpu.product', 'operator': 'In', 'values': formdata.get('gputype', [0]) }) tolerationsExpression = [{ 'key': 'nautilus.io/nrp-testing', 'operator': 'Exists', 'effect': 'NoSchedule', }] setattr(self, 'extra_pod_config', { 'affinity': { 'nodeAffinity': { 'requiredDuringSchedulingIgnoredDuringExecution': { 'nodeSelectorTerms': [{ 'matchExpressions': nodeSelectorTermsExpressions, }], }, }, }, 'tolerations': tolerationsExpression, }) setattr(self, 'startTimeout', 1200) return options profile_list = [ { 'display_name': 'Stack Minimal', }, { 'display_name': 'Stack Minimal + Desktop GUI + Relion', 'kubespawner_override': [{ 'image_spec': 'localhost:30081/prp/jupyter-stack/relion-desktop', 'lifecycle_hooks': { 'postStart': { 'exec': { 'command': [{ 'sh', '-c', # '/home/jovyan/shared/.software/prog-desktop.sh || true', 'echo "Hello World"', }] } } } }] }, { 'display_name': 'Stack Datascience', 'kubespawner_override': { 'image_spec': 'localhost:30081/prp/jupyter-stack/datascience', } }, { 'display_name': 'Stack oneAPI (Test)', 'kubespawner_override': { 'image_spec': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-oneapi', } }, { 'display_name': 'Stack PuLP (Test)', 'kubespawner_override': { 'image_spec': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-pulp-test:583d7269', } }, { 'display_name': 'Stack Tensorflow + PRP Packages', 'kubespawner_override': { 'image_spec': 'localhost:30081/prp/jupyter-stack/prp', } }, { 'display_name': 'Stack R-Studio', 'kubespawner_override': { 'image_spec': 'localhost:30081/prp/jupyter-stack/r-studio', } }, { 'display_name': 'Stack PySpark', 'kubespawner_override': { 'image_spec': 'localhost:30081/prp/jupyter-stack/pyspark', } }, { 'display_name': 'Stack SageMath', 'kubespawner_override': { 'image_spec': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-sagemath', } }, { 'display_name': 'Stack Zeus-Cling (Test)', 'kubespawner_override': { 'image_spec': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-xeus-cling', } }, ] c.JupyterHub.spawner_class = MySpawner