add: memory, storage, pcie collectors (1.4-1.6) — tested on real hardware

This commit is contained in:
2026-03-05 14:50:34 +03:00
parent 569bbf8909
commit 55f6098a17
4 changed files with 381 additions and 1 deletions

View File

@@ -0,0 +1,98 @@
package collector
import (
"bee/audit/internal/schema"
"log/slog"
"strings"
)
// collectMemory runs dmidecode -t 17 and returns all memory slots.
func collectMemory() []schema.HardwareMemory {
out, err := runDmidecode("17")
if err != nil {
slog.Warn("memory: dmidecode type 17 failed", "err", err)
return nil
}
dimms := parseMemory(out)
slog.Info("memory: collected", "count", len(dimms))
return dimms
}
func parseMemory(output string) []schema.HardwareMemory {
sections := splitDMISections(output, "Memory Device")
dimms := make([]schema.HardwareMemory, 0, len(sections))
for _, fields := range sections {
dimm := parseMemorySection(fields)
dimms = append(dimms, dimm)
}
return dimms
}
func parseMemorySection(fields map[string]string) schema.HardwareMemory {
dimm := schema.HardwareMemory{}
if v := cleanDMIValue(fields["Locator"]); v != "" {
dimm.Slot = &v
}
if v := cleanDMIValue(fields["Bank Locator"]); v != "" {
dimm.Location = &v
}
// presence: "No Module Installed" or size == 0
present := true
rawSize := fields["Size"]
if strings.Contains(strings.ToLower(rawSize), "no module") || rawSize == "0" || rawSize == "" {
present = false
}
dimm.Present = &present
if !present {
status := "EMPTY"
dimm.Status = &status
return dimm
}
status := "OK"
dimm.Status = &status
if mb := parseMemorySizeMB(rawSize); mb > 0 {
dimm.SizeMB = &mb
}
if v := cleanDMIValue(fields["Type"]); v != "" && v != "Unknown" {
dimm.Type = &v
}
if mhz := parseInt(strings.TrimSuffix(fields["Speed"], " MT/s")); mhz > 0 {
dimm.MaxSpeedMHz = &mhz
}
if mhz := parseInt(strings.TrimSuffix(fields["Configured Memory Speed"], " MT/s")); mhz > 0 {
dimm.CurrentSpeedMHz = &mhz
}
if v := cleanDMIValue(fields["Manufacturer"]); v != "" {
dimm.Manufacturer = &v
}
if v := cleanDMIValue(fields["Serial Number"]); v != "" {
dimm.SerialNumber = &v
}
if v := cleanDMIValue(fields["Part Number"]); v != "" {
p := strings.TrimSpace(v)
dimm.PartNumber = &p
}
return dimm
}
// parseMemorySizeMB parses DMI size strings: "8 GB", "2048 MB", "No Module Installed".
func parseMemorySizeMB(s string) int {
s = strings.TrimSpace(s)
if strings.Contains(strings.ToLower(s), "no module") {
return 0
}
if strings.HasSuffix(s, " GB") {
n := parseInt(strings.TrimSuffix(s, " GB"))
return n * 1024
}
if strings.HasSuffix(s, " MB") {
return parseInt(strings.TrimSuffix(s, " MB"))
}
return parseInt(s)
}