-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Update BMC HLD with Redis communication for SONiC BMC #2453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,13 +4,30 @@ | |
| Board Management Controller (BMC) is a specialized microcontroller embedded on a motherboard. It manages the interface between system management software and hardware. BMC provides out-of-band management capabilities, allowing administrators to monitor and manage hardware remotely. | ||
| OpenBMC is an open-source project that provides a Linux-based firmware stack for Board Management Controllers (BMCs). It implements the Redfish standard, allowing for standardized and secure remote management of server hardware. In essence, OpenBMC serves as the software that runs on BMC hardware, utilizing the Redfish API to facilitate efficient hardware management. | ||
| Redfish is a standard for managing and interacting with hardware in a datacenter, designed to be simple, secure, and scalable. It works with BMC to provide a RESTful API for remote management of servers. Together, Redfish and BMC enable efficient and standardized hardware management. | ||
| In summary, NOS will deal with BMC through the redfish RESTful API. | ||
|
|
||
| In summary, when the BMC runs OpenBMC, the Switch-Host NOS interacts with the BMC through the Redfish RESTful API. | ||
|
|
||
| When the BMC runs SONiC OS, the Switch-Host NOS interacts with the BMC through Redis over the host–BMC link (`usb0`). The host connects to the Redis instance on the BMC and reads platform data. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this design needs another look. It exposes the BMCs internal OS details to every hostside consumer instead of encapsulating them behind a stable API abstraction. this way sharing implementation details across layers and tightly couples consumers(of BMC) to the BMC OS internals, which could make maintenance and future changes significantly harder. please think about it |
||
|
|
||
| The host selects the communication path at runtime based on `DEVICE_METADATA|bmc.os`. | ||
|
|
||
|
|
||
| ## 2. BMC flows in SONiC | ||
| The implementation is straightforward: SONiC will incorporate a Redfish client as the underlying infrastructure to support the BMC action. This Redfish client object is implemented and initialized at runtime by SONiC itself. | ||
|
|
||
| SONiC supports two BMC operating-system cases on the Switch-Host side: | ||
|
|
||
| | BMC OS | Transport | Client on Switch-Host | | ||
| |--------|-----------|------------------------| | ||
| | **OpenBMC** (default) | Redfish over `usb0` / `bmc_addr` | `RedfishClient` (`redfish_client.py`) | | ||
| | **SONiC** | Redis over `usb0` / `bmc_addr` | Remote STATE_DB connector (`db_connect_remote`) | | ||
|
|
||
| For **OpenBMC**, SONiC incorporates a Redfish client as the underlying infrastructure to support BMC actions. | ||
|
|
||
|  | ||
|
|
||
| For **SONiC BMC**, the host opens a TCP connection to the BMC Redis instance (STATE_DB, db 6), using the same `bmc_addr` from `bmc.json` / `DEVICE_METADATA|bmc`. | ||
| On Switch-BMC systems, Redis is bound to the BMC link IP at startup (see `dockers/docker-database/docker-database-init.sh` and `dockers/docker-database/supervisord.conf.j2`). | ||
|
|
||
| ## 3. BMC ip address initialization | ||
| This is the flow of the bmc ip address configuration: | ||
| - device/platform/bmc.json contains bmc_if_name,bmc_if_addr,bmc_addr,bmc_net_mask | ||
|
|
@@ -27,16 +44,19 @@ iface usb0 inet static | |
|  | ||
|
|
||
|
|
||
| ## 3. BMC firmware upgrade flow | ||
| ## 3. BMC firmware upgrade flow (OpenBMC only) | ||
|
|
||
| It requires a new ComponenetBMC object to be added to the component.py | ||
|
|
||
|  | ||
|
|
||
| ## 4. Sonic-platform-common support for bmc | ||
|
|
||
| ### 4.1 BMC redfish client | ||
| The redfish_client.py module provides the RedfishClient class, which facilitates BMC access via cURL requests to Redfish APIs. This class serves as a cURL wrapper for executing various Redfish commands. The class utilizes callback functions to obtain user credentials securely and supports asynchronous task monitoring to handle long-running operations like firmware updates and log dump. | ||
| ### 4.1 BMC Redfish client (OpenBMC only) | ||
|
|
||
| The `redfish_client.py` module provides the `RedfishClient` class, which facilitates BMC access via cURL requests to Redfish APIs. This class serves as a cURL wrapper for executing various Redfish commands. The class utilizes callback functions to obtain user credentials securely and supports asynchronous task monitoring to handle long-running operations like firmware updates and log dump. | ||
|
|
||
| Used when `DEVICE_METADATA|bmc.os` is `openbmc` (default). | ||
|
|
||
| Key functionalities: | ||
| 1. Session Management: Handles login and logout operations, ensuring secure sessions with the BMC. It manages tokens and session IDs, and automates re-login if tokens expire. | ||
|
|
@@ -45,35 +65,41 @@ Key functionalities: | |
| 4. Error Handling: Maps cURL error codes to RedfishClient error codes, and includes comprehensive error handling and logging. | ||
| 5. Security: Obfuscates sensitive information such as tokens and passwords in logs and command outputs. | ||
|
|
||
| ### 4.2 BMC api scope | ||
| Because in SONiC, each command will be executed as a separate process, nothing will be shared between 2 commands. This requires 2 separate BMC RF sessions, so to avoid exhausting session numbers, we will have a logout call after each of the commands executed. | ||
| Thus, there will be a python decorator used for each API/fucntion, for both login and logout. | ||
| ``` | ||
| APIs inherited from Device Base | ||
| get_name() | ||
| get_presence() | ||
| get_model() | ||
| get_serial() | ||
| get_revision() | ||
| get_status() | ||
| is_replaceable() | ||
|
|
||
| BMC general APIs | ||
| Return dictionary (Manufacturer, Model, PartNumber, PowerState, SerialNumber) to show the eeprom info or exception with the failure reason | ||
| ### 4.2 BMC Redis client (SONiC BMC only) | ||
|
|
||
| When the BMC runs SONiC OS, the Switch-Host does not use Redfish. Instead, `bmc_base.py` connects to the BMC Redis instance over the host–BMC link. | ||
|
|
||
| Implementation reference: `sonic_py_common.daemon_base.db_connect_remote()` (same pattern as `thermalctld` mirroring thermals to the BMC). | ||
|
|
||
| ### 4.3 BMC API scope | ||
|
|
||
| **APIs inherited from Device Base** — both BMC OS types where applicable: | ||
|
|
||
| | API | OpenBMC | SONiC BMC | | ||
| |-----|---------|-----------| | ||
| | `get_name()` | Yes | Yes | | ||
| | `get_presence()` | Yes | Yes | | ||
| | `get_model()` | Yes | Yes | | ||
| | `get_serial()` | Yes | Yes | | ||
| | `get_revision()` | Yes | Yes | | ||
| | `get_status()` | Yes | Yes | | ||
| | `is_replaceable()` | Yes | Yes | | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OpenBMC and SONiC BMC already provide almost all of the capabilities we need (EEPROM, presence, model/serial, status, version, etc.). For those common capabilities, we should expose a single interface that hides the underlying BMC OS. The current design seems to push the BMC OS decision into the caller and we need to hard code like this
That means every consumer now needs to know which BMC OS is running, which creates unnecessary tight coupling. My proposal :
The underlying BMC OS should remain an implementation detail. hostside consumers should nt need to know or care about which BMC OS is running. |
||
|
|
||
| **BMC general APIs:** | ||
|
|
||
| Return dictionary to show the eeprom info or exception with the failure reason | ||
| Returns an empty dictionary {} if EEPROM information cannot be retrieved | ||
| get_eeprom() | ||
|
|
||
| Return string to show the firmware version or exception with the failure reason | ||
| Returns 'N/A' if the BMC firmware version cannot be retrieved | ||
| get_version() | ||
|
|
||
|
|
||
| Returns: A tuple (ret, msg) where: | ||
| ret: An integer return code indicating success (0) or failure | ||
| msg: A string containing success message or error description | ||
| reset_root_password() | ||
|
|
||
|
|
||
| Returns: A tuple (ret, (task_id, err_msg)) where: | ||
| ret: An integer return code indicating success (0) or failure | ||
| task_id: A string containing the Redfish task ID for monitoring | ||
|
|
@@ -90,22 +116,57 @@ get_bmc_debug_log_dump(task_id, filename, path) | |
| param fw_image: string to indicate the path of the firmware image | ||
| Returns:A tuple (ret, msg) where: | ||
| ret: An integer return code indicating success (0) or failure | ||
| msg: A string containing status message about the firmware update | ||
|
|
||
| msg: A string containing status message about the firmware update | ||
| update_firmware(fw_image) | ||
|
|
||
| ``` | ||
| ### 4.4 BMC API details | ||
|
|
||
| | API | OpenBMC | SONiC BMC | Notes | | ||
| |-----|---------|-----------|-------| | ||
| | `get_eeprom()` | Yes | Yes | OpenBMC: Redfish dict (`Manufacturer`, `Model`, `PartNumber`, `PowerState`, `SerialNumber`). SONiC BMC: from `EEPROM_INFO`. Returns `{}` on failure. | | ||
| | `get_version()` | Yes | **No** | Redfish firmware query only | | ||
| | `reset_root_password()` | Yes | **No** | Redfish only | | ||
| | `trigger_bmc_debug_log_dump()` | Yes | **No** | Redfish only | | ||
| | `get_bmc_debug_log_dump()` | Yes | **No** | Redfish only | | ||
| | `update_firmware(fw_image)` | Yes | **No** | Redfish only | | ||
|
|
||
| ## 5. CLI commands | ||
|
|
||
| ### 5.1 BMC OS selection | ||
|
|
||
| The Switch-Host stores the configured BMC operating system in CONFIG_DB: | ||
|
|
||
| - **Table/key**: `DEVICE_METADATA|bmc` | ||
| - **Field**: `os` | ||
| - **Values**: `openbmc` | `sonic` | ||
| - **Default**: `openbmc` | ||
|
|
||
| YANG: `leaf os` under `container bmc` in `sonic-device_metadata.yang`. | ||
|
|
||
| Runtime API: `sonic_py_common.device_info.get_bmc_os()`. | ||
|
|
||
| ``` | ||
| show platform bmc summary | ||
| show platform bmc os | ||
| --------------------------- | ||
| openbmc | ||
|
|
||
| config bmc os sonic | ||
| config bmc os openbmc | ||
| ``` | ||
|
|
||
| `config bmc os` writes `DEVICE_METADATA|bmc.os`. Subsequent BMC CLI/API calls on the Switch-Host use Redfish or Redis according to this setting. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why an operator need this API at all ? exposing I would recommend removing it, or at most exposing it as read only platform metadata. a get is ok but not set . please think about it. |
||
|
|
||
| ### 5.2 Platform BMC CLIs | ||
|
|
||
| ``` | ||
| show platform bmc summary # OpenBMC and SONiC BMC (FirmwareVersion is N/A since it cannot be retrieved without Redfish) | ||
| --------------------------- | ||
| Manufacturer: XXXXX | ||
| Model: XXXXX | ||
| PartNumber: XXXXX | ||
| SerialNumber: XXXXX | ||
| PowerState: XXXXX | ||
| FirmwareVersion: XXXXX | ||
| FirmwareVersion: N/A | ||
|
|
||
| show platform firmware status | ||
| Component Version Description | ||
|
|
@@ -118,23 +179,30 @@ CPLD2 XXXXXXXXXXXXXXXXXXXXXXXXX CPLD - Complex Programmable Logic Device | |
| CPLD3 XXXXXXXXXXXXXXXXXXXXXXXXX CPLD - Complex Programmable Logic Device | ||
| BMC XXXXXXXXXXXXXXXXXXXXXXXXX BMC – Board Management Controller | ||
|
|
||
| show platform bmc eeprom | ||
| show platform bmc eeprom # OpenBMC and SONiC BMC | ||
| --------------------------- | ||
| Manufacturer: XXXXX | ||
| Model: XXXXX | ||
| PartNumber: XXXXX | ||
| PowerState: XXXXX | ||
| SerialNumber: XXXXX | ||
|
|
||
| config platform firmware install chassis component BMC fw -y ${BMC_IMAGE} | ||
| config platform firmware install chassis component BMC fw -y ${BMC_IMAGE} # OpenBMC only | ||
|
|
||
| ``` | ||
|
|
||
| ## 6. show techsupport | ||
| Bmc dump will be included in the show techsupport, trigger_bmc_debug_log_dump() and get_bmc_debug_log_dump() shall be called by the generate-dump script. | ||
|
|
||
| ### OpenBMC (Switch-Host techsupport) | ||
|
|
||
| On Switch-Host, BMC dump collection via Redfish is **OpenBMC only**. `generate_dump` calls `is_bmc_supported()`, which requires Switch-Host, `bmc.json`, and `get_bmc_os() == openbmc`. When the BMC runs SONiC OS, host-side BMC dump collection is skipped. | ||
|
|
||
| For SONiC BMC, collect diagnostics by running `show techsupport` **on the BMC** (local SONiC instance), not from the Switch-Host Redfish path. | ||
|
|
||
| `trigger_bmc_debug_log_dump()` and `get_bmc_debug_log_dump()` are called by the generate-dump script on the Switch-Host for OpenBMC only. | ||
|
|
||
| ### 6.1. Overview | ||
| The 'show techsupport' command is extended to collect BMC dump logs via Redfish API. | ||
| The Switch-Host `show techsupport` command is extended to collect BMC dump logs via Redfish API when the BMC OS is OpenBMC. | ||
| This integration is non-blocking and asynchronous: | ||
| It triggers a BMC dump task at the start of the script, then continues with regular | ||
| system data collection. Before the script finishes, it collects the dump from BMC | ||
|
|
@@ -146,7 +214,7 @@ do not block or interrupt the standard dump flow. | |
|  | ||
|
|
||
| ### 6.3 Errors Handling: | ||
| - generate_dump check whether BMC is suppported (via bmc.json file). If not, BMC logic is skipped. | ||
| - `generate_dump` checks whether BMC Redfish dump is supported: Switch-Host, `bmc.json` present, and `get_bmc_os() == openbmc`. If not, host-side BMC dump logic is skipped. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ideally , this check should be be in only one place something like "ChassisBase.get_bmc()" ( from bmc.json) , all implementation of subclass creation like vendor specific custom code and transport strategy can grow independently |
||
| - Errors in BMC initialization, trigger, or collect phases are caught and logged. | ||
| - The timeout in techsupport script for collect_bmc_dump is set to 60 seconds. | ||
| In practice, the dump is typically ready before collection begins. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we implement the API's in SONiC Redfish too (barring the dump)? Should be fairly straightforward to implement. This way we keep the API layer clean and do away with the bmc os config too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As part of the SONiC BMC project architecture, the agreed-upon design was that communication between the host side and the BMC side would be via Redis. Dedicated Redfish endpoints will be added for specific use cases, but those are outside the scope of this PR.
Most of the existing BMC APIs (bmc_base.py) are OpenBMC-specific and are therefore not relevant for SONiC BMC. Examples include session management, resetting the root password, and firmware updates, which in our case will be handled directly on the BMC side.
However, the host still needs access to the BMC EEPROM data so that we can continue supporting the existing
show platform bmc eepromCLI. For that reason, the EEPROM information is retrieved from the SONiC BMC Redis database.