Add GPU serial number extraction for NVIDIA diagnostics
Parse inventory/output.log to extract GPU serial numbers from lspci output, expose them via serials API, and add GPU category to web UI. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
87
internal/parser/vendors/nvidia/inventory_log_test.go
vendored
Normal file
87
internal/parser/vendors/nvidia/inventory_log_test.go
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package nvidia
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/parser"
|
||||
)
|
||||
|
||||
func TestParseInventoryLog(t *testing.T) {
|
||||
// Test with the real archive
|
||||
archivePath := filepath.Join("../../../../example", "A514359X5A09844_logs-20260115-151707.tar")
|
||||
|
||||
// Check if file exists
|
||||
if _, err := os.Stat(archivePath); os.IsNotExist(err) {
|
||||
t.Skip("Test archive not found, skipping test")
|
||||
}
|
||||
|
||||
// Extract files from archive
|
||||
files, err := parser.ExtractArchive(archivePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract archive: %v", err)
|
||||
}
|
||||
|
||||
// Find inventory/output.log
|
||||
var inventoryLog *parser.ExtractedFile
|
||||
for _, f := range files {
|
||||
if strings.Contains(f.Path, "inventory/output.log") {
|
||||
inventoryLog = &f
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if inventoryLog == nil {
|
||||
t.Fatal("inventory/output.log not found")
|
||||
}
|
||||
|
||||
content := string(inventoryLog.Content)
|
||||
|
||||
// Test devname regex
|
||||
t.Log("Testing devname extraction:")
|
||||
lines := strings.Split(content, "\n")
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, "devname=") && strings.Contains(line, "fieldiag") {
|
||||
t.Logf("Line %d: Found fieldiag command", i)
|
||||
matches := devnameRegex.FindAllStringSubmatch(line, -1)
|
||||
t.Logf(" Found %d devname matches", len(matches))
|
||||
for _, match := range matches {
|
||||
if len(match) == 3 {
|
||||
t.Logf(" PCI: %s -> Slot: %s", match[1], match[2])
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Test lspci regex
|
||||
t.Log("\nTesting lspci BDF extraction:")
|
||||
serialCount := 0
|
||||
bdfCount := 0
|
||||
for i, line := range lines {
|
||||
// Check for lines that look like lspci headers
|
||||
if strings.Contains(line, "3D controller") && strings.Contains(line, "NVIDIA") {
|
||||
t.Logf("Line %d: Potential lspci line: %q (starts with: %q)", i, line[:min(80, len(line))], line[:min(10, len(line))])
|
||||
if match := pciBDFRegex.FindStringSubmatch(line); len(match) > 1 {
|
||||
bdfCount++
|
||||
t.Logf(" -> Matched BDF: %s", match[1])
|
||||
} else {
|
||||
t.Logf(" -> NO MATCH")
|
||||
}
|
||||
}
|
||||
if match := gpuSerialRegex.FindStringSubmatch(line); len(match) > 1 {
|
||||
serialCount++
|
||||
}
|
||||
}
|
||||
t.Logf("\nTotal BDFs found: %d", bdfCount)
|
||||
t.Logf("Total serials found: %d", serialCount)
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user