F11 matrix-correction: re-arm on guest-blind (active mounts not inherited by rebooted guest — live finding)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
This commit is contained in:
@@ -8,8 +8,10 @@ import (
|
||||
)
|
||||
|
||||
type fakeReasserter struct {
|
||||
invoked int
|
||||
results []storage.NetReassertResult
|
||||
invoked int
|
||||
rearmed []string
|
||||
rearmErr error
|
||||
results []storage.NetReassertResult
|
||||
}
|
||||
|
||||
func (f *fakeReasserter) ReassertNetworkAutomounts(context.Context) []storage.NetReassertResult {
|
||||
@@ -17,6 +19,11 @@ func (f *fakeReasserter) ReassertNetworkAutomounts(context.Context) []storage.Ne
|
||||
return f.results
|
||||
}
|
||||
|
||||
func (f *fakeReasserter) RearmNetworkAutomount(_ context.Context, where string) error {
|
||||
f.rearmed = append(f.rearmed, where)
|
||||
return f.rearmErr
|
||||
}
|
||||
|
||||
// The post-start core must run the reassert pass and verify guest visibility for every share the
|
||||
// pass acted on (or found actively mounted) — and never for foreign/errored rows.
|
||||
func TestPostStartNetworkReassert_Core(t *testing.T) {
|
||||
@@ -41,16 +48,41 @@ func TestPostStartNetworkReassert_Core(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A failed verify must be non-fatal: the core returns normally (the hook exits 0 regardless).
|
||||
func TestPostStartNetworkReassert_VerifyFailureNonFatal(t *testing.T) {
|
||||
// F11 matrix-correction: a guest that does NOT see a share (even a skip-active one) must trigger a
|
||||
// re-arm of that specific share, then a re-verify. Encodes the live 2026-07-12 finding that a rebooted
|
||||
// guest inherits neither an idle trigger nor an active mount.
|
||||
func TestPostStartNetworkReassert_RearmsWhenGuestBlind(t *testing.T) {
|
||||
ops := &fakeReasserter{results: []storage.NetReassertResult{
|
||||
{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertRearmed},
|
||||
{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertSkipActive},
|
||||
}}
|
||||
// Must not panic or abort; the WARNING goes to stderr (PVE task log).
|
||||
// sees: false the first time (blind), true the second (post-rearm) — the heal path.
|
||||
calls := 0
|
||||
postStartNetworkReassert(context.Background(), "9201", ops, func(context.Context, string, string) bool {
|
||||
calls++
|
||||
return calls >= 2
|
||||
})
|
||||
if len(ops.rearmed) != 1 || ops.rearmed[0] != "/mnt/felhom-drives/media" {
|
||||
t.Fatalf("a blind guest must trigger exactly one re-arm of the share, got %v", ops.rearmed)
|
||||
}
|
||||
}
|
||||
|
||||
// A failed verify must be non-fatal even if the re-arm also fails: the core returns normally (hook
|
||||
// exits 0 regardless).
|
||||
func TestPostStartNetworkReassert_VerifyFailureNonFatal(t *testing.T) {
|
||||
ops := &fakeReasserter{
|
||||
rearmErr: context.DeadlineExceeded,
|
||||
results: []storage.NetReassertResult{
|
||||
{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertRearmed},
|
||||
},
|
||||
}
|
||||
// Must not panic or abort; the WARNING goes to stderr (PVE task log). Guest never sees it, re-arm errors.
|
||||
postStartNetworkReassert(context.Background(), "9201", ops, func(context.Context, string, string) bool {
|
||||
return false
|
||||
})
|
||||
if ops.invoked != 1 {
|
||||
t.Fatalf("reassert pass invoked %d times, want 1", ops.invoked)
|
||||
}
|
||||
if len(ops.rearmed) != 1 {
|
||||
t.Fatalf("a blind guest must attempt one re-arm, got %d", len(ops.rearmed))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user