This repository contains the software responsible for tracking and controlling the state of different objects within OpenBMC. This currently includes the BMC, Chassis, Host, and Hypervisor. The most critical feature of phosphor-state-manager (PSM) software is its support for requests to power on and off the system by the user.
This software also enforces any restore policy (i.e. auto power on system after a system power event or bmc reset) and ensures its states are updated correctly in situations where the BMC is rebooted and the chassis or host are in on/running states.
This repository also provides a command line tool, obmcutil, which provides basic command line support to query and control phosphor-state-manager applications running within an OpenBMC system. This tool itself runs within an OpenBMC system and utilizes D-Bus APIs. These D-Bus APIs are used for development and debug and are not intended for end users.
As with all OpenBMC applications, interfaces and properties within phosphor-state-manager are D-Bus interfaces. These interfaces are then used by external interface protocols, such as Redfish and IPMI, to report and control state to/by the end user.
phosphor-state-manager makes extensive use of systemd. There is a writeup with an overview of systemd and its use by OpenBMC.
phosphor-state-manager monitors for systemd targets to complete as a trigger to updating the its corresponding D-Bus property. When using PSM, a user must ensure all generic services installed within the PSM targets complete successfully in order to have PSM properly report states.
phosphor-state-manager follows some basics design guidelines in its implementation and use of systemd:
- Keep the different objects as independent as possible (host, chassis, bmc)
- Use systemd targets for everything and keep the code within PSM minimal
- Ensure it can support required external interfaces, but don't necessarily create 1x1 mappings otherwise every external interface will end up with its own special chassis or host state request
- If something like a hard power off can be done by just turning off the chassis, don't provide a command in the host to do the same thing
phosphor-state-manager implements states and state requests as defined in phosphor-dbus-interfaces for each object it supports.
- bmc: The BMC has very minimal states. It is
NotReadywhen first started andReadyonce all services within the default.target have executed. It isQuiescedwhen a critical service has entered the failed state. The only state change request you can make of the BMC is for it to reboot itself.- CurrentBMCState: NotReady, Ready, Quiesced
- RequestedBMCTransition: Reboot
- Monitored systemd targets: multi-user.target and obmc-bmc-service-quiesce@.target
- chassis: The chassis represents the physical hardware in which the system
is contained. It usually has the power supplies, fans, and other hardware
associated with it. It can be either
On,Off, or in a fail state. ABrownOutstate indicates there is not enough chassis power to fully power on andUninterruptiblePowerSupplyindicates the chassis is running on a UPS.- CurrentPowerState: On, Off, BrownOut, UninterruptiblePowerSupply
- RequestedPowerTransition: On, Off, PowerCycle
- Monitored systemd targets: obmc-chassis-poweron@.target, obmc-chassis-poweroff@.target
- host: The host represents the software running on the system. In most
cases this is an operating system of some sort. The host can be
Off,Running,TransitioningToRunning,TransitioningToOff,Quiesced(error condition), or inDiagnosticMode(collecting diagnostic data for a failure)- CurrentHostState: Off, Running, TransitioningToRunning, TransitioningToOff, Quiesced, DiagnosticMode
- RequestedHostTransition: Off, On, Reboot, GracefulWarmReboot, ForceWarmReboot
- Monitored systemd targets: obmc-host-startmin@.target, obmc-host-stop@.target, obmc-host-quiesce@.target, obmc-host-diagnostic-mode@.target
- hypervisor: The hypervisor is an optional package systems can install
which tracks the state of the hypervisor on the system. This state manager
object implements a limited subset of the host D-Bus interface.
- CurrentHostState: Standby, TransitionToRunning, Running, Off, Quiesced
- RequestedHostTransition: On
As noted above, PSM provides a command line tool, obmcutil, which takes a
state parameter. This will use D-Bus commands to retrieve the above states and
present them to the user. It also provides other commands which will send the
appropriate D-Bus commands to the above properties to power on/off the chassis
and host (see obmcutil --help within an OpenBMC system).
The above objects also implement other D-Bus objects like power on hours, boot progress, reboot attempts, and operating system status. These D-Bus objects are also defined out in the phosphor-dbus-interfaces repository.
The RestorePolicy defines the behavior the user wants when the BMC is
reset. If the chassis or host is on/running then this service will not run. If
they are off then the RestorePolicy will be read and executed by PSM code.
The PowerRestoreDelay property within the interface defines a maximum time the
service will wait for the BMC to enter the Ready state before issuing the
power on request, this allows host to be powered on as early as the BMC is
ready.
There is an optional only-allow-boot-when-bmc-ready feature which can be
enabled within PSM that will not allow chassis or host operations (other then
Off requests) if the BMC is not in a Ready state. Care should be taken to
ensure PowerRestoreDelay is set to a suitable value to ensure the BMC reaches
Ready before the power restore function requests the power on.
In situations where the BMC is reset and the chassis and host are on and running, its critical that the BMC software do two things:
- Never impact the state of the system (causing a power off of a running system is very bad)
- Ensure the BMC, Chassis, and Host states accurately represent the state of the system.
Note that some of this logic is provided via service files in system-specific meta layers. That is because the logic to determine if the chassis is on or if the host is running can vary from system to system. The requirement to create the files defined below and ensure the common targets go active is a must for anyone wishing to enable this feature.
phosphor-state-manager discovers state vs. trying to cache and save states. This
ensure it's always getting the most accurate state information. It discovers the
chassis state by checking the pgood value from the power application. If it
determines that power is on then it will do the following:
- Create a file called /run/openbmc/chassis@0-on
- The presence of this file tells the services to alter their behavior because the chassis is already powered on
- Start the obmc-chassis-poweron@0.target
- The majority of services in this target will "fake start" due to the file
being present. They will report to systemd that they started and ran
successfully but they actually do nothing. This is what you would want in
this case. Power is already on so you don't want to run the services to turn
power on. You do want to get the obmc-chassis-poweron@0.target in the
Active state though so that the chassis object within PSM will correctly
report that the chassis is
On
- The majority of services in this target will "fake start" due to the file
being present. They will report to systemd that they started and ran
successfully but they actually do nothing. This is what you would want in
this case. Power is already on so you don't want to run the services to turn
power on. You do want to get the obmc-chassis-poweron@0.target in the
Active state though so that the chassis object within PSM will correctly
report that the chassis is
- Start a service to check if the host is on
The chassis@0-on file is removed once the obmc-chassis-poweron@0.target becomes active (i.e. all service have been successfully started which are wanted or required by this target).
The logic to check if the host is on sends a command to the host, and if a response is received then similar logic to chassis is done:
- Create a file called /run/openbmc/host@0-on
- Start the obmc-host-start@0.target
- Similar to above, most services will not run due to the file being created and their service files implementing a "ConditionPathExists=!/run/openbmc/host@0-request"
The host@0-on file is removed once the obmc-host-start@0.target and obmc-host-startmin@0.target become active (i.e. all service have been successfully started which are wanted or required by these targets).
phosphor-state-manager supports an optional multi-chassis SMP feature for systems with multiple chassis instances that need to be managed as a single logical unit. This is useful in systems where multiple compute nodes or chassis work together in a symmetric multi-processor configuration.
When the multi-chassis SMP feature is enabled, chassis instance 0 acts as an aggregator that monitors and controls chassis instances 1 through N. The aggregator does not monitor any local chassis 0 hardware; instead, it aggregates state information from the other chassis instances and presents a unified view.
- Event-Driven Monitoring: Uses D-Bus property change signals to monitor all chassis instances in real-time (no polling overhead)
- Power State Aggregation: Chassis 0 reports
Ononly when all chassis selected for power on have successfully powered on. It reportsOffwhen all chassis selected for power off have successfully powered off. Chassis not selected for power operations (e.g., due to hardware isolation, missing hardware, or bad power status) are not included in the aggregation. - Power Status Aggregation: Reports worst-case power status across all chassis (BrownOut > UninterruptiblePowerSupply > Good). Note that a degraded power status does not prevent power on operations; chassis with good power status can still be powered on while chassis with bad power status are excluded from the power on operation.
- Coordinated Power Control: Power transition requests are forwarded to all chassis instances, and the systemd target for chassis 0 is also triggered. This allows users who have any global service to run on all power on or off's to put them in the instance 0 obmc-chassis-power(off/on) targets.
The feature is enabled by default in CI but disabled by default within the bitbake recipe.
Configuration options:
multi-chassis-smp: Enable/disable the feature (default: enabled)num-chassis-smp: Maximum number of chassis instances to aggregate, 1-N (default: 12)
Start the chassis state manager instances:
# Chassis 0 (aggregator) - monitors chassis 1-N, no local hardware monitoring
phosphor-chassis-state-manager --chassis 0
# Chassis 1-N (normal operation) - each monitors its own local hardware
phosphor-chassis-state-manager --chassis 1
phosphor-chassis-state-manager --chassis 2
...
phosphor-chassis-state-manager --chassis NChassis 0 presents the standard chassis D-Bus interface at:
- Bus name:
xyz.openbmc_project.State.Chassis0 - Object path:
/xyz/openbmc_project/state/chassis0
The aggregated properties include:
CurrentPowerState: Aggregated power state from all chassisCurrentPowerStatus: Worst-case power status from all chassisRequestedPowerTransition: Forwards requests to all chassis instances
When a power transition is requested on chassis 0:
- The systemd target for chassis 0 is started (e.g.,
obmc-chassis-poweron@0.target) - The transition request is forwarded to all chassis instances 1-N
- Each chassis instance processes the request independently
- Chassis 0 aggregates the resulting states from all instances
This ensures that both the aggregator and individual chassis instances maintain proper systemd target states and can execute any necessary system-specific services.
With systems that support multiple chassis, there are potential system configurations where a chassis is present in the system, but not available for general use by BMC software. For example a chassis may not have AC power plugged, or a required SMP or other cable (i2c, gpio, ...) may not be properly plugged.
In these cases there needs to be a consistent mechanism with OpenBMC firmware to know whether they can access the chassis. This new service within phosphor-state-manager will aggregate the different inputs into a single Available property in each chassis. This will be an optional feature within phosphor-state-manager that OpenBMC machine owners can enable.
The set of D-Bus properties that determine chassis availability is fully data-driven. Rather than compiling in a fixed list of interfaces and properties, the service reads a JSON configuration file at startup that declares what to monitor and what value each property must hold to consider the chassis Available.
The conditions to monitor are defined in a JSON configuration file installed to
/usr/share/phosphor-state-manager/chassis-availability/. A default config will
be installed which has a single mapping to the present property. OpenBMC
machines can override this file in the bitbake layer.
The top-level "availableObjectPath" field specifies where the Available
property is written. Like condition paths, <N> is substituted with the chassis
instance number at runtime. The owning D-Bus service is resolved via
ObjectMapper so there is no compile-time dependency on any specific inventory
implementation.
Each entry in the "conditions" array describes one D-Bus property to monitor.
The "baseObjectPath" is the object path with <N> representing the chassis
instance number (e.g. chassis1, chassis2). At startup the service
substitutes the actual chassis number for <N> and calls the ObjectMapper
GetObject method on the resulting path to determine which D-Bus service owns
that object. It then registers a PropertiesChanged signal match on that
service and object so the check re-runs whenever the property changes. The
application will monitor all chassis instances it finds on dbus and will support
chassis inventory objects showing up on dbus after it has started.
{
"availableObjectPath": "/xyz/openbmc_project/inventory/system/chassis<N>",
"conditions": [
{
"baseObjectPath": "/xyz/openbmc_project/inventory/system/chassis<N>",
"interface": "xyz.openbmc_project.Inventory.Item",
"property": "Present",
"availableValue": true
},
{
"baseObjectPath": "/xyz/openbmc_project/inventory/system/chassis<N>",
"interface": "xyz.openbmc_project.State.Decorator.PowerSystemInputs",
"property": "Status",
"availableValue": "xyz.openbmc_project.State.Decorator.PowerSystemInputs.Status.Good"
},
{
"baseObjectPath": "/xyz/openbmc_project/inventory/system/chassis<N>",
"interface": "xyz.openbmc_project.Common.Progress",
"property": "Status",
"availableValue": "xyz.openbmc_project.Common.Progress.OperationStatus.Completed"
}
]
}The "availableValue" field supports any JSON scalar type (boolean, string,
integer) and is compared directly against the value returned by
org.freedesktop.DBus.Properties.Get.
If a configured object path does not exist on D-Bus for a given chassis (i.e.
GetObject returns no results), the Available property will be false. As the
OpenBMC machine owner has complete control of this configuration file for their
machine it is assumed they expect the property be available.
The chassis is marked as Available only when ALL configured conditions are
met (each monitored property equals its configured "availableValue").
If ANY monitored property transitions away from its required value, the chassis is immediately marked as Unavailable.
The Available property (xyz.openbmc_project.State.Decorator.Availability) is
written to the object path given by "availableObjectPath" in the configuration
file, via org.freedesktop.DBus.Properties.Set. The owning service is resolved
at runtime through ObjectMapper, so there is no compile-time dependency on any
specific inventory implementation.
Decoupling the output path from the condition paths allows machines where the
Availability interface lives on a different object than the monitored
properties (e.g. a dedicated availability object rather than the chassis
inventory item) to use this service without modification.
Note that some additional processing will be required if the property is hosted
by phosphor-inventory-manager as the standard Set call is not persistent.
The availability monitor:
- Reads the JSON configuration file(s) at startup to determine which conditions to evaluate
- For each chassis instance and each condition, calls ObjectMapper
GetObjecton the configured object path to discover which D-Bus service owns it - Subscribes to
InterfacesAddedon/xyz/openbmc_project/inventoryto handle objects that appear after startup - Uses event-driven
PropertiesChangedsignals on discovered objects (no polling) - Monitors all chassis instances 1-N simultaneously
- Updates the
Availableproperty viaorg.freedesktop.DBus.Properties.Seton whichever service owns the"availableObjectPath"object for that chassis - Handles errors gracefully with appropriate logging
- Starts automatically via systemd after the D-Bus mapper is ready
- Service name:
xyz.openbmc_project.State.ChassisAvailability - Systemd unit:
xyz.openbmc_project.State.ChassisAvailability.service
To build this package, do the following steps:
meson setup buildninja -C build
To clean the repository again run rm -rf build.