Add repair to move local data blocking a mount target - #7089
Conversation
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>
There was a problem hiding this comment.
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 duringreload_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_recoveryfolder 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. |
| if isinstance(err, MountTargetNotEmptyError | MountTargetNotDirectoryError): | ||
| self._add_local_data_issue(mounts[i].name) | ||
| continue |
|
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). |
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/frigatebefore 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 reportedactivewhile/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_emptyissue with a newmove_local_datasuggestion (plus the existingexecute_remove). The fixup moves the blocking data to a<name>_local_recoveryfolder in a user-accessible location instead of deleting it, then reloads the mount:/mediaresp./share, so users can inspect and clean it up via the media browser, the Samba shares or add-ons./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 existingmount_failedissue), 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 stalemount_target_not_emptyissue.Type of change
Additional information
Checklist
ruff format supervisor tests)If API endpoints or add-on configuration are added/changed: