v0.84.0: ReassertNetworkMounts — NAS automount survives guest reboots (RCA fix 1)
Storage §8 decision table (stop + enable --now on idle triggers; active mounts untouched), daemon leg at startup with per-running-guest visibility verify, guest-hook post-start leg (root, direct systemctl, non-fatal). Red-proofs: always-rearm table FAIL; unwired hook FAIL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package guesthook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-agent/internal/storage"
|
||||
)
|
||||
|
||||
type fakeReasserter struct {
|
||||
invoked int
|
||||
results []storage.NetReassertResult
|
||||
}
|
||||
|
||||
func (f *fakeReasserter) ReassertNetworkAutomounts(context.Context) []storage.NetReassertResult {
|
||||
f.invoked++
|
||||
return f.results
|
||||
}
|
||||
|
||||
// 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 skip-none/errored rows.
|
||||
func TestPostStartNetworkReassert_Core(t *testing.T) {
|
||||
ops := &fakeReasserter{results: []storage.NetReassertResult{
|
||||
{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertRearmed},
|
||||
{Name: "active", Where: "/mnt/felhom-drives/active", Action: storage.NetReassertSkipActive},
|
||||
{Name: "gone", Where: "/mnt/felhom-drives/gone", Action: storage.NetReassertSkipNone},
|
||||
}}
|
||||
var verified []string
|
||||
postStartNetworkReassert(context.Background(), "9201", ops, func(_ context.Context, vmid, path string) bool {
|
||||
if vmid != "9201" {
|
||||
t.Errorf("verify called with vmid %q, want 9201", vmid)
|
||||
}
|
||||
verified = append(verified, path)
|
||||
return true
|
||||
})
|
||||
if ops.invoked != 1 {
|
||||
t.Fatalf("reassert pass invoked %d times, want 1", ops.invoked)
|
||||
}
|
||||
if len(verified) != 2 || verified[0] != "/mnt/felhom-drives/media" || verified[1] != "/mnt/felhom-drives/active" {
|
||||
t.Fatalf("verify must cover rearmed + skip-active only, got %v", verified)
|
||||
}
|
||||
}
|
||||
|
||||
// A failed verify must be non-fatal: the core returns normally (the hook exits 0 regardless).
|
||||
func TestPostStartNetworkReassert_VerifyFailureNonFatal(t *testing.T) {
|
||||
ops := &fakeReasserter{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).
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user