feat(nico): add BFX03-01 hardware serial inventory + STG05-01 failure-domain observability#539
Conversation
Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Alexandre Begnoche <abegnoche@users.noreply.github.com>
…tion Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Alexandre Begnoche <abegnoche@users.noreply.github.com>
📝 WalkthroughWalkthroughAdded NICo bare-metal checks for stable hardware identifiers and physical failure domains. The changes include provider scripts, validation classes, suite configuration, execution settings, documentation, and unit/integration coverage. ChangesBare-metal observability
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant BareMetalSuite
participant query_serial_numbers.py
participant query_topology.py
participant NICoAPI
participant HardwareSerialCheck
participant FailureDomainObservabilityCheck
BareMetalSuite->>query_serial_numbers.py: Run hardware inventory query
query_serial_numbers.py->>NICoAPI: Fetch site machines with metadata
NICoAPI-->>query_serial_numbers.py: Return machine hardware metadata
query_serial_numbers.py-->>HardwareSerialCheck: Provide component identifiers
BareMetalSuite->>query_topology.py: Run topology query
query_topology.py->>NICoAPI: Fetch site machines
NICoAPI-->>query_topology.py: Return machine labels
query_topology.py-->>FailureDomainObservabilityCheck: Provide host failure domains
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Each bare_metal step is a standalone REST query with no cross-step dependencies. Mark them continue_on_failure so one failing check (e.g. IB tenant isolation when the org has no tenant) does not skip later probes such as hardware serial inventory and topology observability. Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
Apply cleanup-review findings on the new hardware-inventory and topology validations, with no behavior change to validation outcomes: - query_topology: reuse common.inventory.first_string for rack-label extraction and trim RACK_LABEL_KEYS to the two documented keys (RackIdentifier, rack); drop the derivable `observed` field and the unconsumed `failure_domains` aggregate from the JSON contract - query_serial_numbers: drop COMPONENT_ORDER and the dict-rebuilding comprehension (the literal already carries report order), inline the single-use _clean helper, and fix the chassis-identifier comment - HardwareSerialCheck / FailureDomainObservabilityCheck: read min_* config knobs via BaseValidation._parse_positive_int like the newest sibling checks, so config typos fail cleanly instead of raising - update docstrings, suite README step table, and tests to match the trimmed topology contract Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
|
/ok to test 0aaf6d1 |
🔐 TruffleHog Secret Scan✅ No secrets or credentials found! Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉 🕐 Last updated: 2026-07-13 21:40:38 UTC | Commit: 0aaf6d1 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
isvctl/configs/providers/nico/scripts/topology/query_topology.py (1)
82-82: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAnnotate
RACK_LABEL_KEYS.Proposed fix
-RACK_LABEL_KEYS = ("RackIdentifier", "rack") +RACK_LABEL_KEYS: tuple[str, ...] = ("RackIdentifier", "rack")As per coding guidelines, “All Python files must use type annotations following PEP 585.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@isvctl/configs/providers/nico/scripts/topology/query_topology.py` at line 82, Annotate the RACK_LABEL_KEYS constant with an appropriate PEP 585 type, preserving its tuple of string values and existing ordering.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@isvctl/configs/providers/nico/scripts/topology/query_topology.py`:
- Line 82: Annotate the RACK_LABEL_KEYS constant with an appropriate PEP 585
type, preserving its tuple of string values and existing ordering.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: a1c8e815-677f-4f11-92be-a8163328bf44
📒 Files selected for processing (11)
docs/test-plan.yamlisvctl/configs/providers/nico/config/bare_metal.yamlisvctl/configs/providers/nico/scripts/hardware_inventory/query_serial_numbers.pyisvctl/configs/providers/nico/scripts/topology/query_topology.pyisvctl/configs/suites/README.mdisvctl/configs/suites/bare_metal.yamlisvctl/tests/providers/nico/test_nico_provider.pyisvtest/src/isvtest/validations/hardware.pyisvtest/src/isvtest/validations/topology.pyisvtest/tests/test_hardware.pyisvtest/tests/test_topology.py
Align NICo bare_metal orchestration with PR #539 so unrelated probe failures (e.g. IB tenant isolation when the org has no tenant) do not skip later independent validations such as STG02/03/04 storage-infra checks. Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
Implement three NICo bare-metal checks grounded in the public Machine REST API, following the query-script → neutral-JSON → validation pattern from PR #539: - STG02-01 SkipSanitizationBreakfixCheck: extends the SEC21 sanitization audit with tenancy-preserving maintenance skips (in_use -> maintenance -> in_use without Reset). - STG03-01 StableStorageNodeIpCheck: asserts stable admin IPs are queryable via machineInterfaces[].ipAddresses. - STG04-01 OobFailureDetectionCheck: asserts BMC/out-of-band health probes expose failure-detection coverage (BmcSensor baseline). All three ship unreleased; exercise with ISVTEST_INCLUDE_UNRELEASED=1. Closes #358 Closes #359 Closes #360 Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Alexandre Begnoche <abegnoche@users.noreply.github.com>
Implement three NICo bare-metal checks grounded in the public Machine REST API, following the query-script → neutral-JSON → validation pattern from PR #539: - STG02-01 SkipSanitizationBreakfixCheck: extends the SEC21 sanitization audit with tenancy-preserving maintenance skips (in_use -> maintenance -> in_use without Reset). - STG03-01 StableStorageNodeIpCheck: asserts stable admin IPs are queryable via machineInterfaces[].ipAddresses. - STG04-01 OobFailureDetectionCheck: asserts BMC/out-of-band health probes expose failure-detection coverage (BmcSensor baseline). All three ship unreleased; exercise with ISVTEST_INCLUDE_UNRELEASED=1. Closes #358 Closes #359 Closes #360 Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Alexandre Begnoche <abegnoche@users.noreply.github.com>
Summary
Implements two M7 NICo bare-metal observability checks. Both are provider-neutral validations grounded in the public NICo (infra-controller) REST API, following the established NICo-validation pattern (#457/#458/#466). Neither is feasible on AWS: EC2 virtualizes hardware (no real chassis/baseboard/NIC serials) and exposes no physical rack/enclosure topology. Both ship unreleased (
released_tests.jsonuntouched); exercise withISVTEST_INCLUDE_UNRELEASED=1.HardwareSerialCheckmachine.metadata.{dmiData,gpus,networkInterfaces,infinibandInterfaces}+machineCapabilities(viaincludeMetadata=true)FailureDomainObservabilityCheckmachine.labels—RackIdentifierorrackChanges
BFX03-01 (#320) — hardware serial-number inventory
query_serial_numbers.py: reduces each machine's discovered hardware metadata to a per-component stable-identifier record — chassis/baseboard DMI serials, GPU serials, NIC MAC/GUID, CPU model. Chassis falls back to the provider-visible machineserialNumber.HardwareSerialCheck(hardware.py): asserts a stable identifier is queryable for every present component (chassis, baseboard, CPU, GPU, NIC). Absent components (e.g. GPUs on a CPU-only node) are reported as skipped subtests, never failures. Per BFX03-01, obfuscated-but-stable IDs are accepted; CPUs have no per-socket DMI serial, so the stable CPU model descriptor is the identifier.STG05-01 (#361) — failure-domain topology observability
query_topology.py: reads each host's rack/failure-domain identifier from machine labels (RackIdentifier, thenrack) and emits per-host records (host_id,failure_domain).FailureDomainObservabilityCheck(topology.py): asserts every host maps to a named failure domain and the site meets a configurable diversity floor (min_failure_domains, default 1 = observability only).Orchestration
bare_metal.yaml: mark all standalone query stepscontinue_on_failure: trueso unrelated probe failures (e.g. IB tenant isolation when the org has no tenant) do not skip later independent steps such as serial inventory and topology observability. Matches the pattern already used in NICoobservability.yaml.Refactor (no outcome change)
hosts[]; no derivedobserved/failure_domainsaggregates).common.inventory.first_stringfor rack-label extraction; limit keys to documentedRackIdentifier/rack.min_*config knobs viaBaseValidation._parse_positive_int.Wiring / docs
bare_metal.yaml:query_serial_numbers+query_topologysteps.suites/bare_metal.yaml:hardware_serials(BFX03-01) +failure_domain_observability(STG05-01) groups.suites/README.mdstep tables +docs/test-plan.yamllabel unions updated.Test plan
make lint&&make test(1220 + 97 pass)make demo-testuv run pytest isvtest/tests/test_hardware.py isvtest/tests/test_topology.py isvctl/tests/providers/nico/test_nico_provider.py(new validation + script contract tests)ISVTEST_INCLUDE_UNRELEASED=1): both checks PASS on healthy inventory; a present GPU with no serial and an unlabeled host both flow through to actionable failures.Closes #320
Closes #361