Skip to content

P0: redfish_ctl as the authoritative corpus-backed Redfish simulator + stable consumer contract #114

Description

@spyroot

Goal

Make redfish_ctl the authoritative corpus-backed Redfish simulator and publish a stable, versioned contract that IGC and other consumers can depend on without reaching into k8s/sandbox/ or tests/ internals.

This is an umbrella P0. Work lands as ordered, dependency-linked items, one at a time, each validated before the next starts. The corpus manifest, simulator state engine, and public API have a single design owner — they must not be independently redesigned by parallel work.

Extend the existing systems; do not fork a second corpus catalog or a second simulator:

  • Corpus: tests/corpus/manifest.json, tools/corpus.py, docs/corpus-library.md
  • Simulator: k8s/sandbox/mock_bmc_server.py, tests/mutation_rules/, tests/write_traces/
  • All new public classes, modules, commands, docs, tests, and automation use redfish_ctl naming. "iDRAC" remains valid only as Dell's product name.

Non-negotiable semantics

  1. A corpus provides read/observation state.
  2. A corpus alone does not define write behavior.
  3. Write behavior comes from one of two existing engines: replay (strict, recorded, ordered — ReplayState) or rules (stateful, order-independent, precondition-guarded — MutationRules).
  4. Preserve both engines; do not merge them into one ambiguous mode.
  5. Replay and rules are mutually exclusive within one episode.
  6. Full and sim corpora are different artifacts:
    • full: every sanitized captured JSON — mappings, logs, events, schemas, registries, metadata.
    • sim: a derived, optionally filtered serving set optimized for tests/runtime.
  7. "Feature parity" = parity with redfish_ctl's implemented and manifest-declared capabilities for that vendor/model. An Action present in JSON is not proof it is safely simulatable.
  8. A discovered action without grounded transition behavior is reported as unsupported or unverified — never a silent success.
  9. Every simulated mutation is grounded in one of: a captured before/write/after trace; existing verified redfish_ctl command semantics; or standard Redfish behavior validated against captured allowable values.
  10. Preserve the existing Kubernetes sandbox, Docker mock image, CLI wrapper, /__replay_status, and /__set_scenario while introducing the public API.

Ordered items (dependency-linked)

  • RF-SIM-00 — Freeze and document the existing contract (deps: none)
    Inventory mock_bmc_server.py (_OverlayStore/ReplayState/MutationRules/failure injection//__replay_status//__set_scenario), the ilo-sim lane, the sushy-emulator smoke lane (tests/test_emulator_smoke.py), the k8s sandbox consumers, and all per-vendor rules (tests/mutation_rules/*.yaml). Add regression tests freezing current replay ordering, rule composition, 409 for unmatched writes, reset behavior, deterministic seeds, and the Docker/k8s entry points. Write docs/simulator-contract.md. Produce a vendor/model capability matrix with supported / unsupported / unverified states.

  • RF-CORPUS-01 — Upgrade the corpus manifest (deps: RF-SIM-00)
    Bump tests/corpus/manifest.json to a versioned schema with a v1-compatible loader. Give each artifact a corpus_id and kind (full|sim); reclassify today's filtered archives as sim / filtered-device-telemetry (do not call them full); add source_corpus_id linking a sim artifact to its full source. Add fields: checksum, status, JSON count, root prefix, rest_api_map location, logs/events/schemas/registries flags, mutation-rules file, replay traces, simulator capabilities, sanitization version, completeness limitations. Recover/create true sanitized full archives for every committed capture. Dell XR8620t's 995-file archive is a filtered sim, not a full corpus — verify against the original capture and record the real full count. Extend tools/corpus.py (--kind full|sim, strict verify that fails on unresolved LFS pointers, safe extraction, recursive listing, corpus-ID selection, checksums, machine-readable JSON). Promote the implementation to redfish_ctl corpus …, keeping tools/corpus.py as a compatibility wrapper.

  • RF-CORPUS-02 — Make full discovery genuinely complete (deps: RF-CORPUS-01)
    Add an explicit full-corpus discovery profile. In full mode include individual LogService entries, EventService resources, schemas, registries, tasks, jobs, and every reachable JSON. Fix the conflict where --include-log-entries is still defeated by the default SEL/Lclog filter. Full mode must never silently truncate — on a safety limit / permission / transport failure, mark the capture incomplete and record missing paths. Add pacing, retry, resume/checkpoint, and high-cardinality warnings so complete capture does not overload fragile BMCs. Produce a safe JSON URL/method map (rest_api_map.v1.json); retain .npy compatibility but consumers must not need pickle-enabled NumPy.

  • RF-SIM-01 — Extract a public simulator package and CLI (deps: RF-SIM-00, RF-CORPUS-01)
    Move reusable implementation into redfish_ctl/sim/; leave mock_bmc_server.py a thin compatibility wrapper. Publish an in-process API (Simulator.from_catalog(corpus_id, mode, seed), new_episode(seed=None), episode.request(method, path, json=None, headers=None), episode.reset(seed=None), episode.status(), episode.close()) and a standalone server (redfish_ctl sim serve --corpus <id> --mode readonly|replay|rules, sim list, sim capabilities --corpus <id>, sim verify --corpus <id>). Corpus selection is via the manifest, not raw IP dirs. Reads recursively index the materialized corpus, detect path collisions, normalize URI case safely, and never assume one-directory-deep JSON. Keep read-only behavior and 405 when no write engine is selected.

  • RF-SIM-02 — Versioned, parameterized transitions (deps: RF-SIM-01)
    Preserve the current rule/trace grammar as v1. Add a backward-compatible v2 grammar: copy a value from the request body; deep-merge a request subtree; clear a collection and update Members@odata.count; add/remove members; create and advance task/job resources; apply staged settings on reset. Do not replace existing set/delete transitions. InsertMedia must preserve the exact requested Image URI on subsequent reads; Boot PATCH must preserve validated request values; BIOS Settings PATCH must accept captured allowable attributes (not one hard-coded value); ClearLog must yield an observable empty collection/count (not just 204); Volume create/delete must update collection+member state when the vendor capability claims support; a failed injected action performs zero state transitions.

  • RF-SIM-03 — Prove chained workflows end to end (deps: RF-SIM-02, RF-CORPUS-02)
    On a corpus with the required resources (preferably Supermicro GB300): read initial System/BIOS/BIOS-Settings/VirtualMedia → InsertMedia an ISO → verify exact Image + Inserted → stage a captured allowable BIOS attribute → verify live BIOS unchanged and Settings holds the pending value → set a one-time boot target supported by the captured system → reset → verify pending BIOS moved to live, pending setting cleared, one-time boot consumed per captured behavior, virtual-media state matches capture, and replay/rule status reports the expected transitions. Implement twice: an ordered replay trace that rejects out-of-order writes, and mutation rules that allow unrelated ops in any order while enforcing preconditions. Do not force this workflow onto HPE/Dell/X10 when their corpus lacks VirtualMedia/BIOS — their capability matrix states the real subset.

  • RF-SIM-04 — Vendor parity and backend conformance (deps: RF-SIM-02)
    Map every mutating redfish_ctl command to each corpus/vendor. Add corpus-backed conformance tests for Dell XR8620t, HPE iLO, Supermicro X10, GB300, node2. Add a backend registry (internal corpus simulator, existing HPE ilo-sim, existing sushy-emulator lane, external DMTF/Dell simulators when actually available) and run the same read/write capability contract against each. External simulators may expose different subsets — report that rather than fabricating parity.

  • RF-SIM-05 — Episode isolation and RL-scale operation (deps: RF-SIM-01)
    Each episode owns independent overlays, replay progress, RNG, failure history, and reset state — no cross-episode leakage. For HTTP, expose versioned control endpoints or opaque session IDs that are not actions visible to the RL agent; keep old control endpoints. The in-process API is the preferred high-throughput path; HTTP is the interoperability path. Benchmark ≥10,000 mixed read/write requests across many independent episodes; record throughput and p50/p95/p99. Tests: concurrent reads, serialized writes within one episode, parallel writes across isolated episodes, deterministic reset, zero cross-episode contamination. The existing ThreadingHTTPServer smoke test alone does not satisfy RL scale.

  • RF-SIM-06 — Publish the cross-project contract (deps: RF-SIM-03, RF-SIM-04, RF-SIM-05)
    Version the simulator API and corpus-manifest schema. Document full-vs-sim artifacts, readonly/replay/rules modes, the Python API, the CLI/server, the HTTP/session contract, reset+seed semantics, the response/error envelope, capability negotiation, provenance fields, and exact IGC integration commands. Add a redfish_ctl contract fixture IGC can test against without copying simulator code. Link the redfish_ctl and IGC PRs to this issue.

Program acceptance

  • Current replay and mutation-rules tests remain green.
  • The mount-ISO → stage-BIOS → set-one-time-boot → reset → verify sequence passes.
  • Full and sim corpora are accurately distinguished.
  • Full capture retains logs/events instead of silently deleting them.
  • Every simulator episode is independently resettable.
  • All vendor capabilities are reported truthfully; unsupported writes fail explicitly.
  • IGC consumes the public contract, not k8s/sandbox/ or tests/ internals.
  • The simulator handles the RL request-volume benchmark without state leakage.
  • No new generic idrac_ctl identifiers are introduced.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions