saltext.bmc.utils.backend

Protocol-agnostic BMC backend dispatcher.

The public surface (power_status, do_reset, get_boot, set_boot) is identical regardless of whether the underlying transport is Redfish or IPMI. Modules and states call open_backend(), get a backend instance, and stay protocol-neutral.

Backend selection (from pillar):

saltext.bmc:
  profiles:
    bmc-host-01:
      host: 10.0.0.5
      username: root
      password: calvin
      verify_ssl: false
      backend: redfish   # or 'ipmi', or 'auto' (default)
  • auto (default) — probe Redfish first; fall back to IPMI on TLS handshake failure, connection error, or any non-Redfish HTTP response from /redfish/v1/. Handles mixed-hardware fleets out of the box.

  • redfish — Redfish only (skips the probe).

  • ipmi — IPMI only (requires pyghmi).

class saltext.bmc.utils.backend.BmcBackend[source]

Common interface implemented by Redfish and IPMI backends.

abstractmethod open() None[source]

Establish the underlying session.

abstractmethod close() None[source]

Tear down the underlying session.

abstractmethod power_status() str[source]

Return 'on', 'off', or 'unknown'.

abstractmethod do_reset(reset_type: str) dict[source]

Issue a canonical reset action.

Parameters:

reset_type – one of On, ForceOff, GracefulShutdown, PowerCycle, GracefulRestart, ForceRestart.

abstractmethod get_boot() dict[source]

Return a dict with device (friendly), enabled, native_target.

abstractmethod set_boot(device: str, persistent: bool = False) dict[source]

Set the boot override and return a normalized dict.

abstractmethod get_system_info() dict[source]

Return a normalized inventory dict with keys: manufacturer, model, serial_number, uuid, sku, host_name, bios_version, firmware_version, power_state. Any unknown field is None.

abstractmethod get_sensors() dict[source]

Return a dict {"temperatures": [...], "fans": [...], "voltages": [...]} where each list item has name, reading, unit, status. Empty lists are returned for sensor classes the backend does not expose.

class saltext.bmc.utils.backend.RedfishBackend(host: str, username: str, password: str, *, verify_ssl: bool = True, timeout: int = 30)[source]
open() None[source]

Establish the underlying session.

close() None[source]

Tear down the underlying session.

power_status() str[source]

Return 'on', 'off', or 'unknown'.

do_reset(reset_type: str) dict[source]

Issue a canonical reset action.

Parameters:

reset_type – one of On, ForceOff, GracefulShutdown, PowerCycle, GracefulRestart, ForceRestart.

get_boot() dict[source]

Return a dict with device (friendly), enabled, native_target.

set_boot(device: str, persistent: bool = False) dict[source]

Set the boot override and return a normalized dict.

get_system_info() dict[source]

Return a normalized inventory dict with keys: manufacturer, model, serial_number, uuid, sku, host_name, bios_version, firmware_version, power_state. Any unknown field is None.

get_sensors() dict[source]

Return a dict {"temperatures": [...], "fans": [...], "voltages": [...]} where each list item has name, reading, unit, status. Empty lists are returned for sensor classes the backend does not expose.

class saltext.bmc.utils.backend.IpmiBackend(host: str, username: str, password: str, *, port: int = 623, timeout: int = 30, **_unused)[source]
open() None[source]

Establish the underlying session.

close() None[source]

Tear down the underlying session.

power_status() str[source]

Return 'on', 'off', or 'unknown'.

do_reset(reset_type: str) dict[source]

Issue a canonical reset action.

Parameters:

reset_type – one of On, ForceOff, GracefulShutdown, PowerCycle, GracefulRestart, ForceRestart.

get_boot() dict[source]

Return a dict with device (friendly), enabled, native_target.

set_boot(device: str, persistent: bool = False) dict[source]

Set the boot override and return a normalized dict.

get_system_info() dict[source]

Return a normalized inventory dict with keys: manufacturer, model, serial_number, uuid, sku, host_name, bios_version, firmware_version, power_state. Any unknown field is None.

get_sensors() dict[source]

Return a dict {"temperatures": [...], "fans": [...], "voltages": [...]} where each list item has name, reading, unit, status. Empty lists are returned for sensor classes the backend does not expose.

saltext.bmc.utils.backend.open_backend(opts: dict, name: str | None = None, **overrides: Any) BmcBackend[source]

Build a context-managed BmcBackend from opts/pillar + overrides.

The returned object MUST be used as a context manager:

with open_backend(__opts__, name="bmc-host-01") as backend:
    backend.power_status()