feat: expose network adapter port MAC addresses - #180
Conversation
4903134 to
c612bd6
Compare
| ) -> Result<Self, Error<B>> { | ||
| let data = nav.get(bmc.as_ref()).await.map_err(Error::Bmc)?; | ||
| #[cfg(feature = "oem-lenovo")] | ||
| let oem_lenovo = LenovoPort::new(&data).map_err(Error::Json)?; |
There was a problem hiding this comment.
Should Lenovo port parsing be deferred until a fallback is needed? With this feature enabled, an incompatible Lenovo value can fail Port::new() and the whole collection. But valid standard MAC address data may be available in the meantime.
There was a problem hiding this comment.
Yes even worse whole members() would fail if even one fails here.
There was a problem hiding this comment.
Yeah, good call -- I’ll move Lenovo parsing out of Port::new() and defer it to explicit OEM access, so a malformed Lenovo payload can’t fail members() or hide usable standard MAC data. I'll post back when it's done, lemme tweak.
|
|
||
| /// Support of Lenovo Port OEM attributes. | ||
| #[cfg(feature = "ports")] | ||
| pub(crate) mod port; |
There was a problem hiding this comment.
why pub(crate) here? Is not used anywhere inside.
There was a problem hiding this comment.
Sooo, this is/was pub(crate) because port wasn't visible to oem::lenovo. BUT, @poroh's comment below will actually change this, with a pub LenovoPort that we'll make available to through Port::oem_lenovo(). I'll ping back once it's updated! Looking through the other comments still.
| } | ||
|
|
||
| impl<B: Bmc> PortCollection<B> { | ||
| #[allow(dead_code)] // Used by NetworkAdapter when that feature is enabled. |
There was a problem hiding this comment.
I think you can drop it, it would be generated only when port is reachable which requires network adapters
| collection: Arc<PortCollectionSchema>, | ||
| } | ||
|
|
||
| impl<B: Bmc> PortCollection<B> { |
There was a problem hiding this comment.
we usually spliting collection and port in different files in repo. Rule of thumb one primary struct per rs file
There was a problem hiding this comment.
Okay nice -- yeah I like that. Give me a bit; I'll split this across port/mod.rs, port/collection.rs, and port/item.rs.
|
|
||
| /// Get Lenovo's physical-port MAC address. | ||
| #[must_use] | ||
| pub fn physical_port_mac_address(&self) -> Option<&str> { |
There was a problem hiding this comment.
Yupppp -- will update to return Option<MacAddress>.
| /// returned when the standard array is absent or empty. | ||
| /// | ||
| #[must_use] | ||
| pub fn associated_mac_addresses(&self) -> Vec<MacAddress<'_>> { |
There was a problem hiding this comment.
This function doing a little too much. It is not clear from outside (by name at least), what it OEM dependent. associated_mac_addresses is something standart, this silently switches to Lenovo if it not found and Lenovo OEM enabled.
If we want something with vendor fallback (something smart) we need name it as such i think.
It also kinda pushes Site Explorer logic into nv-redfish, which i'm not fan of, better be other way around. But i will let @poroh to chime here.
There was a problem hiding this comment.
nv-redfish rule of thumb is "do not try to be smart when provide data to library user". If data is available through OEM extension then nv-redfish should provide access to OEM extension and let library user to choose if they want to use LenovoPort::physical_port_mac_address as associated_mac_addresses.
This decision is not nv-redfish buisness.
There was a problem hiding this comment.
Yeah agreed. I realize we're fixing a lot of anti-patterns we inherited and/or continued with libredfish with this repo -- thanks for ensuring it stays that way. I'll fiddle with it so port.associated_mac_addresses() returns just standard Ethernet.AssociatedMACAddresses, and then port.oem_lenovo() returns LenovoPort, so site-explorer would end up doing something like...
let addresses = port.associated_mac_addresses();
if addresses.is_empty() {
if let Some(lenovo) = port.oem_lenovo()? {
if let Some(address) = lenovo.physical_port_mac_address() {
// and then site-explorer does some fallback work here or something like that
}
}
}
Back in a bit!
c612bd6 to
744e0d9
Compare
|
@yoks @poroh @jayzhudev Okay, I think this is ready for another pass. Let me know if you want any more adjustments. Thanks for looking through it! |
|
|
||
| use crate::mac_address::MacAddress; | ||
| #[cfg(feature = "oem-lenovo")] | ||
| use crate::oem::lenovo::port::LenovoPort; |
There was a problem hiding this comment.
nitpick: I prefer to separate conditional imports and non-conditional imports.
There was a problem hiding this comment.
@poroh Updated! I think I'll need a re-approval now though.
Some BMCs leave Systems/.../EthernetInterfaces empty even though the installed host NIC is visible through Chassis/.../NetworkAdapters/.../Ports. Add the standard Port collection and resource wrappers and let NetworkAdapter callers traverse that collection. Port::associated_mac_addresses prefers Ethernet.AssociatedMACAddresses, then falls back to Lenovo XCC's Oem.Lenovo.PhysicalPortMacAddress when standard data is absent or empty. Keep vendor handling inside nv-redfish, preserve server-provided MAC formatting, and cover standard, Lenovo-only, precedence, empty, missing-link, and end-to-end collection behavior. Closes NVIDIA#176 Signed-off-by: Chet Nichols III <chetn@nvidia.com>
744e0d9 to
d83b167
Compare
jayzhudev
left a comment
There was a problem hiding this comment.
Sending extra love : )
…4968) Lenovo XCC can report usable onboard `ComputerSystem.EthernetInterfaces` while exposing an installed ConnectX NIC only through a linked chassis `NetworkAdapter.Port`. The adapter-Port fetch treated any usable System MAC as proof that inventory was complete, so the declared NoDpu boot NIC never reached `predicted_machine_interfaces`. So, this leaves the existing no-usable-System-MAC fallback intact and adds a separate supplemental case inside the same verified Lenovo + `ComputerSystem.Links.Chassis` boundary. That case collects adapter Ports even when usable System interfaces exist. Site Explorer still uses System interfaces as Host candidates; it adds a Port MAC alongside them only when that MAC was actually reported by hardware and `ExpectedMachine` declares it as a Host interface. It does not synthesize `EthernetInterfaces`, treat the declaration as an override, or use a Port ID as a boot-interface ID. A refreshed report can now add that MAC to an existing predicted host, keep its boot target MAC-only, and leave already-managed hosts alone. Retained boot metadata is consulted only when a predicted host has no primary, so an unrelated stale record cannot replace a settled primary. This means verified Lenovo XCC hosts fetch Ports from the explicitly linked chassis on each exploration. That extra inventory work stays behind the vendor + linked-chassis boundary because a generic chassis Port is not necessarily a host/PXE interface. Tests added! ## Related issues This supports #4952 ## Type of Change - [ ] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [x] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [ ] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Breaking Changes - [ ] **This PR contains breaking changes** ## Testing - [x] Unit tests added/updated - [x] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ```bash cargo test -p bmc-explorer -p carbide-site-explorer --lib make core/tests TEST_ARGS="-p carbide-site-explorer --test integration zero_dpu::test_ -- --nocapture" cargo make clippy carbide-lints --all-targets --all-features cargo make format-nightly cargo make check-licenses cargo make check-bans cargo xtask check-workspace-deps taplo fmt --check crates/site-explorer/Cargo.toml ``` ## Additional Notes This is the caller-side follow-up to #4469 and #4534, using the adapter-Port inventory exposed by [NVIDIA/nv-redfish#180](NVIDIA/nv-redfish#180). Signed-off-by: Chet Nichols III <chetn@nvidia.com>
We ran into a Lenovo host with an empty
Systems/.../EthernetInterfacescollection, which meantsite-explorercouldn't find the host MAC it needed to recognize the PXE interface. The NIC was there -- it was just exposed underChassis/.../NetworkAdapters/.../Ports, with Lenovo XCC putting the physical-port address inOem.Lenovo.PhysicalPortMacAddress.I don't think every caller should have to learn that Lenovo detail.
nv-redfishis our vendor abstraction layer, so this teaches it to traverse the standard port collection and fall back to Lenovo's OEM value only whenPort.Ethernet.AssociatedMACAddressesis missing or empty. That gives callers one path for both cases, while standard values still win and the MAC text stays exactly as the BMC returned it.What changed
PortCollectionandPortwrappers behind a newportsfeatureNetworkAdapter::ports()for standard adapter-port traversalTesting
make cicargo test -p nv-redfish-tests --test test-network-adapter-port -- --no-captureRelated issues
This supports #176.
This supports NVIDIA/infra-controller#4436.
Closes #176