2d24931597
gates / gates (push) Successful in 24s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
70 lines
2.5 KiB
Go
70 lines
2.5 KiB
Go
package monitor
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
|
)
|
|
|
|
// R-672 (hub v0.124.0): an lvmthin pool is CRITICAL at 90 % of data OR metadata. The consequence is the
|
|
// event the operator receives, asserted per case.
|
|
//
|
|
// COMPANION RED-PROOF (REPORT): `judged` returning the generic bands and data only (hub v0.123.0) → a
|
|
// thin pool at 91 % raises only storage_fill_warning, and a metadata-full pool raises nothing.
|
|
func saveThin(t *testing.T, st *store.Store, dataPct, metaPct float64) {
|
|
t.Helper()
|
|
body := []byte(`{"host_id":"h1","storage_targets":[{"name":"local-lvm","type":"lvmthin","mount_path":"","used_fraction":` +
|
|
ftoa(dataPct/100) + `,"total_bytes":1000,"used_bytes":1,"thin_pool":{"data_used_fraction":` + ftoa(dataPct/100) +
|
|
`,"metadata_used_fraction":` + ftoa(metaPct/100) + `}}]}`)
|
|
if err := st.SaveHostReport("h1", "c1", body, store.HostReportDenorm{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ftoa(f float64) string { return strconv.FormatFloat(f, 'g', -1, 64) }
|
|
|
|
func TestR672_ThinPoolCriticalAt90(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
data, meta float64
|
|
wantType, sev string
|
|
}{
|
|
{"data 91 %", 91, 3, "storage_fill_critical", "critical"},
|
|
{"metadata 92 %, data 50 %", 50, 92, "storage_fill_critical", "critical"},
|
|
{"data 87 %", 87, 3, "storage_fill_warning", "warning"},
|
|
{"data 60 %", 60, 3, "", ""},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
st := newDiskStore(t)
|
|
saveThin(t, st, 10, 1)
|
|
var types, sevs []string
|
|
fc := NewStorageFillChecker(st, 90, 95, func(_, et, sev, _, _, _ string) { types = append(types, et); sevs = append(sevs, sev) }, quietLog())
|
|
saveThin(t, st, tc.data, tc.meta)
|
|
fc.Check()
|
|
if tc.wantType == "" {
|
|
if len(types) != 0 {
|
|
t.Fatalf("a healthy pool raised %v", types)
|
|
}
|
|
return
|
|
}
|
|
if len(types) != 1 || types[0] != tc.wantType || sevs[0] != tc.sev {
|
|
t.Fatalf("events = %v %v — want one %s (%s)", types, sevs, tc.wantType, tc.sev)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// A non-thin storage keeps the generic bands: 91 % is a warning.
|
|
func TestR672_NonThinUnchanged(t *testing.T) {
|
|
st := newDiskStore(t)
|
|
saveStorageReport(t, st, stTarget{"dumpvol", "local-dir", "/mnt/backup", 10})
|
|
var types []string
|
|
fc := NewStorageFillChecker(st, 90, 95, func(_, et, _, _, _, _ string) { types = append(types, et) }, quietLog())
|
|
saveStorageReport(t, st, stTarget{"dumpvol", "local-dir", "/mnt/backup", 91})
|
|
fc.Check()
|
|
if len(types) != 1 || types[0] != "storage_fill_warning" {
|
|
t.Fatalf("a dir storage at 91 %% must stay a warning: %v", types)
|
|
}
|
|
}
|