Files
llmgw/internal/preflight/preflight_test.go
T
Ilker ManapandClaude Opus 5.5 d110968243
CI / test (push) Successful in 8m42s
A machine too small for the models it would serve is said so first
A control plane that is also a node, serving the starter model and two
judges, needs about 10.5 GB: 3.5 for itself, 2 for the starter, 2 for each
judge, and one more because the scheduler counts whole gigabytes. On 8 GB
the install did every step and then had nowhere to run the starter. The
setup's checks now fail this machine's memory and name what it would serve,
and server init refuses before it installs anything, naming the flags that
leave those models off it. quick-install.md said 8 GB; it says 12.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:19:00 +01:00

123 lines
4.3 KiB
Go

package preflight
import (
"context"
"os"
"strconv"
"strings"
"testing"
"time"
"gitea.mynodes.xyz/ilker/llmgw/internal/onboard"
)
func facts(over map[string]string) map[string]string {
f := map[string]string{
"os": "ubuntu", "version": "24.04", "pretty": "Ubuntu 24.04.3 LTS", "arch": "x86_64",
"cpus": "2", "mem_mb": "3900", "disk_gb": "35", "ntp": "yes", "listening": "22 53",
"sudo": "yes", "apt": "yes", "internet": "yes",
"now": strconv.FormatFloat(float64(time.Now().UnixNano())/1e9, 'f', 3, 64),
}
for k, v := range over {
f[k] = v
}
return f
}
func levelOf(fs []Finding, check string) (Level, string) {
for _, f := range fs {
if f.Check == check {
return f.Level, f.Detail
}
}
return -1, ""
}
func TestAMachineFitForItsRoleHasNothingWrong(t *testing.T) {
fs := Evaluate(Machine{Name: "pg01", Roles: []Role{RoleDatabase}}, facts(nil), time.Now())
if r := (Report{Findings: fs}); r.Worst() != OK {
t.Errorf("%+v", fs)
}
}
func TestEachProblemIsFoundAndSaysWhatToDo(t *testing.T) {
m := Machine{Name: "x", Roles: []Role{RoleDatabase, RoleControl}}
cases := []struct {
over map[string]string
check string
want Level
}{
{map[string]string{"os": "centos", "version": "9"}, "system", Fail},
{map[string]string{"version": "20.04"}, "system", Warn},
{map[string]string{"arch": "riscv64"}, "architecture", Fail},
{map[string]string{"sudo": "no"}, "sudo", Warn},
{map[string]string{"mem_mb": "1000"}, "memory", Fail},
{map[string]string{"disk_gb": "20"}, "disk", Warn},
{map[string]string{"ntp": "no"}, "time sync", Warn},
{map[string]string{"listening": "22 5432"}, "ports", Warn},
{map[string]string{"internet": "no"}, "internet", Fail},
{map[string]string{"now": strconv.FormatFloat(float64(time.Now().Add(-30*time.Second).UnixNano())/1e9, 'f', 3, 64)}, "clock", Fail},
}
for _, c := range cases {
fs := Evaluate(m, facts(c.over), time.Now())
got, detail := levelOf(fs, c.check)
if got != c.want {
t.Errorf("%v: %s is %v (%s), want %v", c.over, c.check, got, detail, c.want)
}
for _, f := range fs {
if f.Level != OK && f.Fix == "" {
t.Errorf("%s: %s says nothing about what to do", c.check, f.Check)
}
}
}
// This machine is run as root; sudo is not its question.
if l, _ := levelOf(Evaluate(Machine{Name: "here", Local: true}, facts(map[string]string{"sudo": "no"}), time.Now()), "sudo"); l != -1 {
t.Error("the local machine was asked about sudo")
}
}
func TestAMachineThatCannotReachAnotherIsCalledOut(t *testing.T) {
fs := evaluateReach(Machine{Name: "a"}, "reach 10.0.0.2 yes\nreach 10.0.0.3 no\n")
if fs[0].Level != Fail || !strings.Contains(fs[0].Detail, "10.0.0.3") {
t.Errorf("%+v", fs)
}
}
// TestAgainstRealMachines runs the probe over ssh when LLMGW_TEST_PREFLIGHT
// names user@host,user@host: the scripts are shell, and only a real machine
// says whether they parse.
func TestAgainstRealMachines(t *testing.T) {
targets := os.Getenv("LLMGW_TEST_PREFLIGHT")
if targets == "" {
t.Skip("set LLMGW_TEST_PREFLIGHT=user@host,user@host to run against machines")
}
var ms []Machine
for _, tgt := range strings.Split(targets, ",") {
user, host, _ := strings.Cut(tgt, "@")
ms = append(ms, Machine{Name: host, Addr: host, Roles: []Role{RoleDatabase},
Remote: &onboard.GoSSH{Addr: host, User: user, UseAgent: true}})
}
rep := Run(context.Background(), ms)
for _, f := range rep.Findings {
t.Logf("%-12s %-12s %-5s %s", f.Machine, f.Check, f.Level, f.Detail)
}
for _, f := range rep.Findings {
if f.Check == "login" && f.Level != OK {
t.Fatalf("could not log in: %s", f.Detail)
}
}
}
// The guide's first recording: 8 GB, a control plane serving the starter and
// both judges, every step done and then no room for the starter. Now said at
// the checks, as a failure, before anything is installed.
func TestAMachineTooSmallForTheModelsItServesFailsTheCheck(t *testing.T) {
m := Machine{Name: "llm-1", Roles: []Role{RoleControl, RoleWitness}, ServesMB: 7 * 1024, Serves: "the starter model and 2 judges"}
if l, d := levelOf(Evaluate(m, facts(map[string]string{"mem_mb": "7941"}), time.Now()), "memory"); l != Fail || !strings.Contains(d, "2 judges") {
t.Errorf("8 GB: %v %q", l, d)
}
if l, d := levelOf(Evaluate(m, facts(map[string]string{"mem_mb": "11961"}), time.Now()), "memory"); l != OK {
t.Errorf("12 GB: %v %q", l, d)
}
}