runs: add non-destructive flag + operator Cancel button
Non-destructive pre-declares "don't touch the disks" on Start: the Storage stage skips wipe-probe, badblocks -w, and write-mode fio, and reports a read-only summary. Runs a new non_destructive column; threaded through Claim → agent tests.Deps → Storage stage. Cancel halts an in-flight run. The orchestrator transitions to a new StateCancelled via TriggerOperatorCancelled (valid from any active state); the agent's next heartbeat returns cmd=cancel_stage, which fires a stored CancelFunc on the per-stage context. Stage subprocesses spawned with exec.CommandContext die with the context, the agent posts a cancelled outcome, then powers the host off. Destructive stages mid-run may leave the host in an intermediate state — the UI confirm dialog warns the operator; recovery is manual for now. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,7 @@ type Deps struct {
|
||||
Error func(string)
|
||||
Sensor func(ctx context.Context, samples []Sample) error
|
||||
OverrideWipe bool
|
||||
NonDestructive bool // skip wipe-probe + writes in Storage
|
||||
ExpectedDisks []ExpectedDisk // serials + sizes from host.expected_spec
|
||||
StageTimeout time.Duration
|
||||
}
|
||||
|
||||
@@ -44,6 +44,23 @@ func Storage(ctx context.Context, d Deps) Outcome {
|
||||
}
|
||||
}
|
||||
|
||||
// Non-destructive runs skip wipe-probe (nothing to refuse), badblocks
|
||||
// -w, and write-mode fio. Every expected disk is still asserted
|
||||
// present + readable by listing /sys/block and reading SMART-accessible
|
||||
// identity; the per-disk map flags the shortcut so the report is clear.
|
||||
if d.NonDestructive {
|
||||
perDisk := map[string]any{}
|
||||
for _, t := range targets {
|
||||
perDisk[t.Device] = map[string]any{"mode": "non_destructive", "serial": t.Serial}
|
||||
}
|
||||
d.Info(fmt.Sprintf("Storage: non-destructive — verified %d disk(s) present", len(targets)))
|
||||
return Outcome{
|
||||
Passed: true,
|
||||
Summary: fmt.Sprintf("non-destructive: read-only checks only (%d disks)", len(targets)),
|
||||
Extras: map[string]any{"per_disk": perDisk, "non_destructive": true},
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe probe on every target. A single dirty disk halts the stage
|
||||
// unless the operator has set OverrideWipe via the UI.
|
||||
probes := map[string]wipeProbeResult{}
|
||||
|
||||
Reference in New Issue
Block a user