Improve Redfish recovery flow and raw export timing diagnostics
This commit is contained in:
148
internal/parser/vendors/inspur/storage_serial_fallback.go
vendored
Normal file
148
internal/parser/vendors/inspur/storage_serial_fallback.go
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
package inspur
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
"git.mchus.pro/mchus/logpile/internal/parser"
|
||||
)
|
||||
|
||||
var bpHDDSerialTokenRegex = regexp.MustCompile(`[A-Za-z0-9]{8,32}`)
|
||||
|
||||
func enrichStorageFromSerialFallbackFiles(files []parser.ExtractedFile, hw *models.HardwareConfig) {
|
||||
if hw == nil {
|
||||
return
|
||||
}
|
||||
f := parser.FindFileByName(files, "BpHDDSerialNumber.info")
|
||||
if f == nil {
|
||||
return
|
||||
}
|
||||
serials := extractBPHDDSerials(f.Content)
|
||||
if len(serials) == 0 {
|
||||
return
|
||||
}
|
||||
applyStorageSerialFallback(hw, serials)
|
||||
}
|
||||
|
||||
func extractBPHDDSerials(content []byte) []string {
|
||||
if len(content) == 0 {
|
||||
return nil
|
||||
}
|
||||
matches := bpHDDSerialTokenRegex.FindAllString(string(content), -1)
|
||||
if len(matches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]string, 0, len(matches))
|
||||
seen := make(map[string]struct{}, len(matches))
|
||||
for _, m := range matches {
|
||||
v := normalizeRedisValue(m)
|
||||
if !looksLikeStorageSerial(v) {
|
||||
continue
|
||||
}
|
||||
key := strings.ToLower(v)
|
||||
if _, ok := seen[key]; ok {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func looksLikeStorageSerial(v string) bool {
|
||||
if len(v) < 8 {
|
||||
return false
|
||||
}
|
||||
hasLetter := false
|
||||
hasDigit := false
|
||||
for _, r := range v {
|
||||
switch {
|
||||
case r >= 'A' && r <= 'Z':
|
||||
hasLetter = true
|
||||
case r >= 'a' && r <= 'z':
|
||||
hasLetter = true
|
||||
case r >= '0' && r <= '9':
|
||||
hasDigit = true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return hasLetter && hasDigit
|
||||
}
|
||||
|
||||
func applyStorageSerialFallback(hw *models.HardwareConfig, serials []string) {
|
||||
if hw == nil || len(hw.Storage) == 0 || len(serials) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
existing := make(map[string]struct{}, len(hw.Storage))
|
||||
for _, dev := range hw.Storage {
|
||||
if sn := normalizeRedisValue(dev.SerialNumber); sn != "" {
|
||||
existing[strings.ToLower(sn)] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
filtered := make([]string, 0, len(serials))
|
||||
for _, sn := range serials {
|
||||
key := strings.ToLower(sn)
|
||||
if _, ok := existing[key]; ok {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, sn)
|
||||
}
|
||||
if len(filtered) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
type target struct {
|
||||
index int
|
||||
rank int
|
||||
slot string
|
||||
}
|
||||
targets := make([]target, 0, len(hw.Storage))
|
||||
for i := range hw.Storage {
|
||||
dev := hw.Storage[i]
|
||||
if normalizeRedisValue(dev.SerialNumber) != "" {
|
||||
continue
|
||||
}
|
||||
if !dev.Present && strings.TrimSpace(dev.Slot) == "" {
|
||||
continue
|
||||
}
|
||||
rank := 0
|
||||
if !dev.Present {
|
||||
rank += 10
|
||||
}
|
||||
if strings.EqualFold(strings.TrimSpace(dev.Type), "NVMe") {
|
||||
rank += 5
|
||||
}
|
||||
if strings.TrimSpace(dev.Slot) == "" {
|
||||
rank += 4
|
||||
}
|
||||
targets = append(targets, target{
|
||||
index: i,
|
||||
rank: rank,
|
||||
slot: strings.ToLower(strings.TrimSpace(dev.Slot)),
|
||||
})
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sort.Slice(targets, func(i, j int) bool {
|
||||
if targets[i].rank != targets[j].rank {
|
||||
return targets[i].rank < targets[j].rank
|
||||
}
|
||||
return targets[i].slot < targets[j].slot
|
||||
})
|
||||
|
||||
for i := 0; i < len(targets) && i < len(filtered); i++ {
|
||||
dev := &hw.Storage[targets[i].index]
|
||||
dev.SerialNumber = filtered[i]
|
||||
if !dev.Present {
|
||||
dev.Present = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user