Files
deploy-felhom-compose/TASK.md
T

318 lines
11 KiB
Markdown

# TASK: Show all storage paths on dashboard + fix hub report (v0.15.3)
Two issues after introducing partitioned system drives (OS and user data on separate partitions):
1. **Dashboard & Monitoring pages** only show "SSD tárhely" (root `/`) and "Külső HDD" (one default storage path). Missing: the data partition on the system drive (`/mnt/sys_drive`). All registered storage paths should appear as separate bars.
2. **Hub storage report** only sends root `/` and one HDD entry (with wrong mount path — uses deprecated `cfg.Paths.HDDPath` which is `""`). This causes the hub to display incorrect/stale storage info and a spurious "nem külön meghajtón van" warning.
## Current state (demo-felhom)
```
sda1 ext4 → /mnt/sys_drive (user data partition, 320G)
sda3 ext4 → / (OS partition, 139G)
sdb1 ext4 → /mnt/hdd_1 (external USB HDD, 916G)
```
Registered storage paths in `settings.json`:
```json
"storage_paths": [
{"path": "/mnt/hdd_1", "label": "USB HDD 1TB", "is_default": true},
{"path": "/mnt/sys_drive", "label": "SYS Storage 350G", "schedulable": true}
]
```
Config `controller.yaml`:
- `paths.system_data_path: "/mnt/sys_drive"`
- `paths.hdd_path: ""` (deprecated, empty)
Health check already works correctly: `IsMountPoint("/mnt/sys_drive")` returns `true` inside container (Dev 2049 ≠ parent Dev 2051). No code changes needed in `healthcheck.go`.
---
## Fix 1: Dashboard & Monitoring — show all storage paths
### Root cause
`SystemInfo` struct only has fields for ONE SSD (root `/`) and ONE HDD. `GetInfo(hddPath)` takes a single HDD path. Templates hardcode "SSD tárhely" and "Külső HDD" labels.
### Fix approach
Pass a separate `StorageBars` list to templates alongside `SystemInfo` (which keeps SSD/root info). Each storage bar has label, usage, and color.
### Implementation steps
#### Step 1: Add `StorageBarInfo` type
In `controller/internal/web/handlers.go` (or a new small type near the top), add:
```go
// StorageBarInfo holds data for rendering a storage usage bar on dashboard/monitoring.
type StorageBarInfo struct {
Label string // e.g., "USB HDD 1TB", "SYS Storage 350G"
Path string // e.g., "/mnt/hdd_1"
TotalGB float64
UsedGB float64
Percent float64
}
```
#### Step 2: Build storage bars in handlers
Create a helper method on `Server`:
```go
func (s *Server) buildStorageBars() []StorageBarInfo {
var bars []StorageBarInfo
for _, sp := range s.settings.GetStoragePaths() {
di := system.GetDiskUsage(sp.Path)
if di == nil {
continue
}
bars = append(bars, StorageBarInfo{
Label: sp.Label,
Path: sp.Path,
TotalGB: di.TotalGB,
UsedGB: di.UsedGB,
Percent: di.UsedPercent,
})
}
return bars
}
```
In `dashboardHandler()` (~line 84-91), ADD after the SystemInfo line:
```go
data["StorageBars"] = s.buildStorageBars()
```
In `monitoringHandler()` (~line 365), ADD:
```go
data["StorageBars"] = s.buildStorageBars()
```
#### Step 3: Update dashboard template
**File:** `controller/internal/web/templates/dashboard.html` (~lines 58-91)
Replace the storage section. Keep the SSD bar as-is. Replace the single `{{if .SystemInfo.HDDConfigured}}` HDD block with a range over `StorageBars`:
**Current code** (lines 68-78):
```html
{{if .SystemInfo.HDDConfigured}}
<div class="system-info-item">
<div class="system-info-header">
<span class="system-info-label">Külső HDD</span>
<span class="system-info-value">{{fmtGB .SystemInfo.HDDUsedGB}} / {{fmtGB .SystemInfo.HDDTotalGB}} ({{printf "%.0f" .SystemInfo.HDDPercent}}%)</span>
</div>
<div class="system-bar">
<div class="system-bar-fill system-bar-{{usageColor .SystemInfo.HDDPercent}}" style="width:{{printf "%.0f" .SystemInfo.HDDPercent}}%"></div>
</div>
</div>
{{end}}
```
**Replace with:**
```html
{{range .StorageBars}}
<div class="system-info-item">
<div class="system-info-header">
<span class="system-info-label">{{.Label}}</span>
<span class="system-info-value">{{fmtGB .UsedGB}} / {{fmtGB .TotalGB}} ({{printf "%.0f" .Percent}}%)</span>
</div>
<div class="system-bar">
<div class="system-bar-fill system-bar-{{usageColor .Percent}}" style="width:{{printf "%.0f" .Percent}}%"></div>
</div>
</div>
{{end}}
```
#### Step 4: Update monitoring template
**File:** `controller/internal/web/templates/monitoring.html` (~lines 53-63)
Same pattern — replace the `{{if .HDDConfigured}}` block:
**Current code** (lines 53-63):
```html
{{if .HDDConfigured}}
<div class="storage-item">
<div class="storage-header">
<span class="storage-label">Külső HDD</span>
<span class="storage-value">{{fmtGB .HDDUsedGB}} / {{fmtGB .HDDTotalGB}} ({{printf "%.0f" .HDDPercent}}%)</span>
</div>
<div class="system-bar">
<div class="system-bar-fill {{usageColor .HDDPercent | printf "system-bar-%s"}}" style="width:{{printf "%.1f" .HDDPercent}}%"></div>
</div>
</div>
{{end}}
```
**Replace with** (note: this block is inside `{{with .SystemInfo}}` so we need to access root data with `$`):
```html
{{range $.StorageBars}}
<div class="storage-item">
<div class="storage-header">
<span class="storage-label">{{.Label}}</span>
<span class="storage-value">{{fmtGB .UsedGB}} / {{fmtGB .TotalGB}} ({{printf "%.0f" .Percent}}%)</span>
</div>
<div class="system-bar">
<div class="system-bar-fill {{usageColor .Percent | printf "system-bar-%s"}}" style="width:{{printf "%.1f" .Percent}}%"></div>
</div>
</div>
{{end}}
```
**IMPORTANT:** The monitoring template uses `{{with .SystemInfo}}` context (line 43), so `$.StorageBars` is needed to access the root template data. Check the exact template context before editing.
#### Step 5: Template function access
The `fmtGB` and `usageColor` template functions are already registered in `funcmap.go`. The `StorageBarInfo` fields (`TotalGB`, `UsedGB`, `Percent`) are `float64` — same types used by the existing SSD/HDD fields. No funcmap changes needed.
---
## Fix 2: Hub storage report — include all storage paths
### Root cause
In `controller/internal/report/builder.go` lines 62-72:
```go
r.Storage = []StorageReport{
{Mount: "/", TotalGB: sysInfo.DiskTotalGB, UsedGB: sysInfo.DiskUsedGB, Percent: sysInfo.DiskPercent},
}
if sysInfo.HDDConfigured {
r.Storage = append(r.Storage, StorageReport{
Mount: cfg.Paths.HDDPath, // BUG: empty string "", not the actual path
TotalGB: sysInfo.HDDTotalGB,
...
})
}
```
Two bugs:
1. `Mount: cfg.Paths.HDDPath` is `""` (deprecated field), so the hub receives an empty mount path
2. Only ONE extra storage entry is sent — misses additional storage paths like `/mnt/sys_drive`
### Fix
**File:** `controller/internal/report/builder.go`
#### Step 1: Add `Label` field to `StorageReport`
**File:** `controller/internal/report/types.go` (~line 39-44)
Add a `Label` field:
```go
type StorageReport struct {
Mount string `json:"mount"`
Label string `json:"label,omitempty"`
TotalGB float64 `json:"total_gb"`
UsedGB float64 `json:"used_gb"`
Percent float64 `json:"percent"`
}
```
#### Step 2: Replace storage section in BuildReport
**File:** `controller/internal/report/builder.go` (~lines 62-72)
Replace:
```go
// Storage
r.Storage = []StorageReport{
{Mount: "/", TotalGB: sysInfo.DiskTotalGB, UsedGB: sysInfo.DiskUsedGB, Percent: sysInfo.DiskPercent},
}
if sysInfo.HDDConfigured {
r.Storage = append(r.Storage, StorageReport{
Mount: cfg.Paths.HDDPath,
TotalGB: sysInfo.HDDTotalGB,
UsedGB: sysInfo.HDDUsedGB,
Percent: sysInfo.HDDPercent,
})
}
```
With:
```go
// Storage — root filesystem + all registered storage paths
r.Storage = []StorageReport{
{Mount: "/", Label: "SSD", TotalGB: sysInfo.DiskTotalGB, UsedGB: sysInfo.DiskUsedGB, Percent: sysInfo.DiskPercent},
}
for _, sp := range storagePaths {
di := system.GetDiskUsage(sp.Path)
if di == nil {
continue
}
r.Storage = append(r.Storage, StorageReport{
Mount: sp.Path,
Label: sp.Label,
TotalGB: di.TotalGB,
UsedGB: di.UsedGB,
Percent: di.UsedPercent,
})
}
```
**Note:** This requires adding `"gitea.dooplex.hu/admin/felhom-controller/internal/system"` to the imports in `builder.go` (it may already be imported — check first).
---
## Summary of files to modify
| File | Change |
|------|--------|
| `controller/internal/web/handlers.go` | Add `StorageBarInfo` type, `buildStorageBars()` method, pass `StorageBars` to dashboard/monitoring handlers |
| `controller/internal/web/templates/dashboard.html` | Replace hardcoded HDD bar with `{{range .StorageBars}}` |
| `controller/internal/web/templates/monitoring.html` | Replace hardcoded HDD bar with `{{range $.StorageBars}}` |
| `controller/internal/report/builder.go` | Replace storage section to iterate over all `storagePaths` with `system.GetDiskUsage()` |
| `controller/internal/report/types.go` | Add `Label` field to `StorageReport` |
## Build & Deploy
Version: **v0.15.3**
### Build workflow
```bash
SSH=/c/Windows/System32/OpenSSH/ssh.exe
# 1. Commit & push
cd e:/git/deploy-felhom-compose
git add -A && git commit -m "v0.15.3: Show all storage paths on dashboard/monitoring + fix hub report" && git push
# 2. Build
$SSH kisfenyo@192.168.0.180 "cd ~/build/felhom-controller && git -C ~/git/deploy-felhom-compose pull && ./build.sh v0.15.3 --push"
# 3. Deploy
$SSH kisfenyo@192.168.0.162 "cd /opt/docker/felhom-controller && sudo docker pull gitea.dooplex.hu/admin/felhom-controller:v0.15.3 && sudo sed -i 's|image: gitea.dooplex.hu/admin/felhom-controller:.*|image: gitea.dooplex.hu/admin/felhom-controller:v0.15.3|' docker-compose.yml && sudo docker compose up -d"
# 4. Verify
$SSH kisfenyo@192.168.0.162 "docker ps --filter name=felhom-controller --format '{{.Image}} {{.Status}}'"
```
### Compile check
Always run `go build ./...` in `controller/` before committing to ensure no compile errors.
## Documentation
Add a CHANGELOG.md entry at the top (under `## Changelog`). Read the first 30 lines to see the format, then insert a new entry. Example:
```markdown
### vX.X.X (2026-02-19 session XX)
- **v0.15.3 — Show all storage paths on dashboard + fix hub report:**
Dashboard ("Vezérlőpult") and monitoring ("Rendszermonitor") pages now show usage bars for ALL registered storage paths instead of just one hardcoded "Külső HDD" bar. Each bar displays the storage label and usage from settings.
Hub storage report now correctly includes all registered storage paths with proper mount paths and labels. Previously it sent only root `/` and one HDD entry with an empty mount path (used deprecated `cfg.Paths.HDDPath`).
**Files modified:** `internal/web/handlers.go`, `internal/web/templates/dashboard.html`, `internal/web/templates/monitoring.html`, `internal/report/builder.go`, `internal/report/types.go`
```
Update version in `C:\Users\User\.claude\projects\e--git\memory\MEMORY.md` to `v0.15.3`.
## Verification
After deploying v0.15.3:
1. Navigate to `/` (Vezérlőpult) — should show three bars: "SSD tárhely" + "USB HDD 1TB" + "SYS Storage 350G"
2. Navigate to `/monitoring` (Rendszermonitor) — same three bars in Tárhely section
3. Check hub at `hub.felhom.eu/customers/demo-felhom` — Health section should show no storage warnings; Storage should list all three mounts
4. No health warning about "nem külön meghajtón van" should appear (IsMountPoint already returns true for `/mnt/sys_drive`)