简介
IPMI,全称Intelligent Platform Management Interface(智能平台管理接口),是一组用于带外管理的计算机接口规范。用户可以利用IPMI监视服务器的物理健康特征,如温度、电压、风扇工作状态、电源状态等。而且更为重要的是IPMI是一个开放的免费标准,用户无需为使用该标准而支付额外的费用。
在之前的教学中,我们学习了如何新增一个组件,接下来我们来学习如何为一个组件新增一条IPMI命令。
命令定义
-
若是首次添加IPMI命令,需在组件根目录/mds目录下添加ipmi.json文件,当前组件的所有IPMI命令均定义在该文件中;
-
ipmi.json文件结构:
{ "package": "Hello_openUBMCIpmiCmds", "cmds": { "FirstIpmiCmd": { "netfn": "0x00", "cmd": "0x00", "priority": "Default", "role": "Administrator", "privilege": ["UserMgmt"], "sysLockedPolicy": "Forbidden", "req": [ { "data": "SubCmd", "baseType": "U8", "len": "1B", "value": "0x01" }, { "data": "DataLen", "baseType": "U8", "len": "1B" }, { "data": "Data", "baseType": "String", "len": "*" } ], "rsp": [ { "data": "CompletionCode", "baseType": "U8", "len": "1B" }, { "data": "ManufactureId", "baseType": "U32", "len": "3B", "customizedRule": "Manufacturer" } ] } } }- package:IPMI命令包的名称,一般使用‘组件名IpmiCmds’的大驼峰命名风格;
- cmds:所有IPMI命令定义的集合;
- FirstIpmiCmd: 此条IPMI命令的名称,使用大驼峰命名,同一个组件内的命令名称不可重复
-
命令字段说明:
- netfn:网络功能码,16进制数字符串;
- cmd:命令字,16进制数字符串;
- priority:命令优先级,当某些命令字的netfn、cmd等取值相同时,命令会优先发送至优先级更高的那条,优先级由高到底为:EndUser、OBM、ODM、OEM、Default
- role:可执行此IPMI命令的角色限制,可选角色有Unspecified、Callback、User、Operator、Administrator、OEM;
- privilege:命令执行权限,支持配置多个,用户需同时所有配置权限才可执行命令,命令取值为openUBMC九大权限定义:UserMgmt、BasicSetting、KVMMgmt、VMMMgmt、SecurityMgmt、PowerMgmt、DiagnoseMgmt、ReadOnly、ConfigureSelf;
- sysLockedPolicy:表示系统锁定时此命令能否执行,可选值:Allowed、Forbidden;
-
请求响应说明:
- req、rsp分别为命令的请求和响应数据,其结构为数组
- data:为字段名称,大驼峰风格;
- baseType:为字段数据类型,可取值U8、U1、U32、U8、String等;
- len:字符串长度,b为bit,B为字节,*为变长;若命数据含有数个以bit为长度定义的字段,即可在定义长度时使用b,对多个bit长度字段拼接;对于变长的数据,
- value:表示此字段的固定取值,用于过滤;
- customizedRole: 厂商ID定制规则,命令中涉及厂商ID字段必须配置;
自动生成
ipmi.json定义了新命令后,在组件仓根目录下执行命令bingo gen自动生成ipmi相关代码,生成文件:
- service.lua: 首次添加ipmi命令时,会在此类中生成ipmi命令注册相关代码;
- ipmi.lua: ipmi命令对象的实例集合;
- ipmi_message.lua: ipmi命令的请求和响应集合;
- FirstIpmiCmd.lua: 此条ipmi命令的请求和响应消息对象实例化和参数校验;
自动生成的文件一般无需更改,可直接使用。
命令功能实现
-
注册ipmi命令回调函数:
- 组件名_app.lua文件中有组件的初始化流程,需要在组件初始化时注册所有ipmi命令的回调函数;
- 组件名_app类继承于组件服务基类,基类中提供了regisiter_ipmi_cmd方法用于注册ipmi命令回调;
- regisiter_ipmi_cmd函数有两个参数,分别为ipmi命令的实例、ipmi命令的回调函数;回调函数存在2个入参分别为请求体req和上下文ctx
-
命令业务处理,ipmi命令的实际业务处理实现在回调函数中,大致有以下流程:
- 参数校验,校验失败或其他异常时,使用error(xxx)进行报错,xxx为通用错误引擎,可以通过messages.custom或messages.base获取到(错误信息定义在mdb_interface仓)
- 按需进行业务处理
- 构造响应并返回,响应体为ipmi.json中定义的rsp结构,其中完成码CompletionCode在成功时应为0x00
构建出包与调试
使用新增组件出包可以参考之前的 【教学培训篇】新增组件 教学文档。
按照文档步骤构建出qemu包并运行qemu后, 可通过查看组件资源树验证ipmi命令是否正常注册
-
ssh连接qemu/telnet连接qemu后使用source加载DBUS环境变量;
-
使用busctl命令查看组件资源树,查看ipmi命令是否正常挂载;
-
在终端使用ipmitool发送ipmi命令(需要先下载工具ipmitool);

- -H:openUBMC服务地址;
- -I:ipmi协议接口类型,openUBMC支持ipmi2.0版本的RMCP+协议,一般使用lanplus(也可使用1.5版本,对应取值为lan);
- -p:ipmi服务端口,qemu为10623,真实环境默认为623;
- -U,-P:用户名与密码
- raw:表示使用未加工16进制数作为请求参数,对应ipmi命令定义时的req请求体;
-
查看响应
- 在使用ipmitool发送命令且成功时,响应会隐藏第一字节的响应码;
- 发生异常时(响应码非0x00),会响应错误信息,如示例中的长度校验失败;

※ 异常场景:
发生报错Error: Unable to establish IPMI v2 / RMCP+ session一般为认证失败
![]()
- 首先确认命令中用户名&密码是否输入正确;
- 若确认密码无误,则查看日志是否有ret = 268的报错,此错误会导致ipmi的密文解密异常
; - 日志存在此错误时,需要手动修改一次此用户密码,再次执行ipmi命令,应恢复正常;


