diff --git a/app.py b/app.py index 0da4647..87d395b 100644 --- a/app.py +++ b/app.py @@ -613,6 +613,20 @@ def _shares_with_usage(): return result +def _quota_supported(): + """Return (supported: bool, reason: str). Checks filesystem type under /srv.""" + r = subprocess.run(['df', '-T', '/srv'], capture_output=True, text=True) + for line in r.stdout.splitlines()[1:]: + parts = line.split() + if len(parts) >= 2: + fstype = parts[1].lower() + if fstype == 'zfs': + return False, 'ZFS storage detected — Linux disk quotas are not available inside a ZFS-backed container. Manage per-dataset quotas from the Proxmox host with: zfs set quota=10G ' + if fstype in ('tmpfs', 'overlay', 'aufs'): + return False, f'{fstype} filesystem does not support disk quotas' + return True, '' + + def _quota_usage(): try: r = subprocess.run(['repquota', '-u', '/srv'], capture_output=True, text=True, timeout=10) @@ -649,11 +663,14 @@ def _quota_usage(): @app.route('/api/dashboard', methods=['GET']) @require_auth def get_dashboard(): + quota_ok, quota_reason = _quota_supported() return jsonify({ 'status': _daemon_status(), 'disk': _disk_usage(), 'shares': _shares_with_usage(), - 'quotas': _quota_usage(), + 'quotas': _quota_usage() if quota_ok else [], + 'quota_supported': quota_ok, + 'quota_reason': quota_reason, }) diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 0f6d42b..02628aa 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -36,8 +36,14 @@ async function loadDashboard() { `).join(''); } + // Persist quota support flag for shares.js to read + window._quotaSupported = d.quota_supported !== false; + window._quotaReason = d.quota_reason || ''; + const qb = document.getElementById('dashQuotasBody'); - if (!d.quotas?.length) { + if (!d.quota_supported) { + qb.innerHTML = `${esc(d.quota_reason)}`; + } else if (!d.quotas?.length) { qb.innerHTML = `No quotas set.`; } else { qb.innerHTML = d.quotas.map(q => { diff --git a/static/js/shares.js b/static/js/shares.js index 6e6603a..fba41fa 100644 --- a/static/js/shares.js +++ b/static/js/shares.js @@ -23,8 +23,8 @@ async function loadShares() { - + ${window._quotaSupported !== false ? `` : ''} - + ${window._quotaSupported !== false ? `` : ''}