fix(xfusion): parse disk_info Capacity in TB/binary units for size_gb

parseDiskInfo read capacity with Sscanf(cap, "%f GB"), so every iBMC
"Capacity : 6.986 TB" NVMe line failed to match and size_gb stayed 0
while the BEE-SP live-CD export of the same drive had the real size.
The iBMC number is also binary (GiB/TiB) despite the GB/TB label.

parseDiskCapacityGB parses number + unit (TB/GB/MB), treats it as
binary, and emits decimal GB, matching the drive's marketed capacity
and the live-CD inventory. Found by diffing a G5500 V7 BMC dump against
its live-CD bundle. See ADL-063.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LffAvostt3uMkiUbVUiyM
This commit is contained in:
Mikhail Chusavitin
2026-09-01 11:58:46 +03:00
co-authored by Claude Sonnet 5
parent 8e7f22077d
commit ab8636da04
2 changed files with 82 additions and 5 deletions
+30 -5
View File
@@ -2,6 +2,7 @@ package xfusion
import (
"fmt"
"math"
"strconv"
"strings"
"time"
@@ -1086,11 +1087,7 @@ func parseDiskInfo(content []byte) *models.Storage {
return nil
}
sizeGB := 0
var capFloat float64
if _, err := fmt.Sscanf(fields["Capacity"], "%f GB", &capFloat); err == nil {
sizeGB = int(capFloat)
}
sizeGB := parseDiskCapacityGB(fields["Capacity"])
var wearPct *int
if wearStr := fields["Remnant Media Wearout"]; wearStr != "" {
@@ -1120,6 +1117,34 @@ func parseDiskInfo(content []byte) *models.Storage {
}
}
// parseDiskCapacityGB converts an iBMC disk_info "Capacity" value to decimal GB.
// iBMC labels the number "GB"/"TB" but the value is binary (GiB/TiB): a
// "6.986 TB" NVMe drive is the vendor's 7.68 TB / 7680 GB part, which is also
// what the BEE-SP live-CD inventory reports. Normalize to decimal GB so a
// BMC-dump and a live-CD export of the same drive carry the same size_gb.
func parseDiskCapacityGB(s string) int {
f := strings.Fields(strings.TrimSpace(s))
if len(f) < 2 {
return 0
}
val, err := strconv.ParseFloat(f[0], 64)
if err != nil || val <= 0 {
return 0
}
var binaryBytes float64
switch strings.ToUpper(f[1]) {
case "TB", "TIB":
binaryBytes = val * (1 << 40)
case "GB", "GIB":
binaryBytes = val * (1 << 30)
case "MB", "MIB":
binaryBytes = val * (1 << 20)
default:
return 0
}
return int(math.Round(binaryBytes / 1e9))
}
// parseKeyValueBlock parses "Key (spaces) : Value" lines from a text block.
func parseKeyValueBlock(content []byte) map[string]string {
result := make(map[string]string)