v0.99.0 — R-82 operator rulings: 2-week offsite retention + one backup at a time
Ruling 1 (2 weeks of weekly offsite backups): localPruneSpec's blanket PBS refusal is now scoped — an ADDITIONAL tier with an explicit keep_last may prune its PBS target. The refusal still applies in full to the PRIMARY tier, because BackupTarget() defaults to felhom-pbs and KeepLast() defaults to 3, so a box with neither key set would silently prune its offsite DR to 3 restore points. An additional tier cannot have that accident (keep_last defaults to 0). Ruling 3 (first backup runs as long as needed; nothing else starts until done): - additional-tier wait bound 6h -> 12h (measured ~33 MB/min => ~5h for a first full 10 GB snapshot; 12h gives margin but stays bounded so a hung task still surfaces) - ONE BACKUP AT A TIME PER GUEST across all tiers: POST /backup returns 409 when a DIFFERENT tier is in flight, naming the busy tier, with NO data object so nothing is parseable as the caller's own job. Same tier still returns that job (202, unchanged). - snapshotted now counts as in-flight, not just running — after the snapshot the vzdump is still uploading and holding the lock. The old check left a window where a second POST started a real second vzdump. Latent bug, closed. Full suite green (29 packages); red-proof observed and restored.
This commit is contained in:
@@ -1286,7 +1286,10 @@ func buildLocalAPIServer(cfg config.Config, px *proxmox.Client, store *backup.St
|
||||
if t.KeepLast > 0 {
|
||||
prune = fmt.Sprintf("keep-last=%d", t.KeepLast)
|
||||
}
|
||||
r := backup.NewBackupRunnerWithWait(px, t.TargetID, "", "felhom local-api", prune, t.WaitTimeout, logger)
|
||||
// Pruning a PBS target is allowed ONLY for an additional tier with an explicit keep_last
|
||||
// (the primary's target AND retention both default, so it could prune the DR by accident).
|
||||
allowPBSPrune := !t.Primary && t.KeepLast > 0
|
||||
r := backup.NewBackupRunnerFull(px, t.TargetID, "", "felhom local-api", prune, t.WaitTimeout, allowPBSPrune, logger)
|
||||
if t.Primary {
|
||||
runner = r
|
||||
}
|
||||
@@ -1298,7 +1301,8 @@ func buildLocalAPIServer(cfg config.Config, px *proxmox.Client, store *backup.St
|
||||
Service: r,
|
||||
})
|
||||
logger.Info("backup tier armed", "target", t.TargetID, "cadence", t.Cadence.String(),
|
||||
"keep_last", t.KeepLast, "wait_timeout", t.WaitTimeout.String(), "primary", t.Primary)
|
||||
"keep_last", t.KeepLast, "wait_timeout", t.WaitTimeout.String(),
|
||||
"prune_pbs_allowed", allowPBSPrune, "primary", t.Primary)
|
||||
}
|
||||
// Guest data-drive passthrough (slice 10 P2): a root-CLI runner for the `pct set` bind + chown
|
||||
// (same fenced ExecRunner the host-storage + provision back-half use).
|
||||
|
||||
Reference in New Issue
Block a user