Offsite tier policy engine: mandatory userdata, raw-data quota, restore rework (Task 3a, v0.134.0)
Each toggled app's offsite push = one multi-path restic snapshot (recovery unit + TierOffsite mandatory userdata via ComputeCaptureSet); legacy/undeployed stay unit-only. Loud capture gaps (SP-3.4: restic 0.14.0 silently skips missing paths). Quota = stats --mode raw-data (SP-1; displayed size drops once). Pre-push enlargement gate blocks the userdata enlargement over-quota (unit-only push continues; EnlargedBlocked; edge-triggered notify). forget --group-by host,tags on both sites (SP-2). Restore reworked: scratch off the rootfs + headroom gate (F-A1), unit-only default via --include, size-first full, place-to-live missing-only merge (never --delete). UI: unit/full-two-step/place actions + per-app blocked note; route POST /backup/offbox/place. HUB FLAG: offbox_enlarge_blocked event needs hub allowlist for push delivery. +13 tests; all 10 §10 red-proofs verified. No tier-2/.fab/hub/agent changes.
This commit is contained in:
@@ -661,6 +661,14 @@ func (s *Server) backupsOffboxData(data map[string]interface{}) {
|
||||
}
|
||||
// SLICE 4 soft-quota usage bar (rendered only when a quota is set — shared model).
|
||||
data["OffboxQuotaPct"] = backup.OffboxQuotaPercent(offboxTgt)
|
||||
// 3a: per-app "config+DB only" note set — apps whose enlarged push the quota gate blocked last run.
|
||||
blocked := map[string]bool{}
|
||||
if offboxTgt != nil {
|
||||
for _, a := range offboxTgt.EnlargedBlocked {
|
||||
blocked[a] = true
|
||||
}
|
||||
}
|
||||
data["OffboxBlockedSet"] = blocked
|
||||
}
|
||||
|
||||
// offboxStaleWarningMarker is the substring the zero-toggled offbox run writes into
|
||||
@@ -757,6 +765,24 @@ func (s *Server) backupsAppsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *Server) backupsRestoreHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := s.backupsCommonData("backups-restore", "Biztonsági mentés — Visszaállítás", r)
|
||||
s.backupsOffboxData(data) // restore-to-verify lists the offbox-toggled apps
|
||||
// Full-restore two-step reveal (§7.2): after the size+headroom prepare step, offboxRestoreHandler
|
||||
// redirects here with the app + human size so the confirm section can show the size BEFORE starting.
|
||||
if fp := strings.TrimSpace(r.URL.Query().Get("full_prep")); fp != "" {
|
||||
data["FullPrepApp"] = fp
|
||||
data["FullPrepSize"] = r.URL.Query().Get("full_size")
|
||||
}
|
||||
// Per-app place-to-live availability (a completed full scratch exists → offer the merge action).
|
||||
ready := map[string]bool{}
|
||||
if s.backupMgr != nil {
|
||||
if apps, ok := data["OffboxApps"].([]OffboxAppRow); ok {
|
||||
for _, a := range apps {
|
||||
if a.Enabled && s.backupMgr.OffboxFullScratchReady(a.Name) {
|
||||
ready[a.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data["OffboxScratchReady"] = ready
|
||||
s.executeTemplate(w, r, "backups_restore", data)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user