diff --git a/deploy/deploy-test-server.sh b/deploy/deploy-test-server.sh index 1d4c359..5bc48af 100755 --- a/deploy/deploy-test-server.sh +++ b/deploy/deploy-test-server.sh @@ -79,9 +79,9 @@ fi if command -v apt-get >/dev/null 2>&1; then $sudo_cmd apt-get update - $sudo_cmd apt-get install -y python3 python3-venv python3-pip curl ca-certificates tar gzip fuse-overlayfs fuse3 sudo + $sudo_cmd apt-get install -y python3 python3-venv python3-pip curl ca-certificates tar gzip util-linux sudo elif command -v dnf >/dev/null 2>&1; then - $sudo_cmd dnf install -y python3 python3-pip curl ca-certificates tar gzip fuse-overlayfs fuse3 sudo + $sudo_cmd dnf install -y python3 python3-pip curl ca-certificates tar gzip util-linux sudo else printf 'Unsupported package manager: expected apt-get or dnf\n' >&2 exit 1 @@ -178,6 +178,22 @@ if [ -f "$remote_tmp/admin_username" ] && [ -f "$remote_tmp/admin_password" ]; t fi fi +# One-shot migration: fuse-overlayfs running as the left4me user used +# user.fuseoverlayfs.* xattrs for whiteouts and opaque-dir markers; kernel +# overlayfs ignores those entirely, so a pre-existing upper/ from the fuse +# era would resurrect "deleted" files. Wipe upper/ and work/ for every +# instance once, gated by a sentinel file so reruns are no-ops. +overlay_sentinel=/var/lib/left4me/.kernel-overlay-migrated +if [ ! -e "$overlay_sentinel" ]; then + $sudo_cmd sh -c "systemctl stop 'left4me-server@*.service' 2>/dev/null || true" + $sudo_cmd systemctl stop left4me-web.service 2>/dev/null || true + $sudo_cmd sh -c "findmnt -t fuse.fuse-overlayfs -o TARGET --noheadings 2>/dev/null | xargs -r -n1 umount -l 2>/dev/null || true" + $sudo_cmd sh -c "findmnt -t overlay -o TARGET --noheadings 2>/dev/null | grep '/var/lib/left4me/runtime/' | xargs -r -n1 umount -l 2>/dev/null || true" + $sudo_cmd sh -c 'for d in /var/lib/left4me/runtime/*/; do [ -d "$d" ] || continue; rm -rf "$d/upper" "$d/work"; mkdir -p "$d/upper" "$d/work"; chown left4me:left4me "$d/upper" "$d/work"; done' + $sudo_cmd touch "$overlay_sentinel" + $sudo_cmd chown left4me:left4me "$overlay_sentinel" +fi + $sudo_cmd systemctl daemon-reload $sudo_cmd systemctl enable --now left4me-web.service $sudo_cmd systemctl restart left4me-web.service diff --git a/deploy/tests/test_deploy_artifacts.py b/deploy/tests/test_deploy_artifacts.py index 626bedd..394f84a 100644 --- a/deploy/tests/test_deploy_artifacts.py +++ b/deploy/tests/test_deploy_artifacts.py @@ -179,6 +179,30 @@ def test_deploy_script_installs_overlay_helper_with_executable_mode(): assert "chmod 0755" in script and "left4me-overlay" in script +def test_deploy_script_does_not_install_fuse_overlayfs_apt_dep(): + # fuse-overlayfs / fuse3 were the previous mount engine; kernel overlayfs + # replaces them. Comments in the migration block may legitimately mention + # the names, so scope this to the actual apt-get / dnf install lines. + install_lines = [ + line for line in DEPLOY_SCRIPT.read_text().splitlines() + if ("apt-get install" in line or "dnf install" in line) + ] + assert install_lines, "expected at least one apt/dnf install line" + for line in install_lines: + assert "fuse-overlayfs" not in line, line + assert "fuse3" not in line, line + + +def test_deploy_script_runs_one_shot_kernel_overlay_migration(): + script = DEPLOY_SCRIPT.read_text() + assert "/var/lib/left4me/.kernel-overlay-migrated" in script + # Migration should stop services + force-unmount stale mounts + wipe upper/work + assert "systemctl stop 'left4me-server@" in script + assert "systemctl stop left4me-web.service" in script + assert "findmnt -t overlay" in script + assert "/runtime/" in script and "rm -rf" in script and 'upper"' in script and 'work"' in script + + def test_env_templates_contain_required_defaults(): host_env = HOST_ENV.read_text() assert "Deployment units use fixed /var/lib/left4me paths" in host_env