feat(audit): capture IPMI FRU/Elabel, mc info and LAN on every audit

The techdump — the only place the IPMI FRU / Elabel identity (Product Name
= server model, serials, part numbers) is recorded — only ran under LiveCD.
Run it on every audit so `bee audit` on an installed host captures it too.

Also add `ipmitool mc info` and `ipmitool lan print` to the techdump, and
pin `ipmitool fru print 0` to FRU device 0 to match the Export Tools
"FRU / Elabel" editor exactly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-09-03 15:18:01 +03:00
co-authored by Claude Sonnet 5
parent 319f08ac4b
commit 76db45ee95
4 changed files with 61 additions and 5 deletions
+8 -1
View File
@@ -25,7 +25,14 @@ var techDumpFixedCommands = []struct {
{Name: "lsblk", Args: []string{"-J", "-d", "-o", "NAME,TYPE,SIZE,SERIAL,MODEL,TRAN,HCTL"}, File: "lsblk.json"},
{Name: "sh", Args: []string{"-c", StorageControllerMapScript}, File: "storage-controllers.txt"},
{Name: "sensors", Args: []string{"-j"}, File: "sensors.json"},
{Name: "ipmitool", Args: []string{"fru", "print"}, File: "ipmitool-fru.txt"},
// FRU / Elabel: the identity fields the Export Tools "FRU / Elabel" editor
// reads and rewrites (Product Name / server model, serial, part numbers).
// "fru print 0" pins FRU device 0 to match that editor exactly.
{Name: "ipmitool", Args: []string{"fru", "print", "0"}, File: "ipmitool-fru.txt"},
// BMC identity + LAN config, so a support bundle carries the same context
// the FRU editor shows alongside the elabel.
{Name: "ipmitool", Args: []string{"mc", "info"}, File: "ipmitool-mc-info.txt"},
{Name: "ipmitool", Args: []string{"lan", "print"}, File: "ipmitool-lan-print.txt"},
{Name: "ipmitool", Args: []string{"sdr"}, File: "ipmitool-sdr.txt"},
{Name: "ipmitool", Args: []string{"sensor"}, File: "ipmitool-sensor.txt"},
{Name: "ipmitool", Args: []string{"sel", "list"}, File: "ipmitool-sel.txt"},
+21
View File
@@ -7,6 +7,27 @@ import (
"testing"
)
func TestTechDumpCapturesIPMIIdentity(t *testing.T) {
t.Parallel()
want := map[string][]string{
"ipmitool-fru.txt": {"fru", "print", "0"},
"ipmitool-mc-info.txt": {"mc", "info"},
"ipmitool-lan-print.txt": {"lan", "print"},
}
for _, cmd := range techDumpFixedCommands {
if args, ok := want[cmd.File]; ok {
if cmd.Name != "ipmitool" || !reflect.DeepEqual(cmd.Args, args) {
t.Fatalf("%s: got %s %v, want ipmitool %v", cmd.File, cmd.Name, cmd.Args, args)
}
delete(want, cmd.File)
}
}
if len(want) != 0 {
t.Fatalf("techdump missing IPMI identity captures: %v", want)
}
}
func TestLSBLKDumpDevices(t *testing.T) {
t.Parallel()