diff --git a/config/clusters/2i2c-aws-us/showcase.values.yaml b/config/clusters/2i2c-aws-us/showcase.values.yaml index b3a3e0734..6004e86ed 100644 --- a/config/clusters/2i2c-aws-us/showcase.values.yaml +++ b/config/clusters/2i2c-aws-us/showcase.values.yaml @@ -120,17 +120,6 @@ basehub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true kubespawner_override: mem_guarantee: 7.234G cpu_guarantee: 0.1 diff --git a/config/clusters/2i2c/imagebuilding-demo.values.yaml b/config/clusters/2i2c/imagebuilding-demo.values.yaml index 9f48a2990..7c8fae977 100644 --- a/config/clusters/2i2c/imagebuilding-demo.values.yaml +++ b/config/clusters/2i2c/imagebuilding-demo.values.yaml @@ -59,17 +59,6 @@ jupyterhub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true scipy: display_name: Jupyter SciPy Notebook slug: scipy diff --git a/config/clusters/2i2c/ucmerced-staging.values.yaml b/config/clusters/2i2c/ucmerced-staging.values.yaml index 26ab4970a..2914c5203 100644 --- a/config/clusters/2i2c/ucmerced-staging.values.yaml +++ b/config/clusters/2i2c/ucmerced-staging.values.yaml @@ -23,17 +23,6 @@ jupyterhub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true hub: config: CILogonOAuthenticator: diff --git a/config/clusters/2i2c/ucmerced.values.yaml b/config/clusters/2i2c/ucmerced.values.yaml index aea2c1d05..6032f65ec 100644 --- a/config/clusters/2i2c/ucmerced.values.yaml +++ b/config/clusters/2i2c/ucmerced.values.yaml @@ -23,17 +23,6 @@ jupyterhub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true hub: config: CILogonOAuthenticator: diff --git a/config/clusters/catalystproject-africa/common.values.yaml b/config/clusters/catalystproject-africa/common.values.yaml index fefd420bd..d9ca1de63 100644 --- a/config/clusters/catalystproject-africa/common.values.yaml +++ b/config/clusters/catalystproject-africa/common.values.yaml @@ -80,14 +80,6 @@ jupyterhub: mem_limit: null working_dir: /home/rstudio default_url: /rstudio - volume_mounts: - - name: home - mountPath: /home/rstudio - subPath: "{username}" - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true node_selector: node.kubernetes.io/instance-type: r5.xlarge - display_name: "Medium: up to 16 CPU / 128 GB RAM" @@ -145,14 +137,6 @@ jupyterhub: mem_limit: null working_dir: /home/rstudio default_url: /rstudio - volume_mounts: - - name: home - mountPath: /home/rstudio - subPath: "{username}" - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true node_selector: node.kubernetes.io/instance-type: r5.4xlarge - display_name: "Large: up to 64 CPU / 512 GB RAM" @@ -210,13 +194,5 @@ jupyterhub: mem_limit: null working_dir: /home/rstudio default_url: /rstudio - volume_mounts: - - name: home - mountPath: /home/rstudio - subPath: "{username}" - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true node_selector: node.kubernetes.io/instance-type: r5.16xlarge diff --git a/config/clusters/hhmi/common.values.yaml b/config/clusters/hhmi/common.values.yaml index 6cb409483..c3ce6d651 100644 --- a/config/clusters/hhmi/common.values.yaml +++ b/config/clusters/hhmi/common.values.yaml @@ -69,17 +69,6 @@ basehub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true desktop: display_name: Linux desktop slug: desktop diff --git a/config/clusters/nasa-ghg/common.values.yaml b/config/clusters/nasa-ghg/common.values.yaml index 0d643730b..88f1ee3ea 100644 --- a/config/clusters/nasa-ghg/common.values.yaml +++ b/config/clusters/nasa-ghg/common.values.yaml @@ -85,17 +85,6 @@ basehub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true qgis: display_name: QGIS on Linux Desktop slug: qgis diff --git a/config/clusters/nasa-veda/common.values.yaml b/config/clusters/nasa-veda/common.values.yaml index 9dab43376..b6a21b4ec 100644 --- a/config/clusters/nasa-veda/common.values.yaml +++ b/config/clusters/nasa-veda/common.values.yaml @@ -139,17 +139,6 @@ basehub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true init_containers: # Need to explicitly fix ownership here, as otherwise these directories will be owned # by root on most NFS filesystems - neither EFS nor Google Filestore support anonuid diff --git a/config/clusters/smithsonian/common.values.yaml b/config/clusters/smithsonian/common.values.yaml index 6380dcaad..334bbb877 100644 --- a/config/clusters/smithsonian/common.values.yaml +++ b/config/clusters/smithsonian/common.values.yaml @@ -87,14 +87,6 @@ basehub: image: rocker/binder:4.3 working_dir: /home/rstudio default_url: /rstudio - volume_mounts: - - name: home - mountPath: /home/rstudio - subPath: "{username}" - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true scipy: display_name: Jupyter SciPy Notebook slug: scipy diff --git a/config/clusters/utoronto/r-common.values.yaml b/config/clusters/utoronto/r-common.values.yaml index c9e534251..9e38e008c 100644 --- a/config/clusters/utoronto/r-common.values.yaml +++ b/config/clusters/utoronto/r-common.values.yaml @@ -11,9 +11,6 @@ jupyterhub: # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio singleuser: - storage: - # From https://jupyterhub-image.guide/rocker.html#step-7-setup-zero-to-jupyterhub-configuration-for-home-directory - homeMountPath: /home/rstudio defaultUrl: /rstudio image: name: quay.io/2i2c/utoronto-r-image diff --git a/docs/howto/features/rocker.md b/docs/howto/features/rocker.md index bf9db494f..b27777e0b 100644 --- a/docs/howto/features/rocker.md +++ b/docs/howto/features/rocker.md @@ -112,17 +112,6 @@ jupyterhub: # Ensures container working dir is homedir # https://github.com/2i2c-org/infrastructure/issues/2559 working_dir: /home/rstudio - # Because this is a list, it will override our default volume mounts - volume_mounts: - # Mount the user home directory - - name: home - mountPath: /home/rstudio - subPath: "{username}" - # Mount the shared readonly directory - - name: home - mountPath: /home/rstudio/shared - subPath: _shared - readOnly: true scipy: display_name: Jupyter SciPy Notebook slug: scipy @@ -137,6 +126,6 @@ is configured to automatically install packages from the [Posit Package Manager] which provides fast binary package installs. They are installed under `/usr/local`, and hence *cleared on server stop*. So installed -packages will *not* persist across user sessions. +packages will *not* persist across user sessions. If users need to have persistent packages installed, we would need a custom image. diff --git a/helm-charts/basehub/values.yaml b/helm-charts/basehub/values.yaml index 9c3975f71..231593447 100644 --- a/helm-charts/basehub/values.yaml +++ b/helm-charts/basehub/values.yaml @@ -72,6 +72,9 @@ jupyterhub: - name: home mountPath: /home/jovyan/shared-readwrite subPath: _shared + - name: home + mountPath: /home/rstudio/shared-readwrite + subPath: _shared cloudResources: provider: "" gcp: @@ -307,6 +310,24 @@ jupyterhub: mountPath: /home/jovyan/shared subPath: _shared readOnly: true + + # For all pods, mount home in both /home/jovyan (done via singleuser.storage.static) + # as well as /home/rstudio. This allows rocker images (which use the + # rstudio user and put home ine /home/rstudio) to be first class citizens + # along with jupyter based images, regardless of how they are specified ( + # via the configurator, or with unlisted_choice, or as a profile). For non-rocker + # images, this is just invisible in the UI and there is no performance overhead + # for these extra bind mounts. An additional positive here is that in case *students* + # end up accidentally hardcoding paths in their notebooks, it will continue to work + # regardless of wether they or on RStudio or JupyterLab (described to us as a serious + # problem by openscapes) + - name: home + mountPath: /home/rstudio + subPath: "{username}" + - name: home + mountPath: /home/rstudio/shared + subPath: _shared + readOnly: true memory: guarantee: 256M limit: 1G @@ -621,8 +642,36 @@ jupyterhub: # adjusts the spawner to add config specific to admin users from z2jh import get_config + from kubespawner.utils import get_k8s_model from kubespawner import KubeSpawner from jupyterhub_configurator.mixins import ConfiguratorSpawnerMixin + from kubernetes_asyncio.client.models import V1VolumeMount + + + def modify_pod_hook(spawner, pod): + """ + Modify the pod manifest for admins. + + This is used to modify attributes of the pod that are *lists*, + as those are not merged but replaced by KubeSpawner. Everything + else is managed via the CustomSpawner's start method below. + """ + custom_admin = get_config('custom.singleuserAdmin', {}) + if not (spawner.user.admin and custom_admin): + return pod + + for c in pod.spec.containers: + if c.name == "notebook": + notebook_container = c + break + else: + raise Exception("No container named 'notebook' found in pod definition") + + admin_volume_mounts = custom_admin.get('extraVolumeMounts', []) + notebook_container.volume_mounts += [get_k8s_model(V1VolumeMount, obj) for obj in (admin_volume_mounts)] + + return pod + c.KubeSpawner.modify_pod_hook = modify_pod_hook class CustomSpawner(ConfiguratorSpawnerMixin, KubeSpawner): def start(self, *args, **kwargs): @@ -630,9 +679,6 @@ jupyterhub: if not (self.user.admin and custom_admin): return super().start(*args, **kwargs) - admin_volume_mounts = custom_admin.get('extraVolumeMounts', []) - self.volume_mounts += [vm for vm in admin_volume_mounts if vm not in self.volume_mounts] - admin_environment = custom_admin.get('extraEnv', {}) self.environment.update(admin_environment)