Skip to content

Add repair to move local data blocking a mount target - #7089

Draft
agners wants to merge 1 commit into
mainfrom
mount-target-not-empty-repair
Draft

Add repair to move local data blocking a mount target#7089
agners wants to merge 1 commit into
mainfrom
mount-target-not-empty-repair

Conversation

@agners

@agners agners commented Jul 24, 2026

Copy link
Copy Markdown
Member

Proposed change

When an add-on writes into a media/share directory while its network mount is not in place — e.g. Frigate recording to /media/frigate before network storage was set up, or after systemd tore down the bind mount together with a stopped/restarted data mount (#7013) — the local data blocks re-creating the mount, since mounting over a non-empty directory is refused (#7072). Until now this failed silently at Supervisor startup: the bind mounts were created as fire-and-forget tasks, so the data mount reported active while /media/<name> stayed a local directory, and the only way out was removing the data manually over SSH/Samba and re-creating the mount via the API (see #7037).

This PR surfaces the condition as a new mount_target_not_empty issue with a new move_local_data suggestion (plus the existing execute_remove). The fixup moves the blocking data to a <name>_local_recovery folder in a user-accessible location instead of deleting it, then reloads the mount:

  • media/share mounts: the recovery folder is created next to the mount in /media resp. /share, so users can inspect and clean it up via the media browser, the Samba shares or add-ons.
  • backup mounts: their data mount directory (/mnt/data/supervisor/mounts/<name>) is not reachable for users, so the data is moved to local backup storage instead, where stranded backup files are visible and manageable.

The relocation is inherently safe against touching share content: paths that are mount points are skipped, and renaming a live mount point or moving data across filesystems fails (EBUSY/EXDEV) rather than misplacing data. Name collisions with an existing recovery folder get a numeric suffix.

Detection covers all paths where the condition can appear: bind mount failures during load() are now awaited and routed into resolution issues instead of being swallowed as fire-and-forget tasks (blocking local data raises the new issue; other bind failures create the existing mount_failed issue), the periodic mount reload picks it up through the same error routing, and the reload fixup raises it directly when re-creating the bind mount fails on local data. A successful mount reload dismisses a stale mount_target_not_empty issue.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to the supervisor)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Ruff (ruff format supervisor tests)
  • Tests have been added to verify that the new code works.

If API endpoints or add-on configuration are added/changed:

When an add-on writes into a media/share directory while its network
mount is not in place (#7037), the local data blocks re-creating the
mount: mounting over a non-empty directory is refused. Until now this
failed silently at Supervisor startup — the bind mounts were created as
fire-and-forget tasks — and the only way out was to remove the data
manually over SSH/Samba and re-create the mount via the API.

Surface the condition as a new mount_target_not_empty issue and offer a
move_local_data suggestion. The fixup moves the blocking data to a
<name>_local_recovery folder in a user-accessible location — media or
share for bind mount targets, local backup storage for backup mounts
(their data mount directory is not reachable for users) — then reloads
the mount. Nothing is deleted; users can inspect and clean up the
recovered data via the media browser or the share and backup folders.

Bind mount failures during load are now awaited and routed into
resolution issues instead of being swallowed as fire-and-forget tasks;
bind failures other than blocking local data create the existing
mount_failed issue. A successful mount reload dismisses a stale local
data issue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Supervisor repair path for the case where local files/directories in a mount target prevent (re)creating a bind mount into /media/<name> or /share/<name>, by surfacing it as a resolution issue and providing a fixup that relocates the blocking data and retries the mount.

Changes:

  • Convert bind-mount setup during MountManager.load() (and bind re-creation during reload_mount()) from fire-and-forget into awaited operations that route failures into resolution issues.
  • Introduce a new resolution issue/suggestion pair (mount_target_not_empty / move_local_data) and implement the corresponding fixup that relocates local data to a *_local_recovery folder before remounting.
  • Add test coverage for issue creation/dismissal and for the new fixup behavior (including recovery-folder name collisions).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
supervisor/mounts/manager.py Routes mount/bind errors into resolution issues; adds local-data issue helpers; adds relocate_local_data() job and integrates issue dismissal on successful reload.
supervisor/resolution/const.py Adds IssueType.MOUNT_TARGET_NOT_EMPTY and SuggestionType.MOVE_LOCAL_DATA.
supervisor/resolution/fixups/mount_move_local_data.py Implements the new fixup that calls MountManager.relocate_local_data() and preserves issues on failure.
supervisor/resolution/fixups/mount_execute_remove.py Extends the existing remove fixup to also apply to the new local-data issue.
tests/mounts/test_manager.py Adds tests for local-data issue creation on bind failure, dismissal after successful reload, and recovery-folder collision behavior.
tests/resolution/fixup/test_mount_move_local_data.py Adds end-to-end fixup tests for media/backup mounts, failure retention, and missing-mount dismissal.

Comment on lines +184 to +186
if isinstance(err, MountTargetNotEmptyError | MountTargetNotDirectoryError):
self._add_local_data_issue(mounts[i].name)
continue
@agners

agners commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Since we have already a repair for the failing mount, can't we just have it as part of that repair? Either we make a new repair "mount failed/data move needed" alongside "mount failed", but only raise one of the two.

Actually: We can have a single fixup with another suggestion, one which moves data and one which just retries (in case the user wants to resolve on its own).

@agners
agners marked this pull request as draft July 28, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants