From 141bbe3693a70970b0fd2a7f50cfa6a3d61894d1 Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 20 Aug 2026 15:40:46 +0200 Subject: [PATCH 1/2] Ship /public/dumps/public symlink in singleuser image Previously /public/dumps was a nfs mount and thus didn't need to exist in the host or container filesystem. Changing the type to DirectoryOrCreate means the path needs to exist on the worker, and it can't be created in the read-only container, thus singleuser fails to start. Switch to shipping the now-static symlink /public/dumps/public to /mnt/nfs/dumps which is where dumps-nfs.w.o is now canonically mounted. --- images/singleuser/Dockerfile | 5 +++ .../maintain-dumps-nfs/maintain-dumps-nfs.py | 40 ++----------------- .../maintain-dumps-nfs/daemonset.yaml | 3 -- paws/values.yaml | 9 ----- 4 files changed, 8 insertions(+), 49 deletions(-) diff --git a/images/singleuser/Dockerfile b/images/singleuser/Dockerfile index de24ac7d..88d0a248 100644 --- a/images/singleuser/Dockerfile +++ b/images/singleuser/Dockerfile @@ -152,6 +152,11 @@ RUN r -e "install.packages('IRkernel', version='1.3.2')" && \ USER root +# Ship the /public/dumps/public symlink. As per T432583 dumps-nfs.w.o is always +# mounted to /mnt/nfs/dumps +RUN mkdir -p /public/dumps && \ + ln -s /mnt/nfs/dumps /public/dumps/public + ## Setup OpenRefine ENV OPENREFINE_DIR /srv/openrefine ENV PATH=$PATH:$OPENREFINE_DIR diff --git a/paws/files/maintain-dumps-nfs/maintain-dumps-nfs.py b/paws/files/maintain-dumps-nfs/maintain-dumps-nfs.py index b50ca27c..1b8b77ad 100644 --- a/paws/files/maintain-dumps-nfs/maintain-dumps-nfs.py +++ b/paws/files/maintain-dumps-nfs/maintain-dumps-nfs.py @@ -2,14 +2,13 @@ Runs as a DaemonSet with Bidirectional mount propagation so the mount is visible on the host. Also manages clouddumps100[12]-compat symlinks within -/mnt/nfs and a /public/dumps/public -> /mnt/nfs/dumps symlink for singleuser -pods. +/mnt/nfs. Similar to dumps-nfs-client-sitter in the puppet repo, but differs in that it also manages symlinks as opposed to puppet in production. -/mnt/nfs and /public/dumps are then bind-mounted from the host into singleuser -pods by the jupyterhub spawner. +/mnt/nfs is then bind-mounted from the host into singleuser pods by the +jupyterhub spawner. """ import errno @@ -163,38 +162,6 @@ def ensure_compat_symlinks(host_mnt_nfs): logger.debug("Compat symlink %s -> %s ok", link_path, target) -def ensure_public_dumps_symlink(): - """Create /host/public/dumps/public -> /mnt/nfs/dumps so singleuser pods can reach dumps via /public/dumps.""" - dumps_dir = "/host/public/dumps" - public_path = os.path.join(dumps_dir, "public") - target = "/mnt/nfs/dumps" - try: - current = os.readlink(public_path) - if current == target: - logger.info("Symlink %s -> %s already exists", public_path, target) - return - logger.info("Symlink %s points to %s, updating", public_path, current) - os.unlink(public_path) - except OSError as e: - if e.errno == errno.ENOENT: - logger.info("Symlink %s missing — creating", public_path) - elif os.path.isdir(public_path): - logger.error( - "%s exists and is a directory — cannot create compat symlink", - public_path, - ) - return - else: - logger.info("Removing existing %s to create symlink", public_path) - try: - os.unlink(public_path) - except OSError: - logger.warning("Failed to remove %s", public_path) - return - os.makedirs(dumps_dir, exist_ok=True) - os.symlink(target, public_path) - - def main(): """Mount NFS dumps, create compat symlinks, then loop for health checks and remounts.""" config = load_config() @@ -203,7 +170,6 @@ def main(): server = config["server"] mount_info = {"host_path": DUMPS_MOUNT} - ensure_public_dumps_symlink() ensure_compat_symlinks("/host/mnt/nfs") while True: diff --git a/paws/templates/maintain-dumps-nfs/daemonset.yaml b/paws/templates/maintain-dumps-nfs/daemonset.yaml index ddb28b12..231636a8 100644 --- a/paws/templates/maintain-dumps-nfs/daemonset.yaml +++ b/paws/templates/maintain-dumps-nfs/daemonset.yaml @@ -56,9 +56,6 @@ spec: - name: host-nfs mountPath: /host/mnt/nfs mountPropagation: Bidirectional - - name: host-public-dumps - mountPath: /host/public/dumps - mountPropagation: Bidirectional - name: config mountPath: /etc/maintain-dumps-nfs readOnly: true diff --git a/paws/values.yaml b/paws/values.yaml index 23e43ece..65d9a83d 100644 --- a/paws/values.yaml +++ b/paws/values.yaml @@ -147,10 +147,6 @@ jupyterhub: # * public-dumps is the public interface and holds a symlink to /mnt/nfs spawner.volumes = [ - { - 'name': 'public-dumps', - 'hostPath': { 'path': '/public/dumps' } - }, { 'name': 'mnt-nfs', 'hostPath': { 'path': '/mnt/nfs' } @@ -177,11 +173,6 @@ jupyterhub: 'name': 'home', 'mountPath': '/home/paws' }, - { - 'name': 'public-dumps', - 'mountPath': '/public/dumps', - 'readOnly': True - }, { 'name': 'mnt-nfs', 'mountPath': '/mnt/nfs', From 9b79816215fb170f8e6601dac6b2262dd04fccde Mon Sep 17 00:00:00 2001 From: Github Action Date: Thu, 20 Aug 2026 13:54:07 +0000 Subject: [PATCH 2/2] auto update of tag --- paws/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paws/values.yaml b/paws/values.yaml index 65d9a83d..9cab5f17 100644 --- a/paws/values.yaml +++ b/paws/values.yaml @@ -238,7 +238,7 @@ jupyterhub: fsGid: 52771 image: name: quay.io/wikimedia-paws-prod/singleuser - tag: pr-530 # singleuser tag managed by github actions + tag: pr-532 # singleuser tag managed by github actions pullPolicy: Always memory: guarantee: 0.70G