package webui import ( "encoding/json" "fmt" "html" "sort" "strings" "bee/audit/internal/platform" "bee/audit/internal/schema" ) // PCI vendor IDs used for GPU classification (source: pci-ids.ucw.cz). const ( pciVendorNvidia = 0x10de pciVendorAMD = 0x1002 pciVendorAspeed = 0x1a03 ) type validateInventory struct { CPU string Memory string Storage string TPM string NVIDIA string AMD string NvidiaGPUCount int AMDGPUCount int } func validateFmtDur(secs int) string { if secs < 120 { return fmt.Sprintf("~%d s", secs) } mins := (secs + 29) / 60 return fmt.Sprintf("~%d min", mins) } func validateTotalValidateSec(n int) int { if n < 0 { n = 0 } total := platform.SATEstimatedCPUValidateSec + platform.SATEstimatedMemoryValidateSec + platform.SATEstimatedTPMValidateSec + platform.SATEstimatedNvidiaInterconnectSec + platform.SATEstimatedNvidiaBandwidthSec if n > 0 { total += platform.SATEstimatedNvidiaGPUValidateSec } return total } func validateTotalStressSec(n int) int { if n < 0 { n = 0 } total := platform.SATEstimatedCPUStressSec + platform.SATEstimatedMemoryStressSec + platform.SATEstimatedNvidiaPulseTestSec + platform.SATEstimatedNvidiaInterconnectSec + platform.SATEstimatedNvidiaBandwidthSec if n > 0 { total += platform.SATEstimatedNvidiaGPUStressSec + platform.SATEstimatedNvidiaTargetedStressSec + platform.SATEstimatedNvidiaTargetedPowerSec } return total } func renderValidate(opts HandlerOptions) string { return renderValidateMode(opts, false) } func renderValidateStress(opts HandlerOptions) string { return renderValidateMode(opts, true) } func renderValidateMode(opts HandlerOptions, stressDefault bool) string { inv := loadValidateInventory(opts) n := inv.NvidiaGPUCount validateTotalStr := validateFmtDur(validateTotalValidateSec(n)) stressTotalStr := validateFmtDur(validateTotalStressSec(n)) gpuNote := "" if n > 0 { gpuNote = fmt.Sprintf(" (%d GPU)", n) } estStr := validateTotalStr if stressDefault { estStr = stressTotalStr } alert := `
dcgmi diag targeted_stress`,
validateFmtDur(platform.SATEstimatedNvidiaTargetedStressSec)+` (all GPUs simultaneously).`,
)) +
renderSATCard("nvidia-targeted-power", "NVIDIA Targeted Power", "runNvidiaValidateSet('nvidia-targeted-power')", "", renderValidateCardBody(
inv.NVIDIA,
`Checks that the GPU can sustain its declared power delivery envelope. Pass/fail determined by DCGM.`,
`dcgmi diag targeted_power`,
validateFmtDur(platform.SATEstimatedNvidiaTargetedPowerSec)+` (all GPUs simultaneously).`,
)) +
renderSATCard("nvidia-pulse", "NVIDIA PSU Pulse Test", "runNvidiaFabricValidate('nvidia-pulse')", "", renderValidateCardBody(
inv.NVIDIA,
`Tests power supply transient response by pulsing all GPUs simultaneously between idle and full load. Synchronous pulses across all GPUs create worst-case PSU load spikes — running per-GPU would miss PSU-level failures.`,
`dcgmi diag pulse_test`,
validateFmtDur(platform.SATEstimatedNvidiaPulseTestSec)+` (all GPUs simultaneously; measured on 8-GPU system).`,
)) +
renderSATCard("fan", "Fan Ceiling Check", "runSAT('fan')", "", renderValidateCardBody(
"All system fans reported over IPMI / lm-sensors.",
`Drives CPU (+memory) and, when a GPU is present, the hottest sustained GPU load (dcgmproftester targeted-power — the Power/Thermal Fit engine) at the same time, and watches every fan until none has climbed for ~1 min. The peak RPM reached is recorded as each fan's ceiling and is what the Topology view sizes the fan tiles and duty-cycle fill against. Success once every fan plateaus (or the time cap is hit). A fan reading 0 RPM or an IPMI status of cr/nr under full load fails. IPMI polling backs off automatically if the BMC gets slow under load. If the host cannot be loaded at all, or exposes no fan sensors, the task is cancelled as "not applicable" rather than failed — the platform does not support forcing fans, so this is the closest safe equivalent.`,
`stressapptest / stress-ng + dcgmproftester -t 1004 / rvs gst; ipmitool sdr type Fan`,
`~3–10 min depending on how fast the fan curve settles (hard cap 15 min).`,
))
}
satStressModeJS := "function satStressMode() { return false; }"
if stressDefault {
satStressModeJS = "function satStressMode() { return true; }"
}
return alert + `
Tasks continue in the background — view progress in Tasks.
lscpu, sensors, stress-ng`,
validateFmtDur(platform.SATEstimatedCPUValidateSec)+` in Validate (stress-ng 60 s). `+validateFmtDur(platform.SATEstimatedCPUStressSec)+` in Stress (stress-ng 30 min).`,
)) +
renderSATCard("memory", "Memory", "runSAT('memory')", "", renderValidateCardBody(
inv.Memory,
`Runs a RAM validation pass and records memory state around the test.`,
`free, memtester`,
validateFmtDur(platform.SATEstimatedMemoryValidateSec)+` in Validate (256 MB × 1 pass). `+validateFmtDur(platform.SATEstimatedMemoryStressSec)+` in Stress (512 MB × 1 pass).`,
)) +
renderSATCard("storage", "Storage", "runSAT('storage')", "", renderValidateCardBody(
inv.Storage,
`Collects SMART data and runs a short self-test on each storage device.`,
`lsblk; NVMe: nvme id-ctrl, nvme smart-log, nvme device-self-test -s 1; SATA/SAS: smartctl -H -A, smartctl -t short`,
`~2 min per device (NVMe short self-test; SATA/SAS short self-test — duration device-dependent).`,
)) +
renderCheckOnlySATCard(stressDefault, renderSATCard("tpm", "TPM", "runSAT('tpm')", "", renderValidateCardBody(
inv.TPM,
`Checks TPM 2.0 communication and reports its fixed properties, allocated PCR banks, current PCR values, and the result of self-tests already performed by the TPM. It does not start a new self-test or change TPM state.`,
`tpm2_getcap properties-fixed, tpm2_getcap pcrs, tpm2_pcrread, tpm2_gettestresult`,
`Seconds - read-only queries; no ownership, NV, PCR, or key changes.`,
))) +
`` + inv.NVIDIA + `
All NVIDIA validate tasks use only the GPUs selected here. The same selection is used by Run All.
Loading NVIDIA GPUs...
Select at least one NVIDIA GPU to enable NVIDIA validate tasks.
nvidia-smi, dmidecode, dcgmi diag`,
fmt.Sprintf("Validate: %s (Level 2, all GPUs simultaneously). Stress: %s (Level 3, all GPUs simultaneously).",
validateFmtDur(platform.SATEstimatedNvidiaGPUValidateSec),
validateFmtDur(platform.SATEstimatedNvidiaGPUStressSec)),
)) +
stressOnlyCards +
renderCheckOnlySATCard(stressDefault, renderSATCard("nvidia-interconnect", "NVIDIA Interconnect (NCCL)", "runNvidiaFabricValidate('nvidia-interconnect')", "", renderValidateCardBody(
inv.NVIDIA,
`Verifies NVLink/NVSwitch fabric bandwidth using NCCL all_reduce_perf across all selected GPUs. Pass/fail based on achieved bandwidth vs. theoretical.`,
`all_reduce_perf (NCCL tests)`,
validateFmtDur(platform.SATEstimatedNvidiaInterconnectSec)+` (all GPUs simultaneously, requires ≥2).`,
))) +
renderSATCard("nvidia-bandwidth", "NVIDIA Bandwidth + PCIe Link", "runNvidiaFabricValidate('nvidia-bandwidth')", "", renderValidateCardBody(
inv.NVIDIA,
`Validates GPU memory copy and peer-to-peer bandwidth paths, then samples each GPU's negotiated PCIe speed and width immediately after real traffic. Idle or forced-retrain Gen1 readings do not fail the test.`,
`dcgmi diag -r nvbandwidth, sysfs PCIe link attributes`,
validateFmtDur(platform.SATEstimatedNvidiaBandwidthSec)+` (all GPUs simultaneously; nvbandwidth runs all built-in tests without a time limit - duration set by the tool).`,
)) +
`rocm-smi, dmidecode; MEM Integrity: rvs mem; MEM Bandwidth: rocm-bandwidth-test, rvs babel`,
``,
))) +
`lscpu, sensors, stress-ng`,
validateFmtDur(platform.SATEstimatedCPUValidateSec)+` (stress-ng 60 s).`,
)) +
renderSATCard("memory", "Memory", "runSAT('memory')", "", renderValidateCardBody(
inv.Memory,
`Runs a RAM validation pass and records memory state around the test.`,
`free, memtester`,
validateFmtDur(platform.SATEstimatedMemoryValidateSec)+` (256 MB × 1 pass).`,
)) +
renderSATCard("storage", "Storage", "runSAT('storage')", "", renderValidateCardBody(
inv.Storage,
`Collects SMART health and attributes for each storage device. No self-test is triggered — read-only query only.`,
`lsblk; NVMe: nvme id-ctrl, nvme smart-log; SATA/SAS: smartctl -H -A`,
`Seconds — instantaneous device query, no wear counters incremented.`,
)) +
renderSATCard("tpm", "TPM", "runSAT('tpm')", "", renderValidateCardBody(
inv.TPM,
`Checks TPM 2.0 communication and reads fixed properties, allocated PCR banks, current PCR values, and the result of self-tests already performed by the TPM. It never starts a new self-test.`,
`tpm2_getcap properties-fixed, tpm2_getcap pcrs, tpm2_pcrread, tpm2_gettestresult`,
`Seconds - read-only queries; no ownership, NV, PCR, or key changes.`,
)) +
renderSATCard("nvidia-config", "GPU Config & NVLink", "runSAT('nvidia-config')", "", renderValidateCardBody(
inv.NVIDIA,
`Checks GPU configuration and NVLink topology that DCGM diag does not cover: ECC/MIG/power-limit drift from factory default, NVLink-bonded pair link count and error counters, and (informational) NVIDIA Confidential Computing readiness (CPU TEE support + GPU firmware CC capability). Read-only — changes nothing.`,
`nvidia-smi --query-gpu=..., nvidia-smi topo -m, nvidia-smi nvlink -s/-e, nvidia-smi conf-compute -q, dmesg`,
`Seconds — read-only query only.`,
)) +
`` + inv.NVIDIA + `
Loading NVIDIA GPUs...
Select at least one NVIDIA GPU to enable NVIDIA check tasks.
nvidia-smi, dmidecode, dcgmi diag`,
validateFmtDur(platform.SATEstimatedNvidiaGPUValidateSec)+` (Level 2, all GPUs simultaneously).`,
)) +
renderSATCard("nvidia-interconnect", "NVIDIA Interconnect (NCCL)", "runNvidiaFabricValidate('nvidia-interconnect')", "", renderValidateCardBody(
inv.NVIDIA,
`Verifies NVLink/NVSwitch fabric bandwidth using NCCL all_reduce_perf across all selected GPUs.`,
`all_reduce_perf (NCCL tests)`,
validateFmtDur(platform.SATEstimatedNvidiaInterconnectSec)+` (all GPUs simultaneously, requires ≥2).`,
)) +
renderSATCard("nvidia-bandwidth", "NVIDIA Bandwidth + PCIe Link", "runNvidiaFabricValidate('nvidia-bandwidth')", "", renderValidateCardBody(
inv.NVIDIA,
`Validates GPU memory copy and peer-to-peer bandwidth paths, then samples each GPU's negotiated PCIe speed and width immediately after real traffic.`,
`dcgmi diag -r nvbandwidth, sysfs PCIe link attributes`,
validateFmtDur(platform.SATEstimatedNvidiaBandwidthSec)+` (all GPUs simultaneously).`,
)) +
`rocm-smi, dmidecode; MEM Integrity: rvs mem; MEM Bandwidth: rocm-bandwidth-test, rvs babel`,
``,
)) +
`