☰
OpenBMC:bmcweb 的作用与请求处理流程
2026/10/12 0:34:41 网站建设 项目流程

1. bmcweb 在 OpenBMC 里到底扮演什么角色

如果你刚接手一块 OpenBMC 的板子,浏览器打开 BMC 的 IP 能看到登录页,Redfish 客户端也能拉到/redfish/v1/的 JSON,这背后干活的就是 bmcweb。它是 OpenBMC 的 Web 与 Redfish 网关,对外提供 HTTPS 服务、WebUI 静态资源、Redfish API 和一部分 REST 接口,对内则通过 D-Bus 去访问 phosphor 系列服务。换句话说,外部世界用 HTTP/JSON 说话,OpenBMC 内部用 D-Bus 说话,bmcweb 就是那个翻译官。

很多刚接触 OpenBMC 的朋友会误以为 bmcweb 直接读传感器、直接拉 GPIO 控制电源。实际上它不碰硬件。读温度时,bmcweb 不会去访问 I2C 或 hwmon,而是去 D-Bus 上找xyz.openbmc_project.Sensor.Value这个属性;控制电源时,它也不会去拉 GPIO,而是调用 phosphor-state-manager 暴露的方法。这种解耦设计的好处是,WebUI、Redfish、IPMI 等多个入口看到的状态永远一致,因为大家读的都是同一份 D-Bus 数据。

bmcweb 的核心职责可以归纳成几块:提供 HTTPS 服务、托管 WebUI 静态资源、实现 Redfish API、处理用户登录与会话、执行认证与权限检查、做 HTTP 路由匹配、访问 D-Bus 后端、把 D-Bus 数据转成 JSON、处理固件上传这类文件请求、最后返回 HTTP/Redfish 响应。它依赖 ObjectMapper 来查找对象,依赖 phosphor-logging 查日志,依赖 phosphor-network 改网络,依赖 phosphor-software-manager 做升级。理解这层依赖关系,是后面排查问题的关键。

适合读这篇的人有三类:一是做 BMC 固件开发、需要往 bmcweb 里加自定义路由的工程师;二是做带外运维、需要用 curl 或 Redfish 客户端定位接口异常的运维;三是刚上手 OpenBMC、想搞清楚一次请求到底走了哪些环节的初学者。下面我会先讲清楚请求链路,再给出可复制的路由注册与配置片段,最后用 curl 把每个阶段都验证一遍。

2. 一次 HTTP 请求从接入到响应的完整链路

要定位请求卡在哪,得先知道正常链路长什么样。以最常见的 Redfish GET 为例,客户端发起 HTTPS 请求后,bmcweb 的 acceptor 接收连接,接着解析 HTTP 报文,匹配到注册的路由,执行认证与权限检查,调用对应的处理函数,处理函数通过 D-Bus 访问后端对象,读取属性或调用方法,把结果转成 JSON,最后组装 HTTP 响应返回。这条链路里任何一环出问题,表现都不一样:连接建不起来是 TLS 或端口问题,返回 401 是认证问题,返回 404 是路由没匹配上,返回 500 往往是 D-Bus 调用失败。

如果是 PATCH 或 POST 这类修改请求,链路会多出几步:解析 JSON body、校验参数合法性、检查用户权限、调用 D-Bus 的 set-property 或 method call、根据结果返回成功或错误。比如改网络配置走 PATCH EthernetInterface,bmcweb 解析出 IP、网关、DHCP 字段后,不是直接改网卡配置文件,而是通过 D-Bus 调用网络服务,由 systemd-networkd 最终生效。这样保证 WebUI 和 Redfish 看到的状态一致。

bmcweb 的路由注册用的是 Boost.Beast 加一套自己的 router。每个资源对应一个BMCWEB_ROUTE宏,里面声明路径、允许的 HTTP 方法、权限级别和处理函数。处理函数拿到请求后,通常会用crow::connections::systemBus->async_method_call去异步调用 D-Bus,回调里再构造响应。理解这个异步模型很重要,因为日志里看到的报错经常是回调里抛出来的,而不是路由入口。

下面这张表把几个典型请求和它们最终落到哪个后端服务列出来,排查时可以直接对照:

Redfish 资源bmcweb 处理模块后端 D-Bus 服务
/redfish/v1/Systems/systemsystems 路由phosphor-state-manager
/redfish/v1/Chassis/.../Thermalthermal 路由dbus-sensors
/redfish/v1/Managers/bmcmanagers 路由phosphor-bmc-state-manager
/redfish/v1/AccountServiceaccount 路由phosphor-user-manager
/redfish/v1/UpdateServiceupdate 路由phosphor-software-manager
/redfish/v1/Systems/system/LogServiceslogservices 路由phosphor-logging

链路里还有一个容易被忽略的环节:认证。bmcweb 支持 Basic Auth、Session Token、Cookie 和 TLS 客户端证书几种方式。Redfish 标准做法是先 POST 到/redfish/v1/SessionService/Sessions创建会话,拿到 token 后后续请求带X-Auth-Token。bmcweb 会根据用户角色做权限检查,查看传感器普通权限即可,改网络需要配置权限,电源控制需要操作权限,固件升级需要管理员权限。权限不足时返回 403,而不是 401,这个区别在排查时很有用。

3. 可复制的 bmcweb 路由注册与配置片段

这一节给的是能直接抄进代码和配置文件的片段。先看路由注册。bmcweb 里新增一个 Redfish 资源,通常是在src/webserver/routes.hpp或对应模块的routes文件里加BMCWEB_ROUTE。下面是一个读取自定义属性的最小示例,路径和权限按你实际需求改:

BMCWEB_ROUTE("/redfish/v1/MyService/Status") .methods(boost::beast::http::verb::get)( [](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { if (!redfish::isOk(asyncResp)) { return; } crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code& ec, const std::variant<std::string>& value) { if (ec) { messages::internalError(asyncResp->res); return; } asyncResp->res.jsonValue["Status"] = std::get<std::string>(value); }, "xyz.openbmc_project.MyService", "/xyz/openbmc_project/MyService", "org.freedesktop.DBus.Properties", "Get", "xyz.openbmc_project.MyService.Status", "Status"); });

这段代码里几个点值得注意:BMCWEB_ROUTE的第一个参数是 URI,.methods限定 HTTP 方法,lambda 里通过asyncResp异步回填响应。D-Bus 调用用的是async_method_call,回调里先判ec,出错就返回internalError,成功才写jsonValue。这是 bmcweb 里最标准的写法,照抄不会错。

再看配置文件。bmcweb 的运行时配置在/etc/bmcweb/下,常见的有bmcweb_config.json和redfish_config.json。如果你要调整会话超时、TLS 版本或启用某个 Redfish 特性,改这里:

{ "sessionTimeout": 1800, "tlsVersion": "TLSv1.3", "redfish": { "enableAccountService": true, "enableUpdateService": true, "enableSessionService": true }, "http": { "port": 443, "enableHttps": true } }

改完配置后需要重启服务:

systemctl restart bmcweb systemctl status bmcweb

如果你用的是 systemd 管理,也可以直接看 unit 文件里的启动参数,确认 bmcweb 加载的是哪个配置路径:

systemctl cat bmcweb

这里要提醒一句,bmcweb 的配置项在不同 OpenBMC 版本里字段名可能略有差异,改之前先cat一下现有文件,别直接覆盖。另外,路由注册属于编译期行为,改完 C++ 代码要重新编译镜像,不是重启服务就能生效的。这一点和配置文件的区别要分清楚,否则会白折腾半天。

4. 用 curl 验证各阶段返回结果

链路讲完了,配置也给完了,接下来用 curl 把每个阶段都打一遍,看返回码和内容对不对。先测最基础的连通性和 TLS:

curl -k -u root:0penBmc https://<bmc-ip>/redfish/v1/

-k是跳过证书校验,因为 BMC 默认用的是自签证书。如果这一步就失败,说明 HTTPS 服务没起来或者端口不对,先去看systemctl status bmcweb。返回 200 且带@odata.id的 JSON,说明 TLS 和路由入口都正常。

接着测认证。先用 Basic Auth 直接访问 Manager 资源:

curl -k -u root:0penBmc https://<bmc-ip>/redfish/v1/Managers/bmc

返回 200 说明 Basic Auth 通过。如果返回 401,检查用户名密码;如果返回 403,说明认证过了但权限不够。再测会话方式,先创建会话拿 token:

curl -k -X POST https://<bmc-ip>/redfish/v1/SessionService/Sessions \ -H "Content-Type: application/json" \ -d '{"UserName":"root","Password":"0penBmc"}'

响应头里会有X-Auth-Token,把它记下来,后续请求带上:

curl -k -H "X-Auth-Token: <token>" https://<bmc-ip>/redfish/v1/Systems/system

这一步能返回系统资源,说明会话认证和路由都通了。再往下测 D-Bus 数据是否真的读到了,访问传感器相关的 Thermal 资源:

curl -k -u root:0penBmc https://<bmc-ip>/redfish/v1/Chassis/Baseboard/Thermal

如果返回 200 但Temperatures数组是空的,问题就不在 bmcweb,而在 D-Bus 上有没有传感器对象。这时候去 BMC 上执行:

busctl tree xyz.openbmc_project.ObjectMapper | grep sensors busctl list | grep sensor

能看到传感器对象,说明 dbus-sensors 在跑;看不到,就得先查传感器服务。最后测一个修改类请求,比如电源控制:

curl -k -u root:0penBmc -X POST \ https://<bmc-ip>/redfish/v1/Systems/system/Actions/ComputerSystem.Reset \ -H "Content-Type: application/json" \ -d '{"ResetType":"On"}'

返回 204 或 200 说明 bmcweb 把请求转成了 D-Bus 调用并成功执行。如果返回 500,去看journalctl -u bmcweb -f,日志里会打出 D-Bus 调用的错误码。

5. 本篇常见报错与排查对照

排查 bmcweb 问题,最有效的方式是同时看三样东西:curl 的返回码、bmcweb 日志、D-Bus 对象是否存在。下面把几个高频报错和对应动作列出来。

401 Unauthorized:认证没通过。先确认用户名密码,再确认是不是用了 Session 但 token 过期了。bmcweb 默认会话超时是 1800 秒,超时后要重新创建会话。日志里会看到Authentication failed之类的记录。

403 Forbidden:认证过了但权限不够。比如用普通用户去改网络配置或做固件升级。检查用户角色,Redfish 里对应Roles字段。bmcweb 的权限检查在路由的.privileges()里声明,改权限要改代码重新编译。

404 Not Found:路由没匹配上。先确认 URI 拼写,Redfish 是大小写敏感的。再确认这个资源在当前 OpenBMC 版本里是否启用,有些服务默认关闭,比如 AccountService 或 UpdateService,需要在配置里打开。

500 Internal Server Error:最常见,通常是 D-Bus 调用失败。看journalctl -u bmcweb -f,日志里会有具体的 D-Bus 错误,比如org.freedesktop.DBus.Error.UnknownObject说明对象不存在,ServiceUnknown说明后端服务没起来。这时候用busctl去确认对象和服务状态。

local proxy failed / connection refused:这类报错一般出现在 bmcweb 尝试连 D-Bus 或后端 socket 时。先确认systemctl status dbus正常,再确认目标服务在跑。如果是编译期链接问题,检查依赖库版本。

reading choices 相关报错:多出现在解析 JSON body 时,比如 PATCH 请求的字段类型不对。bmcweb 用 nlohmann::json 解析,类型不匹配会抛异常。检查请求体字段名和类型,对照 Redfish schema。

OAuth / token 相关报错:如果启用了 OAuth 或外部认证,token 校验失败会返回 401。确认 token 签发方和 bmcweb 配置的校验方一致,时钟同步也要检查,时间偏差过大会导致 token 失效。

排查顺序建议固定成:先 curl 看返回码,再journalctl -u bmcweb -f看日志,再busctl看 D-Bus 对象,最后查后端服务状态。这个顺序能覆盖绝大多数问题,避免一上来就翻代码。

6. 把 bmcweb 接入流程固化下来

如果你在做 BMC 固件开发,日常会反复和 bmcweb 打交道,建议把上面这套验证动作固化成脚本。比如写一个check_bmcweb.sh,依次跑连通性、认证、会话、传感器、电源控制几个 curl,把返回码和关键字段打出来。这样每次改完代码或配置,跑一遍就知道链路有没有断。

对于需要长期做 Redfish 自动化或 Agent 开发的场景,可以考虑用 Coding Plan 来管理你的模型调用和代码生成流程,把重复的路由模板、D-Bus 调用样板代码交给它生成,你专注在业务逻辑上。接入文档里有完整的 Base URL、Key 和 Model ID 配置说明,照着配就行。

验证模型或调试接口时,模型对话入口可以直接测请求响应,方便对照 Redfish schema 检查字段。如果你在排查认证或会话问题,API Keys 页面能帮你确认当前使用的凭证状态。把这些工具和上面的 curl 验证结合起来,bmcweb 的请求链路就不再是黑盒,每个阶段都能看到明确的输入输出。

最后留一个实用习惯:每次改完 bmcweb 相关代码,先systemctl restart bmcweb,再journalctl -u bmcweb -f挂着,然后用 curl 打一遍关键接口。日志和返回码对上了,再去做更复杂的测试。这个习惯能帮你省下大量猜测时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询