Fix NIC port count handling and apply pending exporter updates
This commit is contained in:
@@ -193,6 +193,7 @@ func buildDevicesFromLegacy(hw *models.HardwareConfig) []models.HardwareDevice {
|
||||
appendDevice(models.HardwareDevice{
|
||||
Kind: models.DeviceKindGPU,
|
||||
Slot: gpu.Slot,
|
||||
Location: gpu.Location,
|
||||
BDF: gpu.BDF,
|
||||
DeviceClass: "DisplayController",
|
||||
VendorID: gpu.VendorID,
|
||||
@@ -206,12 +207,27 @@ func buildDevicesFromLegacy(hw *models.HardwareConfig) []models.HardwareDevice {
|
||||
LinkSpeed: gpu.CurrentLinkSpeed,
|
||||
MaxLinkWidth: gpu.MaxLinkWidth,
|
||||
MaxLinkSpeed: gpu.MaxLinkSpeed,
|
||||
TemperatureC: gpu.Temperature,
|
||||
Status: gpu.Status,
|
||||
StatusCheckedAt: gpu.StatusCheckedAt,
|
||||
StatusChangedAt: gpu.StatusChangedAt,
|
||||
StatusAtCollect: gpu.StatusAtCollect,
|
||||
StatusHistory: gpu.StatusHistory,
|
||||
ErrorDescription: gpu.ErrorDescription,
|
||||
Details: map[string]any{
|
||||
"uuid": gpu.UUID,
|
||||
"video_bios": gpu.VideoBIOS,
|
||||
"irq": gpu.IRQ,
|
||||
"bus_type": gpu.BusType,
|
||||
"dma_size": gpu.DMASize,
|
||||
"dma_mask": gpu.DMAMask,
|
||||
"device_minor": gpu.DeviceMinor,
|
||||
"temperature": gpu.Temperature,
|
||||
"mem_temperature": gpu.MemTemperature,
|
||||
"power": gpu.Power,
|
||||
"max_power": gpu.MaxPower,
|
||||
"clock_speed": gpu.ClockSpeed,
|
||||
},
|
||||
})
|
||||
}
|
||||
for _, nic := range hw.NetworkAdapters {
|
||||
@@ -292,8 +308,14 @@ func dedupeCanonicalDevices(items []models.HardwareDevice) []models.HardwareDevi
|
||||
continue
|
||||
}
|
||||
if curr.score > prev.score {
|
||||
curr.item = mergeCanonicalDevice(curr.item, prev.item)
|
||||
curr.score = canonicalScore(curr.item)
|
||||
byKey[key] = curr
|
||||
continue
|
||||
}
|
||||
prev.item = mergeCanonicalDevice(prev.item, curr.item)
|
||||
prev.score = canonicalScore(prev.item)
|
||||
byKey[key] = prev
|
||||
}
|
||||
out := make([]models.HardwareDevice, 0, len(order)+len(noKey))
|
||||
for _, key := range order {
|
||||
@@ -306,6 +328,95 @@ func dedupeCanonicalDevices(items []models.HardwareDevice) []models.HardwareDevi
|
||||
return out
|
||||
}
|
||||
|
||||
func mergeCanonicalDevice(primary, secondary models.HardwareDevice) models.HardwareDevice {
|
||||
fillString := func(dst *string, src string) {
|
||||
if strings.TrimSpace(*dst) == "" && strings.TrimSpace(src) != "" {
|
||||
*dst = src
|
||||
}
|
||||
}
|
||||
fillInt := func(dst *int, src int) {
|
||||
if *dst == 0 && src != 0 {
|
||||
*dst = src
|
||||
}
|
||||
}
|
||||
fillFloat := func(dst *float64, src float64) {
|
||||
if *dst == 0 && src != 0 {
|
||||
*dst = src
|
||||
}
|
||||
}
|
||||
|
||||
fillString(&primary.Kind, secondary.Kind)
|
||||
fillString(&primary.Source, secondary.Source)
|
||||
fillString(&primary.Slot, secondary.Slot)
|
||||
fillString(&primary.Location, secondary.Location)
|
||||
fillString(&primary.BDF, secondary.BDF)
|
||||
fillString(&primary.DeviceClass, secondary.DeviceClass)
|
||||
fillInt(&primary.VendorID, secondary.VendorID)
|
||||
fillInt(&primary.DeviceID, secondary.DeviceID)
|
||||
fillString(&primary.Model, secondary.Model)
|
||||
fillString(&primary.PartNumber, secondary.PartNumber)
|
||||
fillString(&primary.Manufacturer, secondary.Manufacturer)
|
||||
fillString(&primary.SerialNumber, secondary.SerialNumber)
|
||||
fillString(&primary.Firmware, secondary.Firmware)
|
||||
fillString(&primary.Type, secondary.Type)
|
||||
fillString(&primary.Interface, secondary.Interface)
|
||||
if primary.Present == nil && secondary.Present != nil {
|
||||
primary.Present = secondary.Present
|
||||
}
|
||||
fillInt(&primary.SizeMB, secondary.SizeMB)
|
||||
fillInt(&primary.SizeGB, secondary.SizeGB)
|
||||
fillInt(&primary.Cores, secondary.Cores)
|
||||
fillInt(&primary.Threads, secondary.Threads)
|
||||
fillInt(&primary.FrequencyMHz, secondary.FrequencyMHz)
|
||||
fillInt(&primary.MaxFreqMHz, secondary.MaxFreqMHz)
|
||||
fillInt(&primary.PortCount, secondary.PortCount)
|
||||
fillString(&primary.PortType, secondary.PortType)
|
||||
if len(primary.MACAddresses) == 0 && len(secondary.MACAddresses) > 0 {
|
||||
primary.MACAddresses = secondary.MACAddresses
|
||||
}
|
||||
fillInt(&primary.LinkWidth, secondary.LinkWidth)
|
||||
fillString(&primary.LinkSpeed, secondary.LinkSpeed)
|
||||
fillInt(&primary.MaxLinkWidth, secondary.MaxLinkWidth)
|
||||
fillString(&primary.MaxLinkSpeed, secondary.MaxLinkSpeed)
|
||||
fillInt(&primary.WattageW, secondary.WattageW)
|
||||
fillString(&primary.InputType, secondary.InputType)
|
||||
fillInt(&primary.InputPowerW, secondary.InputPowerW)
|
||||
fillInt(&primary.OutputPowerW, secondary.OutputPowerW)
|
||||
fillFloat(&primary.InputVoltage, secondary.InputVoltage)
|
||||
fillInt(&primary.TemperatureC, secondary.TemperatureC)
|
||||
fillString(&primary.Status, secondary.Status)
|
||||
if primary.StatusCheckedAt.IsZero() && !secondary.StatusCheckedAt.IsZero() {
|
||||
primary.StatusCheckedAt = secondary.StatusCheckedAt
|
||||
}
|
||||
if primary.StatusChangedAt.IsZero() && !secondary.StatusChangedAt.IsZero() {
|
||||
primary.StatusChangedAt = secondary.StatusChangedAt
|
||||
}
|
||||
if primary.StatusAtCollect == nil && secondary.StatusAtCollect != nil {
|
||||
primary.StatusAtCollect = secondary.StatusAtCollect
|
||||
}
|
||||
if len(primary.StatusHistory) == 0 && len(secondary.StatusHistory) > 0 {
|
||||
primary.StatusHistory = secondary.StatusHistory
|
||||
}
|
||||
fillString(&primary.ErrorDescription, secondary.ErrorDescription)
|
||||
primary.Details = mergeDetailMaps(primary.Details, secondary.Details)
|
||||
return primary
|
||||
}
|
||||
|
||||
func mergeDetailMaps(primary, secondary map[string]any) map[string]any {
|
||||
if len(secondary) == 0 {
|
||||
return primary
|
||||
}
|
||||
if primary == nil {
|
||||
primary = make(map[string]any, len(secondary))
|
||||
}
|
||||
for k, v := range secondary {
|
||||
if _, exists := primary[k]; !exists {
|
||||
primary[k] = v
|
||||
}
|
||||
}
|
||||
return primary
|
||||
}
|
||||
|
||||
func canonicalKey(item models.HardwareDevice) string {
|
||||
if sn := normalizedSerial(item.SerialNumber); sn != "" {
|
||||
return "sn:" + strings.ToLower(sn)
|
||||
@@ -483,6 +594,23 @@ func convertPCIeFromDevices(devices []models.HardwareDevice, collectedAt string)
|
||||
if model == "" {
|
||||
model = d.PartNumber
|
||||
}
|
||||
temperatureC := d.TemperatureC
|
||||
if temperatureC == 0 {
|
||||
temperatureC = firstNonZeroInt(
|
||||
intFromDetailMap(d.Details, "temperature_c"),
|
||||
intFromDetailMap(d.Details, "temperature"),
|
||||
)
|
||||
}
|
||||
powerW := firstNonZeroInt(
|
||||
intFromDetailMap(d.Details, "power_w"),
|
||||
intFromDetailMap(d.Details, "power"),
|
||||
)
|
||||
voltageV := firstNonZeroFloat(
|
||||
floatFromDetailMap(d.Details, "voltage_v"),
|
||||
floatFromDetailMap(d.Details, "voltage"),
|
||||
floatFromDetailMap(d.Details, "input_voltage"),
|
||||
d.InputVoltage,
|
||||
)
|
||||
status := normalizeStatus(d.Status, false)
|
||||
meta := buildStatusMeta(status, d.StatusCheckedAt, d.StatusChangedAt, d.StatusAtCollect, d.StatusHistory, d.ErrorDescription, collectedAt)
|
||||
result = append(result, ReanimatorPCIe{
|
||||
@@ -499,6 +627,9 @@ func convertPCIeFromDevices(devices []models.HardwareDevice, collectedAt string)
|
||||
MaxLinkSpeed: d.MaxLinkSpeed,
|
||||
SerialNumber: normalizedSerial(d.SerialNumber),
|
||||
Firmware: d.Firmware,
|
||||
TemperatureC: temperatureC,
|
||||
PowerW: powerW,
|
||||
VoltageV: voltageV,
|
||||
Status: status,
|
||||
StatusCheckedAt: meta.StatusCheckedAt,
|
||||
StatusChangedAt: meta.StatusChangedAt,
|
||||
@@ -536,6 +667,7 @@ func convertPSUsFromDevices(devices []models.HardwareDevice, collectedAt string)
|
||||
InputPowerW: d.InputPowerW,
|
||||
OutputPowerW: d.OutputPowerW,
|
||||
InputVoltage: d.InputVoltage,
|
||||
TemperatureC: d.TemperatureC,
|
||||
StatusCheckedAt: meta.StatusCheckedAt,
|
||||
StatusChangedAt: meta.StatusChangedAt,
|
||||
StatusAtCollect: meta.StatusAtCollection,
|
||||
@@ -804,6 +936,8 @@ func convertPCIeDevices(hw *models.HardwareConfig, collectedAt string) []Reanima
|
||||
MaxLinkSpeed: gpu.MaxLinkSpeed,
|
||||
SerialNumber: serialNumber,
|
||||
Firmware: gpu.Firmware,
|
||||
TemperatureC: gpu.Temperature,
|
||||
PowerW: gpu.Power,
|
||||
Status: status,
|
||||
StatusCheckedAt: meta.StatusCheckedAt,
|
||||
StatusChangedAt: meta.StatusChangedAt,
|
||||
@@ -954,6 +1088,7 @@ func convertPowerSupplies(psus []models.PSU, collectedAt string) []ReanimatorPSU
|
||||
InputPowerW: psu.InputPowerW,
|
||||
OutputPowerW: psu.OutputPowerW,
|
||||
InputVoltage: psu.InputVoltage,
|
||||
TemperatureC: psu.TemperatureC,
|
||||
StatusCheckedAt: meta.StatusCheckedAt,
|
||||
StatusChangedAt: meta.StatusChangedAt,
|
||||
StatusAtCollect: meta.StatusAtCollection,
|
||||
@@ -1286,13 +1421,73 @@ func intFromDetailMap(details map[string]any, key string) int {
|
||||
switch n := v.(type) {
|
||||
case int:
|
||||
return n
|
||||
case int64:
|
||||
return int(n)
|
||||
case int32:
|
||||
return int(n)
|
||||
case float64:
|
||||
return int(n)
|
||||
case float32:
|
||||
return int(n)
|
||||
case string:
|
||||
i, err := strconv.Atoi(strings.TrimSpace(n))
|
||||
if err == nil {
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func floatFromDetailMap(details map[string]any, key string) float64 {
|
||||
if details == nil {
|
||||
return 0
|
||||
}
|
||||
v, ok := details[key]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
switch n := v.(type) {
|
||||
case float64:
|
||||
return n
|
||||
case float32:
|
||||
return float64(n)
|
||||
case int:
|
||||
return float64(n)
|
||||
case int64:
|
||||
return float64(n)
|
||||
case int32:
|
||||
return float64(n)
|
||||
case string:
|
||||
f, err := strconv.ParseFloat(strings.TrimSpace(n), 64)
|
||||
if err == nil {
|
||||
return f
|
||||
}
|
||||
return 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func firstNonZeroInt(values ...int) int {
|
||||
for _, v := range values {
|
||||
if v != 0 {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func firstNonZeroFloat(values ...float64) float64 {
|
||||
for _, v := range values {
|
||||
if v != 0 {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// inferStorageStatus determines storage device status
|
||||
func inferStorageStatus(stor models.Storage) string {
|
||||
if !stor.Present {
|
||||
|
||||
Reference in New Issue
Block a user