controller v0.50.0: slice 10 P4 — dual-role drives + backup-aware wipe warning
4A: user-data drives are backup-target-eligible (not role-locked) — surfaced in the drive purpose note. 4B: handleStorageImpact returns backup_copies (apps whose cross-drive backups live on the drive, via backupCopiesOnPath); the wipe/eject modal warns they'd be destroyed (stays customer-confirmable — copies redundant). Cross-drive backup engine remains out of scope. Test: TestBackupCopiesOnPath. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,12 +6,15 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/appbackup"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/system"
|
||||
)
|
||||
@@ -307,7 +310,42 @@ func (s *Server) handleStorageImpact(w http.ResponseWriter, r *http.Request) {
|
||||
if apps == nil {
|
||||
apps = []string{}
|
||||
}
|
||||
writeDiskJSON(w, http.StatusOK, true, "", map[string]any{"where": where, "apps": apps})
|
||||
// P4 (4B): a user-data drive is ALSO backup-target-eligible — it may hold cross-drive backup copies
|
||||
// of OTHER drives' app data. A wipe destroys those copies too, so name them in the confirmation.
|
||||
// (The copies are redundant — the originals live on the source drive — so the wipe stays customer-
|
||||
// confirmable, NOT operator-signature; the warning just makes the loss explicit.)
|
||||
backupCopies := backupCopiesOnPath(where)
|
||||
if backupCopies == nil {
|
||||
backupCopies = []string{}
|
||||
}
|
||||
writeDiskJSON(w, http.StatusOK, true, "", map[string]any{
|
||||
"where": where, "apps": apps, "backup_copies": backupCopies,
|
||||
})
|
||||
}
|
||||
|
||||
// backupCopiesOnPath lists the apps whose CROSS-DRIVE (secondary) backup copies are stored on the
|
||||
// drive mounted at `where` (slice 10 P4) — the felhom-data/backups/secondary/<app> dirs. A wipe of
|
||||
// this drive removes these copies. Best-effort filesystem scan; empty until the cross-drive backup
|
||||
// ENGINE (a follow-on slice) actually writes here. Shared/aggregate dirs (restic repo, _infra) are
|
||||
// not apps and are skipped.
|
||||
func backupCopiesOnPath(where string) []string {
|
||||
secondary := filepath.Join(where, appbackup.FelhomDataDir, "backups", "secondary")
|
||||
entries, err := os.ReadDir(secondary)
|
||||
if err != nil {
|
||||
return nil // no secondary backups here (or the path isn't readable) — nothing to warn about
|
||||
}
|
||||
var apps []string
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := e.Name()
|
||||
if name == "restic" || name == "_infra" { // shared repo / infra, not a per-app copy
|
||||
continue
|
||||
}
|
||||
apps = append(apps, name)
|
||||
}
|
||||
return apps
|
||||
}
|
||||
|
||||
// handleStorageWipe is the customer-confirmed wipe of a USER-DATA drive: it unmounts (eject —
|
||||
|
||||
Reference in New Issue
Block a user