F20-BUG3: run mkfs detached (survives request deadline + agent restart); v0.31.0
The format ran mkfs under the HTTP request context, so the controller's 15s client timeout cancelled it → SIGKILL mid-write → corrupt disk. Now mkfs runs DETACHED off s.baseCtx (a dropped request can't kill it) via a persisted formatJob record; the handler still waits to return the synchronous result (backward-compatible with the v0.62.0 controller) but abandoning the wait on client-disconnect leaves the mkfs running to completion. New GET /disks/format/status surfaces the job (additive). RecoverFormatJob runs on agent startup: a record left 'running' (agent died mid-format) is re-resolved by durable-id (anti-retarget — absent/swapped disk NOT re-formatted) and the mkfs re-run; a blank/path-bound interrupted format is marked failed (retry), never auto-re-run. Tests: detached run persists running→done + binds durable-id; status endpoint; recovery re-runs an interrupted durable-id-bound format; skips blank; skips unresolvable durable-id. Version 0.30.0 → 0.31.0.
This commit is contained in:
@@ -91,6 +91,10 @@ type Options struct {
|
||||
// startup re-assert (ReassertGuestBinds) can restore a bind that a re-provision dropped (F9).
|
||||
// OPTIONAL — when nil, guest binds are not recorded and the startup re-assert is a no-op.
|
||||
GuestBinds *GuestBindStore
|
||||
// FormatJobs persists the in-flight/last disk-format job so mkfs runs detached from the request
|
||||
// (F20-BUG3: a request deadline can't kill it) and survives an agent restart (RecoverFormatJob).
|
||||
// OPTIONAL — when nil, formats still run detached but are not persisted/recovered.
|
||||
FormatJobs *FormatJobStore
|
||||
// HostReader is the root-free host topology reader used to classify a device/mount's protection
|
||||
// ROLE (it backs SystemDisks for the eject role-gate + the /disks role hints). OPTIONAL — when nil
|
||||
// it defaults to the production *storage.ProcHostReader. Injectable so the role-gate is testable.
|
||||
@@ -148,6 +152,7 @@ type Server struct {
|
||||
guestAttach GuestAttacher // slice 10 P2 (optional)
|
||||
intent IntentRecorder // slice 10 P3 (optional)
|
||||
guestBinds *GuestBindStore // F9 startup bind re-assert record (optional)
|
||||
formatJobs *FormatJobStore // F20-BUG3 detached-format job record (optional)
|
||||
host storage.HostReader // role classification source (optional; defaults to ProcHostReader)
|
||||
|
||||
hostMetrics HostMetricsProvider // slice 9 (optional)
|
||||
@@ -204,6 +209,7 @@ func NewServer(o Options) (*Server, error) {
|
||||
guestAttach: o.GuestAttach,
|
||||
intent: o.Intent,
|
||||
guestBinds: o.GuestBinds,
|
||||
formatJobs: o.FormatJobs,
|
||||
host: o.HostReader,
|
||||
hostMetrics: o.HostMetrics,
|
||||
hostID: o.HostID,
|
||||
@@ -232,6 +238,7 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("POST /disks/assign", s.withGuest(s.handleDiskAssign))
|
||||
mux.HandleFunc("POST /disks/eject", s.withGuest(s.handleDiskEject))
|
||||
mux.HandleFunc("POST /disks/format", s.withGuest(s.handleDiskFormat))
|
||||
mux.HandleFunc("GET /disks/format/status", s.withGuest(s.handleDiskFormatStatus))
|
||||
// Guest data-drive passthrough (slice 10 P2): bind an enrolled drive's felhom-data namespace in.
|
||||
mux.HandleFunc("POST /disks/guest-attach", s.withGuest(s.handleDiskGuestAttach))
|
||||
// Guest reboot (slice 10 P2 activation): user-triggered restart to activate pending drive binds.
|
||||
|
||||
Reference in New Issue
Block a user