fix: complete hardware collection diagnostics

This commit is contained in:
2026-08-25 17:04:33 +03:00
parent 33ace33de5
commit ccc781856e
19 changed files with 311 additions and 81 deletions
@@ -43,6 +43,9 @@ func (s *System) RunNvidiaConfigCheckPack(ctx context.Context, baseDir string, l
if settings, err := s.ListNvidiaGPUSettings(); err != nil {
status.Notes = append(status.Notes, "nvidia-smi GPU settings unavailable (no driver, or no GPU present): "+err.Error())
} else {
if len(settings) == 0 {
status.NoGPUs = true
}
for _, g := range settings {
f := NvidiaGPUConfigFinding{
Index: g.Index, Name: g.Name,
@@ -127,6 +130,7 @@ type NvidiaConfigCheckStatus struct {
GPUs []NvidiaGPUConfigFinding `json:"gpus,omitempty"`
NVLinkPairs []NvidiaNVLinkPairFinding `json:"nvlink_pairs,omitempty"`
NoGPUs bool `json:"no_gpus"`
// Confidential Computing readiness — informational only, does not gate
// overall_status: an unconfigured/NOT_READY CC state is a
@@ -466,7 +470,10 @@ func renderNvidiaConfigCheckSummary(status NvidiaConfigCheckStatus) string {
fmt.Fprintf(&b, "cc_state=%s\n", status.CCState)
fmt.Fprintf(&b, "cpu_cc_capability=%s\n", status.CPUCCCapability)
fmt.Fprintf(&b, "gpu_cc_capability=%s\n", status.GPUCCCapability)
if len(status.Warnings) == 0 {
if status.NoGPUs {
fmt.Fprintln(&b, "overall_status=UNSUPPORTED")
fmt.Fprintln(&b, "reason=no_nvidia_gpus_detected")
} else if len(status.Warnings) == 0 {
fmt.Fprintln(&b, "overall_status=OK")
} else {
fmt.Fprintln(&b, "overall_status=FAILED")
@@ -165,6 +165,10 @@ func TestRenderNvidiaConfigCheckSummaryOverallStatus(t *testing.T) {
if got := renderNvidiaConfigCheckSummary(withWarning); !strings.Contains(got, "overall_status=FAILED") {
t.Fatalf("status with warnings missing overall_status=FAILED:\n%s", got)
}
noGPU := NvidiaConfigCheckStatus{NoGPUs: true}
if got := renderNvidiaConfigCheckSummary(noGPU); !strings.Contains(got, "overall_status=UNSUPPORTED") {
t.Fatalf("no-GPU summary must be unsupported:\n%s", got)
}
}
// TestRenderNvidiaConfigCheckSummaryIncludesWarningsField guards that a
+11
View File
@@ -920,6 +920,12 @@ func (s *System) RunStorageAcceptancePack(ctx context.Context, baseDir string, e
runSyncBracketHook(job, "after", logFunc)
}
status, rc := classifySATResult(job.name, out, err)
// A zero smartctl exit status only proves the command ran. If the
// drive did not return its overall-health verdict, it must not turn
// the storage SAT green.
if job.name == "smartctl-health" && status == "OK" && !hasSMARTOverallHealth(out) {
status = "UNSUPPORTED"
}
stats.Add(status)
key := filepath.Base(devPath) + "_" + strings.ReplaceAll(job.name, "-", "_")
fmt.Fprintf(&summary, "%s_rc=%d\n", key, rc)
@@ -1560,6 +1566,11 @@ func classifySATResult(name string, out []byte, err error) (string, int) {
return "FAILED", rc
}
func hasSMARTOverallHealth(out []byte) bool {
m := smartHealthRE.FindStringSubmatch(string(out))
return len(m) > 1 && strings.TrimSpace(m[1]) != ""
}
func runSATCommand(verboseLog, name string, cmd []string, logFunc func(string)) ([]byte, error) {
start := time.Now().UTC()
resolvedCmd, err := resolveSATCommand(cmd)
+10 -2
View File
@@ -124,6 +124,7 @@ func writeNVMeReport(b *strings.Builder, outputs map[string][]byte) {
writtenBytes: writtenBytes,
readBytes: readBytes,
capacityBytes: capacityBytes,
healthKnown: true,
}
writeResourceSection(b, ri)
@@ -232,6 +233,7 @@ func writeSATAReport(b *strings.Builder, outputs map[string][]byte) {
capacityBytes: capacityBytes,
readPercent: 100 - readValue,
hasReadPercent: hasReadValue,
healthKnown: !strings.EqualFold(health, "unknown"),
}
writeResourceSection(b, ri)
@@ -341,6 +343,7 @@ const (
type resourceInfo struct {
powerOnHours uint64
healthKnown bool
powerCycles uint64
writtenBytes uint64
readBytes uint64
@@ -393,7 +396,10 @@ func writeConclusionSection(b *strings.Builder, r resourceInfo) {
writeSectionHeader(b, "Conclusion")
var reasons, notes []string
isNew := true
isNew := r.healthKnown
if !r.healthKnown {
notes = append(notes, "SMART overall health unavailable — disk cannot be accepted as NEW")
}
if r.capacityBytes > 0 {
writtenFrac := float64(r.writtenBytes) / float64(r.capacityBytes)
@@ -424,7 +430,9 @@ func writeConclusionSection(b *strings.Builder, r resourceInfo) {
reasons = append(reasons, fmt.Sprintf("power cycles %s", formatUint(r.powerCycles)))
}
if isNew {
if !r.healthKnown {
writeField(b, "Disk Condition", "UNVERIFIED")
} else if isNew {
writeField(b, "Disk Condition", "NEW")
} else {
writeField(b, "Disk Condition", "USED")
@@ -141,6 +141,15 @@ func TestGenerateDiskReportSATA(t *testing.T) {
assertContains(t, report, "Power_On_Hours")
}
func TestHasSMARTOverallHealth(t *testing.T) {
if !hasSMARTOverallHealth([]byte("SMART overall-health self-assessment test result: PASSED\n")) {
t.Fatal("expected SMART health verdict to be recognized")
}
if hasSMARTOverallHealth([]byte("SMART support is: Available\n")) {
t.Fatal("availability alone must not be accepted as a health verdict")
}
}
func assertContains(t *testing.T, text string, needles ...string) {
t.Helper()
for _, needle := range needles {