Skip to content

fix(diskctl): list mounted drives even without write access - #3380

Open
JamBalaya56562 wants to merge 8 commits into
motioneye-project:devfrom
JamBalaya56562:fix/list-non-writable-mounts
Open

fix(diskctl): list mounted drives even without write access#3380
JamBalaya56562 wants to merge 8 commits into
motioneye-project:devfrom
JamBalaya56562:fix/list-non-writable-mounts

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

A mounted USB/flash drive is now offered as a storage device even when the motion user can't (yet) write to it — but it's shown as disabled with a "No write access" hint, rather than being silently omitted. Previously such a drive was invisible and only "Custom Path" was selectable.

Why

diskctl._list_mounts() skipped every mount that failed os.access(mount_point, os.W_OK). A drive mounted but owned by root (so not writable by the motion user) was therefore filtered out and never appeared in the storage-device dropdown — it looked unrecognised, even though it showed up in fdisk and /dev/disk/by-id/. @MichaIng reproduced this and pinpointed the write-access filter as the cause in #3024.

How

Drop the os.W_OK filter in _list_mounts(); instead, tag every mount with a writable flag (os.access(mount_point, os.W_OK)). list_mounted_disks() already cross-references _list_disks() (real block devices from /dev/disk/by-id or fdisk -l), so this only surfaces genuine mounted partitions, not virtual/system mounts like proc/tmpfs.

In the UI, a non-writable drive is now listed with a "[No write access]" label but rendered as a disabled <option>, so it cannot actually be selected as the storage device. Making it selectable was deliberately avoided — picking a drive the motion user can't write to would silently point a camera's target directory at a location where writes fail. Granting the motion user OS-level write access to the drive is the remaining step to actually use it; this PR only makes that limitation visible instead of hiding the drive entirely.

Testing

  • tests/test_diskctl.py: asserts _list_mounts() still returns a mount when os.access reports no write permission, but flags it writable: False (locks in the fix), and still de-duplicates bind mounts.
  • Full suite green in a Linux container: 129 passed. ruff check / ruff format --check pass.

Closes #3024

@JamBalaya56562
JamBalaya56562 force-pushed the fix/list-non-writable-mounts branch from 5337664 to 8be9021 Compare June 29, 2026 23:58

@Marijn0 Marijn0 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A mounted USB/flash drive is now offered as a storage device even when the motion user can't (yet) write to it. Previously only "Custom Path" was selectable for such drives.

In my opinion, there should be some form of indication that a drive is not writable by the motion user (or whichever user is running the motionEye/Motion service). Otherwise, users may select it as their storage location without understanding why Motion fails to write any files.

@Marijn0 Marijn0 linked an issue Jun 30, 2026 that may be closed by this pull request
@JamBalaya56562
JamBalaya56562 force-pushed the fix/list-non-writable-mounts branch from 8be9021 to 5912e6b Compare June 30, 2026 22:54
@JamBalaya56562

Copy link
Copy Markdown
Contributor Author

Good point — added in 1d435c2.

diskctl._list_mounts now reports a writable flag (os.access(mount_point, os.W_OK)), which flows through list_mounted_disks into available_disks. The storage-device dropdown then appends a [ne skribebla] ("not writable") marker to any drive the motion user can't write to, so it's visible before the user selects it.

Two notes:

  • the marker text is an Esperanto source string per the existing convention (e.g. "Propra dosierindiko") — happy to change the wording if you'd prefer something else;
  • the translation catalogs aren't regenerated here because the update_locales workflow is skipped for fork PRs; until they're regenerated the marker falls back to its source string (gettext returns the msgid unchanged for unknown keys, so nothing breaks).

@JamBalaya56562
JamBalaya56562 requested a review from Marijn0 June 30, 2026 23:00
Comment thread motioneye/controls/diskctl.py Outdated
Comment thread motioneye/controls/diskctl.py Outdated
Comment thread motioneye/static/js/main.js Outdated
@Marijn0
Marijn0 requested a review from MichaIng July 1, 2026 14:31
Comment thread motioneye/static/js/main.js Outdated
@Marijn0
Marijn0 force-pushed the fix/list-non-writable-mounts branch from 0fb3562 to 85f343a Compare July 1, 2026 14:54

@Marijn0 Marijn0 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good now.

I cleaned up a few things and made some small changes; I hope that is okay.

What we are achieving here is that mounts which are detected but are not writable by the user running motionEye/motion are now shown to the user. This makes it clear that the mounts are available but cannot be used for storage until the appropriate write permissions are configured.

And for that use case, I think it looks good. Thanks!

@zagrim zagrim left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me. I span it up for a quick test run in my dev env and indeed got some mounts listed with "[No write access]". So all good in the scope of the fix, I think.

@zagrim

zagrim commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

However, I noticed that I only got a list of non-RAID mounts for local disks, but not any of the mounted RAID arrays or network shares. I guess omission of the latter might be intentional (and can always by used by chosing "Custom Path"), but why wouldn't the RAID array mounts show 🤔 Anyway, the RAID arrays are listed just like the non-RAID mounts in the content of /proc/mounts (just with a device name that starts with "md" instead of "sd" that SATA disks have). With debug logging I can see both types are found by _list_mounts in diskctl.py:

[...]
   DEBUG: listing mounts...
   DEBUG: found mount "sysfs" at "/sys"
   DEBUG: found mount "proc" at "/proc"
[...]
   DEBUG: found mount "/dev/sdd10" at "/usr/local"
[...]
   DEBUG: found mount "/dev/md124" at "/mnt/project"
[...]

The RAID arrays are also found by _list_disks, which is called by _list_disks that is called by list_mounted_disks, which in turn is called from motion_camera_dict_to_ui in config.py:

   DEBUG: found disk at "/dev/md124" on bus "md": "uuid-89d92cf3:bcf1561e:99e2d1a6:d33176c1 "

However, these RAID arrays do not fit the idea of "disks containing partitions" that _list_disks_dev_by_id seems to use, causing them to be effectively filtered out of the resulting list.

$ ls -la /dev/disk/by-id/ |grep sdd
lrwxrwxrwx 1 root root    9 Jul  9 14:54 wwn-0x50025388500e6fda -> ../../sdd
lrwxrwxrwx 1 root root   10 Jul  9 14:54 wwn-0x50025388500e6fda-part1 -> ../../sdd1
lrwxrwxrwx 1 root root   11 Jul  9 14:54 wwn-0x50025388500e6fda-part10 -> ../../sdd10
[...]

$ ls -la /dev/disk/by-id/ |grep md
lrwxrwxrwx 1 root root   11 Jul  9 14:54 md-uuid-8385b5d2:521b811c:0572a3a5:13bff8ea -> ../../md126
lrwxrwxrwx 1 root root   11 Jul  9 14:54 md-uuid-89d92cf3:bcf1561e:99e2d1a6:d33176c1 -> ../../md124
[...]

(I redacted lines with MD array names as well as lines with ATA devices named after the device properties, both are essentially duplicates for the lines with plain IDs that are shown above)

Anyway, this is something that is better fixed separately to keep things organised and clear, I'll try to check if there's already an issue for this and will create one in case there isn't one yet.

Edit: issue created: #3393

JamBalaya56562 and others added 6 commits July 13, 2026 18:17
A mounted USB/flash drive was not offered as a storage device (only
"Custom Path" was selectable) when the motion user could not write to it.
_list_mounts() skipped any mount failing os.W_OK, so the drive looked
unrecognised even though it appeared in fdisk and /dev/disk/by-id. Drop
the write-access filter so the drive is listed; granting the motion user
write access to it is the remaining (OS-level) step. Reproduced and
diagnosed by a maintainer in the issue.

Closes motioneye-project#3024

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per @Marijn0's review: a non-writable drive is now listed, but a user
could pick it and not understand why Motion fails to store any media.
diskctl._list_mounts now reports a `writable` flag (os.W_OK), and the
storage-device dropdown appends a "[ne skribebla]" (not writable) marker
to such drives so the limitation is visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Marijn0
Marijn0 force-pushed the fix/list-non-writable-mounts branch from 85f343a to 6669a4f Compare July 13, 2026 16:17
@Marijn0
Marijn0 requested a review from Copilot July 13, 2026 16:37

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 adjusts disk/mount discovery so mounted removable drives are surfaced in the UI even when the running user lacks write permissions, addressing cases where such drives previously didn’t appear as selectable storage devices.

Changes:

  • Remove the write-access filter in diskctl._list_mounts() and instead expose a per-mount writable flag.
  • Update the storage-device dropdown rendering to display a “no write access” hint for unwritable mounts.
  • Add unit tests to lock in the new mount-listing behavior and existing bind-mount de-duplication.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
motioneye/controls/diskctl.py Stops filtering mounts by os.W_OK and adds a writable field to mount metadata.
motioneye/static/js/main.js Renders unwritable mounts with a label hint and adjusts option creation logic.
tests/test_diskctl.py Adds coverage for including unwritable mounts and still de-duplicating bind mounts.

Comment thread motioneye/static/js/main.js Outdated
Comment thread motioneye/static/js/main.js
Comment thread motioneye/static/js/main.js
Marijn0 and others added 2 commits July 13, 2026 19:50
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
A selected-but-disabled storage_device option reads back as null via
jQuery's .val(), crashing the backend on save. Add a validator that
flags the field invalid whenever the selected option is disabled,
with an ignoreVisibility flag on makeCustomValidator since the
storage section is by default collapsed but still relevant.
@Marijn0

Marijn0 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Added a validator on #storageDeviceSelect that checks on Apply if the selected storage location is still writable, and warns the user if not. Had to make it ignore section-visibility too, since "File storage" is collapsed by default and the check still needs to fire.
(For more info on why this was needed, see: #3380 (comment))

Should now be fine to merge from my side. 😃

@JamBalaya56562

Copy link
Copy Markdown
Contributor Author

Thank you @Marijn0, this is a great addition. 🙏

I reviewed both commits and they look correct to me. The flow is now: unwritable drives stay listed and the existing selection is kept, and the user gets a clear warning on Apply if their storage location isn't writable. Fine to merge from my side too — thanks again for pushing this over the line!

@JamBalaya56562
JamBalaya56562 requested a review from zagrim July 13, 2026 21:21

@zagrim zagrim left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Flashdrive not showing up under stoarge device

4 participants