IPMI

Read one IPMI value from a BMC and check it, or write one. A step names what it reads with get (a sensor, a FRU field, a SEL entry, or a field of a decoded IPMI command), writes a value with set, sends request bytes with raw, or captures the host console with sol, and states what it expects with expect, the same way Shell pairs command with expect. The step runs ipmitool, in-band on the transport target or over lanplus, and reports each check with the value it found.

AttributeTypeRequiredDefaultDescription
cmdconstYesipmiCommand Name
namestringYesName to uniquely identify the teststep. This name will show up in reports, logs and the WebUI
transportTransportObjectNolocalWhere ipmitool runs. See IPMI Transport.
optionsOptionsObjectNoAdditional command options. The default timeout is 2 minutes.
parametersIPMIOptionsYesOptions passed into the ipmi cmd

IPMI Quick start

Check a sensor reading, running ipmitool on the BMC itself:

- cmd: ipmi
  name: P3V3 within 10% of nominal
  parameters:
    get: sdr/P3V3/reading
    expect: { range: 2.97..3.63 }
  transport:
    proto: ssh
    options:
      host: "[[attributes.BMC]]"
      user: root

Check the watchdog over lanplus from the runner:

- cmd: ipmi
  name: Initial watchdog countdown is 300 seconds
  parameters:
    lan:
      host: "[[attributes.BMC]]"
      user: root
      password: "[[attributes.BMCPassword]]"
      cipher: 17
    get: watchdog/initial-countdown
    expect: { eq: 300s }

Each step reads one thing. To check several values, use several steps; a failure then names exactly what broke.

IPMI Options

Exactly one of get, set, raw and sol is required.

AttributeTypeRequiredDefaultDescription
getstringConditionalWhat to read. See IPMI Paths.
setstringConditionalWhat to write, with value. See IPMI Set.
valuescalar or mapWith setThe value set writes: a name or its number, such as cycle or 0x02, or the fields of a command that carries several.
rawstringConditionalRequest bytes as they would follow ipmitool raw: netfn, cmd, then data. See IPMI Raw Commands.
solSolObjectConditionalCapture the host console over Serial over LAN. Needs lan. See IPMI SOL.
expectExpectation or listYesWhat the value must satisfy. A list is checked against the same value or response.
wheremapNoNarrows a wildcard get to records whose fields match, such as { type: threshold }. A value matches as eq; a map with one operator filters by it. See Checking every sensor or FRU.
exclude[]stringNoSensor names, FRU ids or SEL record ids a wildcard get leaves out.
retry{timeout, interval}NoRead again every interval (default 2s) until every expectation passes or timeout ends. See IPMI Retry.
variablestringNoStore the value read for later steps as {{ NAME }}. See IPMI Variables.
lanLanObjectNoReach the BMC over lanplus. Without it, ipmitool runs in-band on the transport target.
placeholders[]stringNosee belowValues programmed rejects, compared ignoring case; * matches any text. Defaults to To be filled by O.E.M., Default string, Not Specified and *-NOT-FILLED.

IPMI Lan Options

AttributeTypeRequiredDescription
hoststringYesBMC host name or address
userstringNoIPMI user
passwordstringNoIPMI password. Masked in the step log.
cipherinteger or stringNolanplus cipher suite, such as 17

IPMI Paths

PathFields
sdr/<sensor>/<field>name, reading, unit, state, type, lower-non-recoverable, lower-critical, lower-non-critical, upper-non-critical, upper-critical, upper-non-recoverable, number, entity
fru/<id>/chassis/<field>type, part-number, serial, extra
fru/<id>/board/<field>mfg-date, manufacturer, product, serial, part-number, fru-id, extra
fru/<id>/product/<field>manufacturer, name, part-number, version, serial, asset-tag, fru-id, extra
sel/<id>/<field>id, time, sensor-type, sensor, event, direction, detail

Sensor names and FRU ids are used exactly as the BMC reports them. A sensor name may contain spaces or /.

sdr reads ipmitool -c sensor, and also ipmitool sdr elist for the sensor number (0x98), the entity (10.1) and the states of discrete sensors. fru reads ipmitool fru print, and a SEL entry ipmitool sel elist. Every other path sends one IPMI command; see IPMI Commands.

For a discrete sensor, state lists the asserted states as ipmitool sdr elist names them, comma-separated: Presence detected, Power Supply AC lost. The step runs sdr elist only when it reads or filters on number, entity or the state of a discrete sensor. A sensor keeps its hex bitmap (0x0080) when elist names no state, for example for an OEM sensor type. ipmitool cuts names to 16 characters, so two sensors can share a name; they pair with the elist rows of that name in SDR order.

- cmd: ipmi
  name: PSU0 reports AC lost
  parameters:
    get: sdr/PSU0_Status/state
    expect: { contains: AC lost }

Values are normalized:

  • Enumerations are lowercase: on, hard-reset, sms-os, always-off.
  • Booleans are true or false.
  • Durations carry a unit: 300s, 120.5s.
  • Timestamps are RFC 3339 in UTC. The SEL’s “never” reads as unspecified, and time counted from BMC start as pre-init <n>s.
  • A threshold sensor’s state is ipmitool’s status: ok, nc, cr, nr or na. A discrete sensor’s state is its list of asserted states, or a hex bitmap (see above).
  • guid is the 16 bytes of Get System GUID, which IPMI sends least significant first, as an RFC 4122 string.
  • A list is comma-separated, such as ipmi,sol, or none.

A field the BMC does not report is absent. exists and programmed also treat an empty FRU field as absent, whether ipmitool omits it or prints it blank.

IPMI Commands

These paths send the IPMI command raw and decode the reply from the IPMI 2.0 and DCMI 1.5 specifications, so they do not depend on ipmitool’s text output. <channel> takes 0 to 15, <payload> takes ipmi, sol, oem-explicit or a number, and every number in a path may be decimal or hex (channel/0x0f/protocol).

PathFieldsCommand
device/<field>device-id, device-revision, provides-sdrs, available, firmware-revision, ipmi-version, supports, manufacturer-id, product-idGet Device ID
guidGet System GUID
device-guidGet Device GUID
self-test (passed, not-implemented, device-error, fatal-hardware-error), self-test-errorsGet Self Test Results
acpi-system (s0 to s5, s4-s5, g3, sleeping, g1-sleeping, override, legacy-on, legacy-off, unknown), acpi-device (d0 to d3, unknown)Get ACPI Power State
watchdog/<field>timer-use, running, logging, timeout-action, pre-timeout-interrupt, pre-timeout-interval, expired, initial-countdown, present-countdownGet Watchdog Timer
channel/<channel>/<field>number, medium, protocol, sessions, active-sessions, vendor-idGet Channel Info
access-mode, alerting, privilege-limit, as in effectGet Channel Access
payloads, session-payloads, oem-payloadsGet Channel Payload Support
cipher-suites: every suite ID, such as 3,17Get Channel Cipher Suites
channel/<channel>/auth/<field>auth-types, logins, user-level-auth, per-message-auth, kg-set, ipmi-v15, ipmi-v20, oem-idGet Channel Authentication Capabilities
channel/<channel>/payload/<payload>/versionversionGet Channel Payload Version
payload/<payload>/<field>capacity, active instancesGet Payload Activation Status
session/<field>privilege of the session the step runs inSet Session Privilege Level, without a change
handle, slots, active, user, channelGet Session Info
system-info/<field>set-in-progress, firmware-version, system-name, primary-os-name, os-name, os-version, bmc-url, hypervisor-urlGet System Info Parameters
user/<id>/<field>nameGet User Name
privilege, messaging, link-auth, callback-only, enabled, on channel 1Get User Access
users/<field>max, enabled and fixed-names user IDs, on channel 1Get User Access
chassis/<field>power, power-overload, interlock, power-fault, power-control-fault, power-restore-policy, last-power-event, intrusion, front-panel-lockout, drive-fault, cooling-fault, identifyGet Chassis Status
minutes-per-count, power-on-hoursGet POH Counter
restart-cause, restart-channelGet System Restart Cause
boot/<field>set-in-progressGet System Boot Options, parameter 0
valid, persistent, type (legacy, efi), cmos-clear, lock-keyboard, device, screen-blank, lock-reset-button, lock-power-button, verbosity, progress-traps, password-bypass, lock-sleep-button, console-redirection, bios-shared-mode, bios-mux, device-instanceGet System Boot Options, parameter 5: the boot flags
fru/<id>/<field>size in bytes, access (byte or word)Get FRU Inventory Area Info
fru/<id>/header/<field>version, internal-offset, chassis-offset, board-offset, product-offset, multirecord-offset (bytes, 0 when the area is absent), checksum-okRead FRU Data, the common header
fru/<id>/byte/<offset>the byte at the offsetRead FRU Data
sdr/<field>version, records, free-bytes, last-add, last-erase, overflow, update-modes, supportsGet SDR Repository Info
reservationReserve SDR Repository
timeGet SDR Repository Time
sdr-record/<id>/<field>next, id, version, type, length; record 0 is the firstGet SDR
device-sdr/<field>sdrs, dynamicGet Device SDR Info, SDR count
sensorsGet Device SDR Info, sensor count
reservationReserve Device SDR Repository
sel/<field>version, entries, free-bytes, last-add, last-erase, overflow, supportsGet SEL Info
timeGet SEL Time
reservationReserve SEL
lan/<channel>/<field>set-in-progress, ip, ip-source, mac, netmask, gateway, gateway-mac, backup-gateway, backup-gateway-mac, community, vlan (off or the ID), vlan-priorityGet LAN Configuration Parameters
sol/<channel>/<field>set-in-progress, enabled, force-encryption, force-authentication, privilege, accumulate-interval, send-threshold, retry-count, retry-interval, bit-rate, volatile-bit-rate, payload-channel, portGet SOL Configuration Parameters
dcmi/<field>version, sel-entriesGet DCMI Capabilities Info, platform attributes
controller-idGet Management Controller Identifier String
asset-tagGet Asset Tag
dcmi/power/<field>current, minimum, maximum, average, period, activeDCMI Get Power Reading

The step log lists every field of the reply under the raw bytes, with ✗ before the field the step read when its check failed, and with the code of a named value: privilege administrator (0x04). A reply that spans several requests, such as the cipher suites or a DCMI string, is read to its end.

A named value, a boolean and a list also have their raw value, the code. A number in a check compares with the code, written in decimal or hex, so each pair below is the same check:

expect: { eq: administrator }              # expect: { eq: 0x04 }
expect: { eq: true }                       # expect: { eq: 1 }
expect: { matches: '^(static|dhcp)$' }     # expect: { range: 1..2 }

When the text of a field is a number itself, such as the bit rate 115200, a number compares with the text. contains on a list looks for one item, so contains: 17 matches 3,17 but not 117.

These paths can check the completion code like raw, so a refused request reads as what it is. Without a completion check, a non-zero completion code fails the step.

- cmd: ipmi
  name: Unknown FRU ID 0xff is rejected
  parameters:
    get: fru/0xff/size
    expect: { completion: 0xcc }

SEL entries

sel/<id>/<field> reads one entry of the event log, by record id (0x1a or 26), last for the newest one, or * for every entry. sel/<field> stays the log’s own information (version, entries, time).

FieldExample
id0x1a
time2026-10-14T09:02:41Z; pre-init, a time since BMC start (S+ 00:01:23) or a time in another zone stays as ipmitool prints it
sensor-typePower Supply
sensorPSU0_Status, or #0x98 when the BMC has no SDR for it
eventPower Supply AC lost
directionasserted or deasserted
detailReading 95 > Threshold 90 degrees C
- cmd: ipmi
  name: The SEL logged PSU0 losing AC
  parameters:
    get: sel/*/event
    where: { sensor: PSU0_Status, direction: asserted }
    expect: { contains: AC lost }

Checking every sensor or FRU

* in place of a sensor name or FRU id checks every one. where narrows the set by other fields of the same record:

- cmd: ipmi
  name: No threshold sensor is outside its limits
  parameters:
    get: sdr/*/state
    where: { type: threshold }
    expect: { eq: ok }
  transport:
    proto: ssh
    options:
      host: "[[attributes.BMC]]"
      user: root

The report counts passes and names each member that failed:

✗ sdr/*/state where type=threshold eq ok: 37/39
  ✗ PSU0_Status: "cr"
  ✗ PSU1_Status: "na"

A wildcard that matches nothing fails the step, because it checked nothing, unless a count expectation allows zero.

A plain where value matches as eq does. A map with one operator filters by eq, ne, ge, le, range, matches or contains. name filters sdr by sensor name, and id filters fru by device id (for fru, name stays the product name field). A record without the field never matches a condition, and a regular expression is checked when the step is validated:

    get: sdr/*/reading
    where:
      name: { matches: '^PSU[0-9]_' }
      type: threshold
    expect: { ge: 0 }

count checks how many records the wildcard matched, after where and exclude. It can stand alone or next to checks on each record, and a failed count names the records it found (up to ten):

- cmd: ipmi
  name: Both PSU status sensors are reported and healthy
  parameters:
    get: sdr/*/state
    where: { name: { matches: '^PSU[01]_Status$' } }
    expect:
      - { count: 2 }
      - { ne: cr }

distinct checks that no two matched records hold the same non-empty value and names the records that share one, for example get: sdr/*/number with expect: distinct. sum adds up the field over the matched records and compares the total; a record without a number fails the sum and is named. With a variable, the DCMI power reading checks the PSU power:

- cmd: ipmi
  name: Record the DCMI power reading
  parameters:
    get: dcmi/power/current
    expect: { ge: 1 }
    variable: DCMI_W

- cmd: ipmi
  name: PSU output power adds up to the DCMI reading
  parameters:
    get: sdr/*/reading
    where: { name: { matches: '^PSU[01]_Out_Power$' } }
    expect: { sum: { range: "{{ DCMI_W }}±15%" } }

exclude leaves named sensors or FRU ids out of a wildcard, for example a sensor for a fan that is not populated on this board:

    get: sdr/*/state
    where: { type: threshold }
    exclude: [FAN5, FAN6]
    expect: { ne: cr }

The report header names the exclusions. An excluded name the BMC does not report is listed as “excluded but not reported by the BMC”, so a stale entry is visible after a rename. SEL entries are excluded by record id in the forms get takes, 0x1a or 26.

IPMI Expectations

An expectation is one operator and its value, written as a map, or one of four bare words. The operator names match the Redfish inventory rules.

OperatorPasses when the value
eq, neequals or differs. Durations compare as durations (5m equals 300s), numbers as numbers (0x0f equals 15), anything else as text.
ge, leis at least or at most this number or duration
rangelies within min..max, inclusive, or within a tolerance around a centre: 450±10%, 12±0.6 (+- works as ±). The report shows the bounds: range 450±10% (405..495).
matchesmatches the regular expression
containscontains the text; on a list, such as cipher-suites, holds the item
withinis a timestamp no further than this duration from the runner’s clock, such as { within: 1m } for sel/time
completionraw, set and the IPMI Commands of get: the completion code equals this value
countwildcard get only: the number of matched records equals a whole number, or compares with eq, ne, ge, le or range (count: { ge: 1 })
sumwildcard get only: the total of the matched records’ values compares like count does (sum: { range: 450±10% })
existsbare word: the field is present and non-empty
programmedbare word: the field is present, non-empty and not a placeholder
distinctbare word, wildcard get only: no two matched records hold the same non-empty value
refusedbare word, with lan only and the only expectation of its step: the BMC answers but refuses the session. See IPMI Refused Sessions.

More than one operator in one expectation is an error. To check a value from both sides, use range or a list:

expect:
  - { ge: 1 }
  - { le: 500 }

IPMI Set

set writes value to a path, as ipmitool raw would send it, and checks the completion code like raw. A value is a name or its number, decimal or hex, wherever the field reads as a name: value: cycle and value: 0x02 send the same request. A command that carries several fields takes them as a map.

PathvalueCommand
chassis/poweroff, on, cycle, reset, diag or softChassis Control
chassis/power-restore-policyalways-off, previous, always-on, or no-change to only read the supported policiesSet Power Restore Policy
chassis/identifyoff, on until turned off, or seconds (15s or 15)Chassis Identify
boot/set-in-progresscomplete, in-progress or commit-writeSet System Boot Options, parameter 0
boot/flagsthe fields of boot/<field>; valid is true unless givenSet System Boot Options, parameter 5
device/resetcold or warmCold Reset or Warm Reset of the BMC
watchdogreset, off, or the fields of watchdog/<field>, with timer-use and with clear for the expiration flags to clearReset Watchdog Timer, Set Watchdog Timer
session/privilegea privilege levelSet Session Privilege Level
user/<id>/nameup to 16 ASCII characters; "" deletes the user on OpenBMCSet User Name
user/<id>/passwordup to 20 ASCII characters, masked in the step logSet User Password, set
user/<id>/password-testthe password to test: 0x00 matches, 0x80 does notSet User Password, test
user/<id>/enabledtrue or falseSet User Password, enable or disable
user/<id>/privilegeas get reads it; on channel 1 it also turns IPMI messaging on and link auth and callback-only offSet User Access
sel/timean RFC 3339 time or seconds since 1970Set SEL Time
sel/entrysensor-type, sensor and event-type (threshold, sensor-specific or a number); optional direction, event-data (up to 3 bytes; 0x00 and the rest 0xff, unspecified), generator (0x20), evm-revision (0x04), record-type (system-event), timestampAdd SEL Entry
lan/<channel>/<field>as get reads it: set-in-progress, ip, ip-source, mac, netmask, gateway, gateway-mac, backup-gateway, backup-gateway-mac, vlan (off or an ID), vlan-prioritySet LAN Configuration Parameters
sol/<channel>/<field>as get reads it: set-in-progress, enabled, bit-rate, volatile-bit-rate, payload-channel, portSet SOL Configuration Parameters

watchdog: off sends what ipmitool mc watchdog off sends: SMS/OS use, no action, its expiration flag cleared, 300 s. A SOL field that shares its parameter with others, such as privilege, is written with raw.

- cmd: ipmi
  name: The next boot goes to PXE in EFI mode
  parameters:
    set: boot/flags
    value: { device: pxe, type: efi }
    expect: { completion: 0x00 }

- cmd: ipmi
  name: The SEL takes a physical security event
  parameters:
    set: sel/entry
    value: { sensor-type: physical-security, sensor: 1, event-type: sensor-specific, event-data: 0x00 0xff 0xff }
    expect: { completion: 0x00 }

IPMI Raw Commands

raw sends request bytes exactly as they would follow ipmitool raw, for any request, also one that get or set names, for example with a wrong length on purpose. Expectations then check the completion code or the response data:

AttributeTypeDefaultDescription
completioninteger or stringThe completion code equals this value. 0x00 is success, 0xc1 is Invalid Command.
byteintegerOffset of the first data byte to check. 0 is the first byte after the completion code.
leninteger1Number of bytes read as one little-endian value, up to 8
maskinteger or stringBit mask applied before comparing

A byte check takes eq, ne, ge, le or range.

- cmd: ipmi
  name: SEL info rejects an extra byte
  parameters:
    raw: 0x0a 0x40 0x00
    expect: { completion: 0xc7 }

- cmd: ipmi
  name: Reserve SDR Repository returns a reservation
  parameters:
    raw: 0x0a 0x22
    expect:
      - { completion: 0x00 }
      - { byte: 0, len: 2, ne: 0 }

The second step sends the command once and checks both expectations against the same response, which matters for commands such as Reserve SDR Repository that change state on every call.

When a raw command fails and no expectation checks completion, the step reports the completion code once instead of failing every byte check for the same reason.

A non-zero completion code is the BMC’s answer, not a tool failure, so the log shows it as BMC response: completion code 0xc7: Request data length invalid instead of the ipmitool error text.

IPMI SOL

sol captures the host console over Serial over LAN for duration, and can send one line. It needs lan, because ipmitool opens the SOL session over lanplus, and GNU timeout where the step runs (normally the runner):

- cmd: ipmi
  name: Host console answers at the login prompt
  parameters:
    lan: { host: "[[attributes.BMC]]", user: root, password: "[[attributes.BMCPassword]]", cipher: 17 }
    sol:
      duration: 2m
      send: uname -a
      wait: 5s
      until: "login:"
    expect:
      - { matches: '(?m)^.*login:' }
      - { contains: Linux }
AttributeTypeRequiredDescription
durationstringYesHow long the capture runs at most.
sendstringNoOne line sent after wait, ended with CR as the Enter key sends it. It must not start with ~, the SOL escape character of ipmitool.
waitstringNoDelay before send.
untilstringNoText that ends the capture early once it appears (plain text, not a regular expression).

The step first deactivates a SOL session that is still open, so a stale one does not block the capture. It removes terminal escape sequences, turns CR and CRLF into newlines, and logs the end of the console (the last 16 KiB). expect takes matches, contains and exists on the console text and names the line where it found the text; use (?m) for ^ and $ per line. retry and variable do not apply: capture longer with duration instead. Without an options timeout, the step timeout is the default plus duration; an options timeout that does not outlast duration is rejected.

IPMI Refused Sessions

expect: refused passes when the BMC answers and turns the lanplus session down: an unknown user, a wrong password, a cipher suite or a privilege level it does not accept. ipmitool runs with -v, which prints the reason, and the report names it. A BMC that does not answer at all is not a refusal and fails the step, so a switched-off BMC cannot pass a security check:

- cmd: ipmi
  name: A wrong password is refused
  parameters:
    lan: { host: "[[attributes.BMC]]", user: root, password: not-the-password, cipher: 17 }
    get: device/device-id
    expect: refused

- cmd: ipmi
  name: Cipher suite 0 (no authentication) is refused
  parameters:
    lan: { host: "[[attributes.BMC]]", user: root, password: "[[attributes.BMCPassword]]", cipher: 0 }
    raw: 0x06 0x01
    expect: refused

A session that opens fails the check, also when only the command is then rejected with a completion code; check that with completion.

IPMI Retry

retry repeats the read and every expectation until they all pass or timeout ends, every interval (default 2s). It applies to get and raw, and it also covers a BMC that does not answer yet, for example while it reboots:

- cmd: ipmi
  name: One PSU reports AC lost
  parameters:
    get: sdr/*/state
    where: { type: discrete, state: { contains: AC lost } }
    expect: { count: 1 }
    retry: { timeout: 1m, interval: 5s }
  transport:
    proto: ssh
    options:
      host: "[[attributes.BMC]]"
      user: root

The log shows the last attempt in full, then how the retry ended (passed on attempt 4 after 6s, or still failing after 31 attempts in 1m0s) and one line per earlier failed attempt, with repeats of the same failure merged: attempts 1 to 3 at +0s to +4s: ✗ eq on got "off". When the step needs discrete states, every attempt runs sdr elist again, so a state that changes is seen.

Without an options timeout, the step timeout is the default of 2 minutes plus the retry timeout. An options timeout shorter than the retry timeout is rejected when the step is validated.

IPMI Variables

variable: NAME stores the value a single get read, or the data bytes of a successful raw command as hex without spaces (3412ab), for later steps as {{ NAME }}:

- cmd: ipmi
  name: Record the firmware revision
  parameters:
    get: device/firmware-revision
    expect: exists
    variable: FW_REV

The value is stored even when an expectation fails, because it is what the BMC reported. Nothing is stored when no value was read. A wildcard get stores the number of records it matched, after where and exclude. With retry, the value of the last attempt is stored. Stored values keep only A-Z a-z 0-9 / _ . : + -; when that drops characters (the space in degrees C), the log says so next to the stored value.

IPMI Transport

transport is optional and defaults to local.

  • With lan, ipmitool connects over lanplus (-I lanplus -H -U -P -C) from wherever the step runs. With the default transport, that is the contest runner, which needs network access to the BMC’s IPMI port (UDP 623).
  • Without lan, ipmitool runs in-band on the transport target. Use an ssh transport to the BMC itself; this works whether or not the BMC’s IPMI LAN channel is enabled.
  • sol always needs lan, and GNU timeout on the host that runs ipmitool.

IPMI Security

  • The lan password is passed to ipmitool as a command-line argument, so it is briefly visible in the process list (ps, /proc/<pid>/cmdline) of the host that runs ipmitool while the step runs. It is masked in the step log. This is acceptable for lab BMCs with shared credentials.
  • In-band checks over ssh send no IPMI credentials at all.