# 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]) }) setattr(self, 'extra_pod_config', { 'affinity': { 'nodeAffinity': { 'requiredDuringSchedulingIgnoredDuringExecution': { 'nodeSelectorTerms': [{ 'matchExpressions': nodeSelectorTermsExpressions, }], }, }, } }) setattr(self, 'startTimeout', 1200) self.volume_mounts = [ { 'name': 'volume-{username}', 'mountPath': '/home/jovyan', }, { 'name': 'csusb-hpc-share', 'mountPath': '/home/jovyan/shared', }, { 'name': 'shm-volume', 'mountPath': '/dev/shm', }, ] self.volumes = [ { 'name': 'volume-{username}', 'persistentVolumeClaim': { 'claimName': 'claim-{username}' } }, { 'name': 'csusb-hpc-share', 'persistentVolumeClaim': { 'claimName': 'csusb-hpc-share' } }, { 'name': 'shm-volume', 'emptyDir': { 'medium': 'Memory' } } ] 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', } }, { 'display_name': 'Stack Datascience', 'kubespawner_override': { 'image_spec': 'localhost:30081/prp/jupyter-stack/datascience', } }, { '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 oneAPI (Test)', 'kubespawner_override': { 'image_spec': 'gitlab-registry.nrp-nautilus.io/youngsu_kim/csusb-jupyter-stack/stack-oneapi', } }, ] c.JupyterHub.spawner_class = MySpawner