v0.55.0: Phase 3 — auto off-drive Tier 2 (rootfs-headroom guard)
Tier 2 rsync-mirrors each HDD app's recovery unit + appdata to a DIFFERENT physical disk (the only off-drive protection bind-mounted userdata can get; PBS can't reach it). Auto-enabled, auto-target: prefer another registered drive (different physical disk via system.SamePhysicalDevice), else the internal SSD for SMALL units only — with a size-aware headroom guard that REFUSES rather than fill the ~8G guest rootfs, recording an honest "needs 2nd HDD" status. Status persisted via the surviving CrossDriveBackup; "2. mentés" UI card now populated. Daily tier2-backup job + POST /api/backup/tier2. - backup/tier2.go (engine+selection+headroom), tier2_test.go (headroom arithmetic) - system.SamePhysicalDevice (linux Stat_t.Dev + stub) - handlers.go Tier2 UI population + tier2DestLabel; backups.html honest no-target reason - fixed stale TestBackupCopiesOnPath (old felhom-data layout -> in-guest layout) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -221,6 +221,10 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
case path == "/backup/run" && req.Method == http.MethodPost:
|
||||
r.triggerBackup(w, req)
|
||||
|
||||
// POST /api/backup/tier2 — run off-drive Tier 2 copies for all HDD apps
|
||||
case path == "/backup/tier2" && req.Method == http.MethodPost:
|
||||
r.triggerTier2(w, req)
|
||||
|
||||
// GET /api/metrics/system
|
||||
case path == "/metrics/system" && req.Method == http.MethodGet:
|
||||
r.metricsSystem(w, req)
|
||||
@@ -749,6 +753,22 @@ func (r *Router) triggerBackup(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(w, http.StatusOK, apiResponse{OK: true, Message: "Mentés elindítva"})
|
||||
}
|
||||
|
||||
// triggerTier2 runs the off-drive Tier 2 copies for all HDD apps (recovery unit + userdata to a
|
||||
// different physical disk). Auto-targets and applies the rootfs-headroom guard internally.
|
||||
func (r *Router) triggerTier2(w http.ResponseWriter, _ *http.Request) {
|
||||
if r.backupMgr == nil {
|
||||
writeJSON(w, http.StatusBadRequest, apiResponse{OK: false, Error: "Backup not configured"})
|
||||
return
|
||||
}
|
||||
if r.backupMgr.IsRunning() {
|
||||
writeJSON(w, http.StatusConflict, apiResponse{OK: false, Error: "Mentés már folyamatban"})
|
||||
return
|
||||
}
|
||||
r.logger.Println("[INFO] [api] Manual Tier 2 (off-drive) backup triggered")
|
||||
go r.backupMgr.RunAllTier2()
|
||||
writeJSON(w, http.StatusOK, apiResponse{OK: true, Message: "2. mentés elindítva"})
|
||||
}
|
||||
|
||||
// --- Metrics handlers ---
|
||||
|
||||
func (r *Router) metricsSystem(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user