slice 8C Phase B.2 + C.1/C.2: retire disk subsystem + rewire disk mgmt to agent

Retired (~12.3k LOC): internal/storage/* (scan/format/attach/migrate/safety),
backup restic/crossdrive/restore_drives/disk_layout/local_infra/restore_scan/
paths + restore_app, report/infra_backup*/infra_pull, setup/scanner,
monitor/watchdog+pinger, web/storage_handlers+handler_restore. Surgically split
backup.Manager to app-data only (DB dumps + volume tars + app restore; dropped
restic + cross-drive + snapshot history). Fixed router/main/web wiring.
Added agent-backed disk API (web/agent_disk_handlers.go): /api/disks list/
assign/eject/format proxying agentapi; data-bearing format refusal -> HTTP 409
'operator authorization required'. report/config_pull.go keeps the setup
fresh-install config download. go build + go test green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 13:57:27 +02:00
parent 0294513906
commit abe4e8e619
47 changed files with 404 additions and 12317 deletions
-32
View File
@@ -11,7 +11,6 @@ import (
"strings"
"time"
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
"gitea.dooplex.hu/admin/felhom-controller/internal/system"
@@ -45,7 +44,6 @@ func Run(cfg *config.Config, sett *settings.Settings, logger *log.Logger) *Summa
func() CheckResult { return checkStoragePaths(sett) },
func() CheckResult { return checkGitCatalog(cfg.Paths.StacksDir) },
func() CheckResult { return checkHubConnectivity(cfg) },
func() CheckResult { return checkResticRepos(sett) },
func() CheckResult { return checkMetricsDB(cfg.Paths.DataDir) },
}
@@ -214,36 +212,6 @@ func checkHubConnectivity(cfg *config.Config) CheckResult {
return CheckResult{Name: "Hub connectivity", Status: "warn", Message: fmt.Sprintf("HTTP %d from %s", resp.StatusCode, url)}
}
func checkResticRepos(sett *settings.Settings) CheckResult {
paths := sett.GetStoragePaths()
if len(paths) == 0 {
return CheckResult{Name: "Restic repos", Status: "pass", Message: "no storage paths, skipped"}
}
found := 0
missing := 0
for _, sp := range paths {
if sp.Disconnected || sp.Decommissioned {
continue
}
repoPath := backup.PrimaryResticRepoPath(sp.Path)
if _, err := os.Stat(repoPath); err == nil {
found++
} else {
missing++
}
}
if found == 0 && missing > 0 {
return CheckResult{Name: "Restic repos", Status: "warn", Message: fmt.Sprintf("0 repos found, %d expected", missing)}
}
msg := fmt.Sprintf("%d repos found", found)
if missing > 0 {
msg += fmt.Sprintf(", %d missing", missing)
}
return CheckResult{Name: "Restic repos", Status: "pass", Message: msg}
}
func checkMetricsDB(dataDir string) CheckResult {
dbPath := filepath.Join(dataDir, "metrics.db")
info, err := os.Stat(dbPath)