b12dfe64e4
CAP und FRAG wurden um eine Spalte verschoben gelesen (DEDUP statt CAP, CAP statt FRAG). Korrekt: FRAG=parts[6], CAP=parts[7]. Prozentzeichen ergänzt, da -p die Werte ohne % liefert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ZMB Webui Backend API
FastAPI backend for ZFS pool, dataset, and snapshot management.
Quick Start (Local Development)
Prerequisites
- Python 3.11+
- ZFS tools installed (
zpool,zfs)
Setup
cd backend
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create default admin user (password: admin)
python3 -c "from services.auth import auth_service; auth_service.add_user('admin', 'admin')"
# Run development server
python3 main.py
Server runs on http://localhost:8000
API Endpoints
Authentication
# Login
curl -X POST http://localhost:8000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# Returns: {"access_token":"...", "token_type":"bearer"}
Pools
# List pools (requires auth)
curl http://localhost:8000/api/pools \
-H "Authorization: Bearer YOUR_TOKEN"
# Get pool status
curl http://localhost:8000/api/pools/tank \
-H "Authorization: Bearer YOUR_TOKEN"
# Start scrub
curl -X POST http://localhost:8000/api/pools/tank/scrub \
-H "Authorization: Bearer YOUR_TOKEN"
Datasets
# List datasets
curl http://localhost:8000/api/datasets \
-H "Authorization: Bearer YOUR_TOKEN"
# Create dataset
curl -X POST http://localhost:8000/api/datasets \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"tank/backup","properties":{"compression":"lz4"}}'
# Delete dataset
curl -X DELETE http://localhost:8000/api/datasets/tank/test \
-H "Authorization: Bearer YOUR_TOKEN"
Snapshots
# List snapshots
curl http://localhost:8000/api/snapshots \
-H "Authorization: Bearer YOUR_TOKEN"
# Create snapshot
curl -X POST http://localhost:8000/api/snapshots \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"dataset":"tank/share"}'
# Delete snapshot
curl -X DELETE http://localhost:8000/api/snapshots/tank/share@2026-04-14-120000 \
-H "Authorization: Bearer YOUR_TOKEN"
# Rollback snapshot
curl -X POST http://localhost:8000/api/snapshots/rollback \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"snapshot":"tank/share@2026-04-14-120000"}'
File Manager (Browse /tank/share)
# Browse directory
curl "http://localhost:8000/api/files/browse?path=/" \
-H "Authorization: Bearer YOUR_TOKEN"
# Get file info
curl "http://localhost:8000/api/files/info?path=/document.pdf" \
-H "Authorization: Bearer YOUR_TOKEN"
# Read text file (< 10MB)
curl "http://localhost:8000/api/files/read?path=/config.json&limit=1000" \
-H "Authorization: Bearer YOUR_TOKEN"
# Download file
curl "http://localhost:8000/api/files/download?path=/archive.tar.gz" \
-H "Authorization: Bearer YOUR_TOKEN" \
-O
# Upload file
curl -X POST "http://localhost:8000/api/files/upload?path=/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@/local/path/file.txt"
# Create directory
curl -X POST http://localhost:8000/api/files/mkdir \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/new_folder"}'
# Create file
curl -X POST http://localhost:8000/api/files/create \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/notes.txt","content":"Hello World"}'
# Rename file
curl -X POST http://localhost:8000/api/files/rename \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"old_path":"/oldname.txt","new_name":"newname.txt"}'
# Delete file
curl -X DELETE "http://localhost:8000/api/files/delete?path=/file.txt" \
-H "Authorization: Bearer YOUR_TOKEN"
# Delete directory (recursive)
curl -X DELETE "http://localhost:8000/api/files/delete?path=/folder&recursive=true" \
-H "Authorization: Bearer YOUR_TOKEN"
# Get space usage
curl http://localhost:8000/api/files/space \
-H "Authorization: Bearer YOUR_TOKEN"
Architecture
Services
- zfs_runner.py: Subprocess wrapper for ZFS commands with caching
- auth.py: JWT token generation and verification
Routers
- auth.py: Login endpoint
- pools.py: Pool list, status, scrub operations
- datasets.py: Dataset CRUD operations
- snapshots.py: Snapshot CRUD, rollback
Models
- pool.py: Pool, PoolStatus, PoolHealth
- dataset.py: Dataset, DatasetType
- snapshot.py: Snapshot
- auth.py: User, Token, TokenData
Caching Strategy
- Pool status: 30s TTL
- Snapshots: 60s TTL
- Datasets: 60s TTL
Cache is cleared on mutations (create/delete operations).
Performance Notes
For 4GB RAM Raspberry Pi:
- gunicorn: 2 workers
- Memory limit: 512M soft / 768M hard
- Connection timeout: 30s
- Max requests per worker: 500 (recycle to prevent memory leaks)
Optimizations:
- ZFS queries limited to max depth 2
- Snapshots limited to 50 by default (can be increased with
?limit=N) - Subprocess timeout: 5s
- In-memory TTL cache (no Redis required)
Production Deployment
- Copy backend to
/opt/zmb-webui/backend - Install systemd service:
sudo cp deploy/zmb-webui-backend.service /etc/systemd/system/ - Update users:
python3 -c "from services.auth import auth_service; auth_service.add_user('yourusername', 'strongpassword')" - Start service:
sudo systemctl daemon-reload sudo systemctl enable zmb-webui-backend sudo systemctl start zmb-webui-backend
Troubleshooting
ZFS commands not working
- Check:
zpool listruns without errors - Check: Running as root or with proper sudo permissions
- Check: ZFS kernel module is loaded:
lsmod | grep zfs
Memory usage growing
- Check:
ps aux | grep uvicornfor VSZ/RSS - Restart service:
systemctl restart zmb-webui-backend - Increase frequency of restarts in crontab if needed
Slow responses
- Check:
zpool statusoutput (large pool = slow scrub) - Clear cache:
curl -X POST /api/pools/clear-cache(with auth) - Consider increasing cache TTLs in
zfs_runner.py
Development Tips
- Use
curlor Postman for API testing - Check logs:
journalctl -u zmb-webui-backend -f - Interactive API docs:
http://localhost:8000/docs(after running)