From 5a099abe98ad52d6227cbda923180ab21c6e4989 Mon Sep 17 00:00:00 2001 From: Krish Dandiwala Date: Mon, 22 Jun 2026 16:25:40 +0000 Subject: [PATCH 1/3] feat: add support for lenovo gb300s Signed-off-by: Krish Dandiwala --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/bmc-explorer/src/lib.rs | 27 +++++++++++++++++++ .../tests/lenovo_gb300_explore.rs | 7 ++++- crates/redfish/src/libredfish/conv.rs | 2 +- crates/site-explorer/src/redfish.rs | 1 + 6 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 073a4b15c0..9ec1dccb40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6530,7 +6530,7 @@ dependencies = [ [[package]] name = "libredfish" version = "0.0.0" -source = "git+https://github.com/NVIDIA/libredfish.git?tag=v0.44.11#677c18d32be6abff6fbd82dcce86b1845e680899" +source = "git+https://github.com/NVIDIA/libredfish.git?tag=v0.44.12#29de93f4bd4b1c5de8c57fef9ac49d1b7d93494d" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index b08d7aea86..17045b8d17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ authors = ["NVIDIA Carbide Engineering "] [workspace.dependencies] clap = { version = "4", features = ["derive", "env"] } -libredfish = { git = "https://github.com/NVIDIA/libredfish.git", tag = "v0.44.11" } +libredfish = { git = "https://github.com/NVIDIA/libredfish.git", tag = "v0.44.12" } librms = { git = "https://github.com/NVIDIA/nv-rms-client.git", tag = "v0.9.0-rc1" } ansi-to-html = "0.2.2" diff --git a/crates/bmc-explorer/src/lib.rs b/crates/bmc-explorer/src/lib.rs index 7f597eafb1..40c4ad1a4a 100644 --- a/crates/bmc-explorer/src/lib.rs +++ b/crates/bmc-explorer/src/lib.rs @@ -159,6 +159,10 @@ pub async fn nv_generate_exploration_report( need_oem_ami_config_bmc: true, ..Default::default() }, + hw::HwType::LenovoGb300 => manager::Config { + need_host_interfaces: true, + ..Default::default() + }, hw::HwType::Supermicro => manager::Config { need_host_interfaces: true, need_oem_supermicro_kcs_interface: true, @@ -376,6 +380,29 @@ fn lockdown_status( .map(|status| Some(LockdownStatus { status, message })) } + // LenovoGB300 (Grace-based AMI host BMC) has neither the KCS BIOS + // attribute nor the OEM ConfigBMC endpoint. Lockdown is read from the + // USB support attribute (attribute-id prefixed enum, e.g. + // "USB000Disabled") together with the host interface state. + hw::HwType::LenovoGb300 => { + let bios = bios.as_ref().ok_or_else(Error::bmc_not_provided("bios"))?; + let usb000 = bios.attribute("USB000"); + let usb000 = usb000.as_ref().and_then(|v| v.str_value()); + let hi_enabled = explored_manager + .host_interfaces + .as_ref() + .ok_or_else(Error::bmc_not_provided("host interfaces"))? + .iter() + .any(|i| i.interface_enabled().is_none_or(identity)); + let message = format!("usb_support={usb000:?}; host_interface={hi_enabled}"); + match (usb000, hi_enabled) { + (Some("USB000Disabled"), false) => Ok(InternalLockdownStatus::Enabled), + (Some("USB000Enabled"), true) => Ok(InternalLockdownStatus::Disabled), + _ => Ok(InternalLockdownStatus::Partial), + } + .map(|status| Some(LockdownStatus { status, message })) + } + hw::HwType::Dell => { let attributes = explored_manager .oem_dell_attributes diff --git a/crates/bmc-explorer/tests/lenovo_gb300_explore.rs b/crates/bmc-explorer/tests/lenovo_gb300_explore.rs index 6ee8b69814..a035cbdb87 100644 --- a/crates/bmc-explorer/tests/lenovo_gb300_explore.rs +++ b/crates/bmc-explorer/tests/lenovo_gb300_explore.rs @@ -20,7 +20,7 @@ use bmc_explorer::hw::HwType; use bmc_explorer::nv_generate_exploration_report; use bmc_explorer::test_support::detect_hw_type; use bmc_mock::test_support; -use model::site_explorer::EndpointType; +use model::site_explorer::{EndpointType, InternalLockdownStatus}; use tokio::test; /// A Lenovo GB300 (AMI BMC) must classify as the GB300 platform regardless of the @@ -49,4 +49,9 @@ async fn explore_lenovo_gb300() { assert_eq!(report.vendor, Some(bmc_vendor::BMCVendor::LenovoAMI)); assert!(!report.systems.is_empty(), "systems must be present"); assert!(!report.chassis.is_empty(), "chassis must be present"); + + let lockdown = report + .lockdown_status + .expect("GB300 lockdown status must be populated"); + assert_eq!(lockdown.status, InternalLockdownStatus::Partial); } diff --git a/crates/redfish/src/libredfish/conv.rs b/crates/redfish/src/libredfish/conv.rs index dcff6cd5db..2705d7de86 100644 --- a/crates/redfish/src/libredfish/conv.rs +++ b/crates/redfish/src/libredfish/conv.rs @@ -159,7 +159,7 @@ pub fn bmc_vendor(r: libredfish::model::service_root::RedfishVendor) -> BMCVendo RedfishVendor::Dell => BMCVendor::Dell, RedfishVendor::Hpe => BMCVendor::Hpe, RedfishVendor::Lenovo => BMCVendor::Lenovo, - RedfishVendor::LenovoAMI => BMCVendor::LenovoAMI, + RedfishVendor::LenovoAMI | RedfishVendor::LenovoGB300 => BMCVendor::LenovoAMI, RedfishVendor::LiteOnPowerShelf => BMCVendor::Liteon, RedfishVendor::DeltaPowerShelf => BMCVendor::Delta, RedfishVendor::Supermicro => BMCVendor::Supermicro, diff --git a/crates/site-explorer/src/redfish.rs b/crates/site-explorer/src/redfish.rs index 513957f2d5..7a6ab54fe7 100644 --- a/crates/site-explorer/src/redfish.rs +++ b/crates/site-explorer/src/redfish.rs @@ -246,6 +246,7 @@ impl RedfishClient { .map_err(map_redfish_error)?; } RedfishVendor::LenovoAMI + | RedfishVendor::LenovoGB300 | RedfishVendor::Supermicro | RedfishVendor::Dell | RedfishVendor::Hpe => { From 86c3a9df0486970f53c213ba823a694087d4e2e2 Mon Sep 17 00:00:00 2001 From: Krish Dandiwala Date: Mon, 22 Jun 2026 17:20:28 +0000 Subject: [PATCH 2/3] chore: document pw change more clearly Signed-off-by: Krish Dandiwala --- crates/site-explorer/src/redfish.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/site-explorer/src/redfish.rs b/crates/site-explorer/src/redfish.rs index 7a6ab54fe7..1c4d592085 100644 --- a/crates/site-explorer/src/redfish.rs +++ b/crates/site-explorer/src/redfish.rs @@ -230,8 +230,10 @@ impl RedfishClient { .map_err(|err| redact_password(err, curr_password.as_str())) .map_err(map_redfish_error)?; } - // Handle Vikings - RedfishVendor::AMI => { + // Vikings and Lenovo GB300s. GB300s are detected as AMI at this + // point (vendor isn't refined to LenovoGB300 until later), but both + // rotate via the same admin account, so handle them together. + RedfishVendor::AMI | RedfishVendor::LenovoGB300 => { /* https://docs.nvidia.com/dgx/dgxh100-user-guide/redfish-api-supp.html @@ -246,7 +248,6 @@ impl RedfishClient { .map_err(map_redfish_error)?; } RedfishVendor::LenovoAMI - | RedfishVendor::LenovoGB300 | RedfishVendor::Supermicro | RedfishVendor::Dell | RedfishVendor::Hpe => { From af3333d23251a867fd1c966f81e4a360ac245d9c Mon Sep 17 00:00:00 2001 From: Krish Dandiwala Date: Mon, 22 Jun 2026 17:50:48 +0000 Subject: [PATCH 3/3] fix: trim whitespace for chassis serial numbers Signed-off-by: Krish Dandiwala --- crates/bmc-explorer/src/chassis.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bmc-explorer/src/chassis.rs b/crates/bmc-explorer/src/chassis.rs index dc5c40f5ae..4d105e8150 100644 --- a/crates/bmc-explorer/src/chassis.rs +++ b/crates/bmc-explorer/src/chassis.rs @@ -243,7 +243,8 @@ impl ExploredChassis { let serial_number = self .assembly_sn .clone() - .or(hw_id.serial_number.map(|v| v.to_string())); + .or(hw_id.serial_number.map(|v| v.to_string())) + .map(|s| s.trim().to_string()); let nvidia_oem = self .chassis