Hardware Control
Control and manage hardware devices including DUTs, PiKVM interfaces, and QEMU virtual machines.
DUTCTL
Run DUTCTL for the DUT. This command can power-cycle and flash the DUT as well as read the serial of the DUT.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
cmd | const | Yes | dutctl | Command Name |
name | string | Yes | Name to uniquely identify the teststep. This name will show up in reports, logs and the WebUI | |
options | OptionsObject | No | Additional command options | |
parameters | DUTCTLOptions | Yes | Options passed into the dutctl cmd |
DUTCTL Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
host | string | Yes | Hostname or IP address of the device. | |
command | string | Yes | Command to execute on the device. Available commands: power, flash, serial. | |
args | []string | No | Arguments for the command. Arguments depend on the command that is executed. | |
input | string | No | Input for the command, used only if command is set to serial. | |
uart | integer | No | UART number to use for serial communication. |
DUTCTL Expect Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
regex | string | Yes | expect | Regular expression to match against the output of the device for the serial command. |
DUTCTL Example
PiKVM
Manage PiKVM operations.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
cmd | const | Yes | pikvm | Command name. |
name | string | Yes | Unique identifier for the teststep. | |
options | OptionsObject | No | Additional command options. | |
parameters | PiKVMOptions | Yes | Parameters for the pikvm command. |
PiKVM Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
command | string | Yes (must be one of: image, screenshot, keyboard) | Operation to perform via the PiKVM interface. | |
host | string | Yes | Hostname or IP address of the PiKVM (format: “https://hostname”). | |
auth | object | Yes (must include username and password) | Authentication details for the PiKVM API. | |
image | object | Conditionally required when command is image | Image configuration. Contains a path property with the image file path to upload and mount. | |
keyboard | object | Conditionally required when command is keyboard | Keyboard input configuration. Use either the keys (array of key sequences) or text (string) property. |
PiKVM Examples
Image mounting:
Screenshot:
Keyboard input:
or
Qemu
Manage QEMU virtual machines.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
cmd | const | Yes | qemu | Command Name |
name | string | Yes | Name to uniquely identify the teststep. This name will show up in reports, logs and the WebUI | |
options | OptionsObject | No | Additional command options | |
parameters | QemuOptions | Yes | Options passed into the qemu cmd |
Qemu Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
mode | string | Yes | Supported modes are start, run and stop. | |
executable | string | Conditional (see below) | The executable that should be executed. | |
firmware | string | Conditional (see below) | The firmware that should be used. | |
image | string | No | The image that should be booted. | |
nproc | integer | No | The number of processors that should be used. | |
mem | integer | No | The amount of memory that should be used. | |
variable | string | Conditional (see below) | Name a variable to store the qemu PID for later session return. | |
serial | QemuStepsOptions | Yes | Steps to interact with during test execution. |
Behavior and semantics
- The
runmode can be used to attach to an already running QEMU instance. In this case,variablemust be set to the PID of the QEMU process. - If
variableis not set, therunmode will behave like thestartmode, launching a new QEMU instance. - The
stopmode will send a termination signal to the QEMU process identified byvariable.
Conditional rules:
start: requiresexecutable,firmware, andvariable. The step launches QEMU and stores its PID invariable. If QEMU prints a PTY path it is stored in<variable>_pty.run: ifvariableis provided the step attaches to the recorded PID/PTY and runs serial steps; ifvariableis empty,runrequires bothexecutableandfirmwareand will launch QEMU and run serial steps.stop: requiresvariableand must not includeexecutable,args,firmwareorserial.
Qemu Serial Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
send | string | No | A string that should be sent as input. | |
timeout | string | No | Timeout for the interaction. Format: h for hours, m for minutes, s for seconds (e.g., 1h30m20s). | |
expect | QemuExpectOptions | No | Expectation for the interaction output. |
Qemu Expect Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
regex | string | Yes | expect | Regular expression that should be matched against the output of the interaction. |
BMCTest
Run BMC (Baseboard Management Controller) compliance and functionality tests using the bmc-test-go tool. This command executes automated tests to verify BMC behavior including IPMI, Redfish, and other BMC interfaces.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
cmd | const | Yes | bmctest | Command Name |
name | string | Yes | Name to uniquely identify the teststep. This name will show up in reports, logs and the WebUI | |
options | OptionsObject | No | Additional command options | |
parameters | BMCTestOptions | Yes | Options passed into the bmctest cmd |
BMCTest Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
command | string | Yes | bmc-test-go subcommand to execute: single, suite, all, run-from-cfg | |
config_path | string | Yes | Path to the YAML configuration file containing BMC device details | |
test_name | string | Conditional (required for single) | Specific test to run (only used when command is single) | |
suite_name | string | Conditional (required for suite) | Test suite to run: redfish, ipmi, ifaces, ipmi-mct, ipmi-twitter, pci | |
log_mode | string | No | structured | Logging format: default or structured |
log_file | string | No | /tmp/bmc-test-output.json | Path for structured log output (only used when log_mode is structured) |
BMCTest Command Details
single: Run a specific test by name (requirestest_name)suite: Run a test suite (requiressuite_name)all: Run all available testsrun-from-cfg: Run tests defined in the configuration file
BMCTest Examples
Run a complete test suite:
Run a single test:
Run all tests with custom log location:
Run a suite with environment variables (e.g. for configs that reference $IMAGE or $GOLDEN_IMAGE):
Redfish
Run DMTF Redfish conformance testing against a BMC. Wraps the DMTF reference validators — Redfish-Service-Validator (schema, DSP8010), Redfish-Interop-Validator (profiles), and Redfish-Protocol-Validator (protocol behavior, DSP0266) — and adds a native inventory engine for board-specific value checks the validators do not perform. The validators run on the contest runner and connect to the BMC over HTTPS; their full reports (HTML/XLSX/TSV) are attached as downloadable artifacts while a per-check summary is folded into the step log.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
cmd | const | Yes | redfish | Command Name |
name | string | Yes | Name to uniquely identify the teststep. This name will show up in reports, logs and the WebUI | |
transport | TransportObject | No | local | Where the validator process runs — defaults to local (the runner). See Transport. The BMC connection itself is always HTTPS. |
options | OptionsObject | No | Additional command options | |
parameters | RedfishOptions | Yes | Options passed into the redfish cmd |
Quick start
Run the schema validator against a BMC:
Check a few board values with the native inventory engine. Most rules are four fields — a target, a property, a comparison, a value:
That covers most needs. The full inventory rule reference adds counts, ranges, per-component checks (forEach), multi-hop navigation (via), and composition (all/any) — reach for them only when a simple rule can’t express what you want.
Run the interop validator against a profile carried inline (no profile file needs to be staged on the runner):
Alternatively set interop.profile to the path of a profile JSON already on the runner.
Redfish Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
host | string | Yes | BMC host (and optional :port) of the Redfish service, without scheme. HTTPS is assumed. | |
auth | AuthObject | Yes | Redfish HTTP credentials the validators authenticate with against the BMC. | |
validate | string or []string | Yes | Engine(s) to run: service, interop, protocol, inventory. A single string or an array. | |
fatal | string | No | must | Severity that fails the step: must (only MUST-level fails), recommended (MUST+RECOMMENDED), or all (any fail/warn). |
insecure | boolean | No | true | Skip TLS certificate verification (lab BMCs use self-signed certs). Enforced by the inventory and protocol engines; the service/interop validators always connect leniently. |
service | EngineOptions | No | Options for the schema-conformance engine (Redfish-Service-Validator). | |
interop | EngineOptions | No | Options for the profile engine (Redfish-Interop-Validator). profile or profileDoc is required when interop is selected. | |
protocol | EngineOptions | No | Options for the protocol engine (Redfish-Protocol-Validator). | |
inventory | InventoryOptions | No | Native board-specific value checks. |
Select one engine per step (with options.on-error: continue) to get an independent pass/fail per engine instead of one merged verdict.
Security
- TLS verification is off by default (
insecure: true) because lab BMCs ship self-signed certificates. Setinsecure: falsefor any non-lab/production target. Note the wrapped service/interop validators always connect leniently regardless, so rely on the native inventory and protocol engines when strict TLS matters. - The BMC password is passed to the DMTF validators as a command-line argument, so it is briefly visible in the runner host’s process list (
ps,/proc/<pid>/cmdline) while a validator runs. It is redacted from the step log. This is acceptable for lab BMCs with shared credentials; do not use credentials you would not want visible to anything with process-list access on the runner.
Transport
transport is optional and defaults to local — the validators run on the contest runner (where the DMTF tools are installed) and reach the BMC over HTTPS. Omit it for almost every deployment.
Use transport: { proto: ssh, options: { ... } } to run the validator processes on a remote SSH host instead. The cases where you need it:
- The BMC is reachable only from a jump host / bastion, not from the contest runner — a segmented or air-gapped management network. Run the validators on a host that can actually reach the BMC.
- The DMTF validators live on a different machine (an on-prem appliance or pre-provisioned host with BMC access) rather than in the runner image.
For ssh the target must have the DMTF validators on PATH (rf_service_validator, rf_interop_validator, rf_protocol_validator), and the runner needs SSH access to it (set under transport.options).
Caveat: only the
service,interop, andprotocolengines run over the transport. The nativeinventoryengine is an HTTPS client that always runs on the runner, sosshdoes not change where its requests originate — if the BMC is unreachable from the runner, keepinventoryoff ssh-only targets.
Redfish Auth Options
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
user | string | Yes | Redfish username. | |
password | string | Yes | Redfish password. | |
mode | string | No | basic | basic sends credentials on every request; session creates a SessionService token, reuses it, and logs out at the end. |
Redfish Engine Options
The service, interop, and protocol sub-blocks tune the wrapped DMTF validators. All accept extraArgs, an array of raw passthrough flags to the underlying tool.
| Attribute | Applies to | Type | Required | Description |
|---|---|---|---|---|
scope | service | string | No | Path to crawl as a subtree (--payload Tree); empty crawls the whole tree. For single-resource validation use extraArgs: ["--payload", "Single", "<uri>"]. |
oemCheck | service | boolean | No | Validate OEM subtrees (omit to use the tool default). |
profile | interop | string | One of profile/profileDoc | Path to an interop profile JSON already present on the runner. Use this or profileDoc. |
profileDoc | interop | object | One of profile/profileDoc | A DMTF interoperability profile inline in the test config. It is written to a temp file and validated offline, so no profile file needs to be staged on the runner. Use this or profile. |
extraArgs | all | []string | No | Raw passthrough flags to the validator. |
Redfish Inventory Options
The native engine fetches resources directly and checks board-specific values. Rules come from inline rules and/or an expected file.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
rules | []InventoryRule | No | Inline value-match rules. | |
expected | string | No | Path to a YAML/JSON file of rules (a bare list or a {rules: [...]} object). |
Inventory Rule
Each rule names a target (where to look), a value source (what to read), and a comparison (op + value).
| Attribute | Type | Required | Description |
|---|---|---|---|
path | string | Target (one of) | Resource URI, e.g. /redfish/v1/Systems/system. |
chassis | string | Target (one of) | Glob selecting a chassis member by @odata.id, e.g. *S8047*. |
via | []string | No | Follow these single-resource link names from the base before the check (multi-hop targets, e.g. chassis → Power → PowerSupplies). Each segment must be an @odata.id link to a single resource, not a collection. |
prop | string | Source (one of) | Property on the target. May be slash-nested to reach into objects, e.g. Status/Health. |
collection | string | Source (one of) | A sub-collection link whose member count is checked (use with count/ge/le/range). |
forEach | string | Source (one of) | Iterate a collection link (members fetched individually) or an inline array of objects, applying the comparison to every member — one result each. Passes iff all members pass; an empty collection is SKIP. |
where | MemberFilter | No | forEach only: only members matching this predicate are checked; the rest are skipped (not failed). |
all | []object | Source (one of) | Composition (AND): passes iff every {prop, op, value} condition passes. Use instead of a single prop/op/value. |
any | []object | Source (one of) | Composition (OR): passes iff at least one {prop, op, value} condition passes. |
op | string | No | Comparison — see below (default eq, or exists semantics for presence). |
value | string | Depends on op | Expected value, or min..max for range. |
Comparison ops:
| op | Meaning |
|---|---|
exists | Property is present. |
eq / ne | String equality / inequality. |
matches | value is a regex matched against the property. |
contains | value is an exact element of an array property, or a substring of a scalar. |
ge / le | Numeric >= / <= (inclusive), on a collection count or a numeric property. |
range | Numeric inclusive band; value is min..max (e.g. 4..8). |
count | Collection member count equals value. |
Numeric ops parse both sides as numbers; a non-numeric operand fails the rule with a clear message rather than crashing.
Member Filter
A forEach inclusion predicate. Only members for which it holds are checked; the rest are skipped. The canonical use is ignoring empty slots, e.g. {prop: Status/State, op: ne, value: Absent}.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
prop | string | Yes | Member property to test (may be slash-nested). | |
op | string | No | eq | Predicate comparison (eq, ne, ge, le, matches, exists, contains). |
value | string | No | Predicate value. |
Multi-hop navigation and composition
via follows a chain of single-resource links from the base before the check, so a nested target works in one rule while keeping a dynamic chassis id — e.g. chassis: "*" with via: [Power] then forEach: PowerSupplies walks chassis → Power → PowerSupplies.
all / any replace a single prop/op/value with condition groups, evaluated against the target (or against each member under forEach). With both set, the rule passes iff every all condition passes and at least one any condition passes.
Note: The inventory rule grammar is complete and frozen — the fields above cover the intended use cases. Genuinely new needs are better met by a scripted check than by growing this mini-language further.
Redfish Examples
Schema conformance (full tree crawl):
Inventory with fleet-aware checks — counts, per-member (forEach / where / range), multi-hop (via), and composition (all / any):