v0.142.0: offsite repo continuity — orphaned-repo guard (A) + run-status auto-refresh (C)
- Part A: classify restic cat-config failure (wrong-password=orphaned vs no-repo vs other); ORPHANED state + Hungarian card + offbox_repo_orphaned/reset events (once, not nightly); reset = move-aside (never delete) + init, unclaimed auto / claimed confirm. Red-proofs TestOffbox_OrphanDetection_* + ConfirmedReset. - Part C: GET /backup/offbox/status + poll on backups_remote → flips Fut→Rendben/Hiba without manual reload.
This commit is contained in:
@@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -209,6 +210,12 @@ func (s *Server) offboxRunHandler(w http.ResponseWriter, r *http.Request) {
|
||||
offboxRedirect(w, r, "A távoli mentés a kulcs letétbe helyezésére vár.", true)
|
||||
return
|
||||
}
|
||||
// Offsite-repo continuity (v0.142.0): an ORPHANED repo can't be written — route the customer to the
|
||||
// orphan card's explanation/reset instead of attempting a doomed write.
|
||||
if s.backupMgr.OffboxOrphaned() {
|
||||
offboxRedirect(w, r, "A távoli tároló elárvult — előbb indíts új távoli mentést a kártyán látható módon.", true)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Hour)
|
||||
defer cancel()
|
||||
@@ -219,6 +226,50 @@ func (s *Server) offboxRunHandler(w http.ResponseWriter, r *http.Request) {
|
||||
offboxRedirect(w, r, "A távoli mentés elindult (a futás után az állapot frissül).", false)
|
||||
}
|
||||
|
||||
// offboxResetHandler is the CLAIMED confirmed orphaned-repo reset (Scenario C): move the old (recovery-
|
||||
// code-recoverable) history aside — never delete — and init a fresh repo. Refuses unless orphaned AND
|
||||
// explicitly confirmed (confirm=1, set by the reveal-then-confirm block on the orphan card).
|
||||
func (s *Server) offboxResetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if s.backupMgr == nil || !s.backupMgr.OffboxConfigured() {
|
||||
offboxRedirect(w, r, "A távoli mentési cél nincs beállítva.", true)
|
||||
return
|
||||
}
|
||||
if !s.backupMgr.OffboxOrphaned() {
|
||||
offboxRedirect(w, r, "Az offsite tároló nincs elárvult állapotban.", true)
|
||||
return
|
||||
}
|
||||
if r.FormValue("confirm") != "1" {
|
||||
offboxRedirect(w, r, "A visszaállításhoz megerősítés szükséges.", true)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
if err := s.backupMgr.ResetOrphanedRepo(ctx); err != nil {
|
||||
s.logger.Printf("[WARN] [web] offbox orphaned-repo reset failed: %v", err)
|
||||
}
|
||||
}()
|
||||
offboxRedirect(w, r, "Új távoli mentés indítása folyamatban — a régi előzmény félretéve (nem törölve).", false)
|
||||
}
|
||||
|
||||
// offboxStatusHandler (Part C) is the poll source for the remote-backup run status — the page polls it
|
||||
// after "Távoli mentés most" and flips to the terminal state without a manual reload. Session-auth'd.
|
||||
func (s *Server) offboxStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
t := s.settings.GetOffboxTarget()
|
||||
resp := map[string]any{"status": "", "snapshots": 0, "orphaned": false}
|
||||
if t != nil {
|
||||
resp["status"] = t.LastStatus
|
||||
resp["snapshots"] = t.SnapshotCount
|
||||
resp["last_run"] = t.LastRun
|
||||
resp["last_duration"] = t.LastDuration
|
||||
resp["repo_size_human"] = t.RepoSizeHuman
|
||||
resp["last_error"] = t.LastError
|
||||
resp["orphaned"] = t.RepoState == "orphaned"
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}
|
||||
|
||||
// offboxRestoreHandler restores an app's off-box data to an on-data-drive scratch dir (§7, F-A1;
|
||||
// non-destructive — does NOT overwrite live data). mode=unit (default) restores the recovery unit
|
||||
// only; mode=full is size-gated and two-step (first POST computes the size + headroom and redirects
|
||||
|
||||
Reference in New Issue
Block a user