feat(models): resolve CPU serial from source PPIN as common fallback
Centralize CPU identity in models.ResolveCPUSerialNumber: an explicit source serial wins, otherwise a valid source PPIN is used, placeholders rejected. Dell, H3C and Redfish apply it while parsing; canonical-device and Reanimator conversion apply it again at the output boundary. No identity is synthesized from socket/model/board serial. See ADL-058. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
9d701885da
commit
07c270cda2
+4
-2
@@ -19,7 +19,7 @@ import (
|
||||
"git.mchus.pro/mchus/logpile/internal/parser/vendors/pciids"
|
||||
)
|
||||
|
||||
const parserVersion = "3.0"
|
||||
const parserVersion = "3.1"
|
||||
|
||||
func init() {
|
||||
parser.Register(&Parser{})
|
||||
@@ -323,6 +323,7 @@ func parseCPUView(props map[string]string, result *models.AnalysisResult) {
|
||||
if model == "" {
|
||||
return
|
||||
}
|
||||
ppin := strings.TrimSpace(props["ppin"])
|
||||
cpu := models.CPU{
|
||||
Socket: parseSocketFromFQDD(firstNonEmpty(props["fqdd"], props["instanceid"])),
|
||||
Model: model,
|
||||
@@ -331,7 +332,8 @@ func parseCPUView(props map[string]string, result *models.AnalysisResult) {
|
||||
Threads: parseIntLoose(props["numberofenabledthreads"]),
|
||||
FrequencyMHz: parseIntLoose(props["currentclockspeed"]),
|
||||
MaxFreqMHz: parseIntLoose(props["maxclockspeed"]),
|
||||
PPIN: strings.TrimSpace(props["ppin"]),
|
||||
PPIN: ppin,
|
||||
SerialNumber: models.ResolveCPUSerialNumber(props["serialnumber"], ppin),
|
||||
Status: normalizeStatus(props["primarystatus"]),
|
||||
}
|
||||
result.Hardware.CPUs = append(result.Hardware.CPUs, cpu)
|
||||
|
||||
+3
@@ -152,6 +152,9 @@ func TestParseNestedTSRZip(t *testing.T) {
|
||||
if got := result.Hardware.CPUs[0].Model; got != "Intel(R) Xeon(R) Gold 6330" {
|
||||
t.Fatalf("unexpected cpu model: %q", got)
|
||||
}
|
||||
if got := result.Hardware.CPUs[0].SerialNumber; got != "ABCD" {
|
||||
t.Fatalf("expected CPU serial fallback from PPIN, got %q", got)
|
||||
}
|
||||
|
||||
if len(result.Hardware.NetworkAdapters) != 1 {
|
||||
t.Fatalf("expected 1 network adapter, got %d", len(result.Hardware.NetworkAdapters))
|
||||
|
||||
+9
-6
@@ -20,8 +20,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
parserVersionG5 = "2.1"
|
||||
parserVersionG6 = "2.1"
|
||||
parserVersionG5 = "2.2"
|
||||
parserVersionG6 = "2.2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -506,6 +506,8 @@ func parseHardwareInfoNetworkAdapters(content []byte) []models.NetworkAdapter {
|
||||
func parseCPUFromHardwareInfoSection(sectionName string, section map[string]string) models.CPU {
|
||||
socket := parseSectionIndex(sectionName, `(?i)processor\s+(\d+)`)
|
||||
statusRaw := getSectionValue(section, "Status")
|
||||
ppin := getSectionValue(section, "CPU PPIN", "PPIN")
|
||||
serial := getSectionValue(section, "Processor ID", "Serial Number")
|
||||
|
||||
return models.CPU{
|
||||
Socket: socket,
|
||||
@@ -516,8 +518,8 @@ func parseCPUFromHardwareInfoSection(sectionName string, section map[string]stri
|
||||
L1CacheKB: parseMaybeIntLoose(getSectionValue(section, "L1 Cache")),
|
||||
L2CacheKB: parseMaybeIntLoose(getSectionValue(section, "L2 Cache")),
|
||||
L3CacheKB: parseMaybeIntLoose(getSectionValue(section, "L3 Cache")),
|
||||
PPIN: getSectionValue(section, "CPU PPIN", "PPIN"),
|
||||
SerialNumber: getSectionValue(section, "Processor ID", "Serial Number"),
|
||||
PPIN: ppin,
|
||||
SerialNumber: models.ResolveCPUSerialNumber(serial, ppin),
|
||||
Status: normalizeComponentStatus(statusRaw),
|
||||
}
|
||||
}
|
||||
@@ -1503,6 +1505,7 @@ func parseCPUXML(content []byte, result *models.AnalysisResult) {
|
||||
}
|
||||
|
||||
socket := parseSocketID(node.XMLName.Local)
|
||||
ppin := strings.TrimSpace(fields["PPIN"])
|
||||
cpu := models.CPU{
|
||||
Socket: socket,
|
||||
Model: model,
|
||||
@@ -1511,8 +1514,8 @@ func parseCPUXML(content []byte, result *models.AnalysisResult) {
|
||||
Threads: parseMaybeInt(fields["TotalThreads"]),
|
||||
FrequencyMHz: parseMaybeInt(fields["ProcessorSpeed"]),
|
||||
MaxFreqMHz: parseMaybeInt(fields["ProcessorMaxSpeed"]),
|
||||
SerialNumber: strings.TrimSpace(fields["SerialNumber"]),
|
||||
PPIN: strings.TrimSpace(fields["PPIN"]),
|
||||
SerialNumber: models.ResolveCPUSerialNumber(fields["SerialNumber"], ppin),
|
||||
PPIN: ppin,
|
||||
Status: normalizePresenceStatus(fields["Status"]),
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -831,6 +831,9 @@ Pre-Init,Info,0x0,Management Subsystem Health,Health,Assertion event,Pre-Init,"M
|
||||
if result.Hardware.CPUs[0].FrequencyMHz != 2800 {
|
||||
t.Fatalf("expected CPU frequency 2800MHz, got %d", result.Hardware.CPUs[0].FrequencyMHz)
|
||||
}
|
||||
if got := result.Hardware.CPUs[0].SerialNumber; got != "49-A9-50-C0-15-9F-2D-DC" {
|
||||
t.Fatalf("expected CPU serial fallback from PPIN, got %q", got)
|
||||
}
|
||||
|
||||
if len(result.Hardware.Memory) != 2 {
|
||||
t.Fatalf("expected 2 DIMMs from hardware_info.ini, got %d", len(result.Hardware.Memory))
|
||||
|
||||
Reference in New Issue
Block a user