openUBMC社区的CLI接口采用接口映射配置方案实现,需要将命令配置到json文件中。CLI命令的接口映射配置文件位于rackmount代码仓的cli路径下。
本篇指导仅介绍CLI接口独有的配置规则,接口映射配置公共机制可见《接口映射配置》。
CLI命令映射
CLI命令格式为ipmcget/ipmcset [-t <target>] -d <dataitem> [-s <systemid>] [-v <value> ...]
映射规则:
ipmcget
对应方法GET
,ipmcset
对应方法PATCH
;- Uri格式
/cli/v1/<target>/<dataitem>
,没有-t
参数时<target>
用下划线_
替代; -v
参数<value>
不参与Uri组成,用于构造成请求体数据;-s
参数<systemid>
用于构造成请求头参数SystemId
。
在配置文件中,Uri对应字段Resources[].Uri
, 方法对应字段Resources[].Interfaces[].Type
。
示例如下:
ipmcget -t service -d list → GET /cli/v1/service/list
ipmcset -d upgrade -v /tmp/image.hpm → PATCH /cli/v1/_/upgrade
命令提示
输入的指令无法匹配到唯一命令时,会提示-t
/-d
的部分或全部命令及对应命令描述,例如:
openUBMC:/->ipmcset -t se
-t <target>
service Operate with service
sensor Operate with sensor
securitybanner Operate login security banner information
securityenhance Operate security enhance
openUBMC:/->ipmcset -t service
-d <dataitem>
state Set service enable state
port Set service port
命令描述配置在Resources[].Interfaces[].Description
中(必须配置),例如:
ipmcset -t service
对应的Uri为/cli/v1/service
,其命令描述为Operate with service
,配置如下:
{
"Uri": "/cli/v1/service",
"Interfaces": [
{
"Type": "PATCH",
"Description": "Operate with service"
}
]
}
ipmcset -t service -d port
对应的Uri为/cli/v1/service/Port
,其命令描述为Operate with service
,配置如下:
{
"Uri": "/cli/v1/service/port",
"Interfaces": [
{
"Type": "PATCH",
"Description": "Set service port"
}
]
}
参数提示
当输入的指令可以唯一匹配到某一命令时,但是-v
参数输入不合理,此时系统需要输出此命令的相关提示:
- 命令格式 → Resources[].Interfaces[].Usage
- 简单描述 → Resources[].Interfaces[].Brief
- 参数说明 → Resources[].Interfaces[].ReqBody[].Name + Description,
Description
为空则不输出该参数说明 - 示例说明 → Resources[].Interfaces[].Example
NOTE
各字段按需配置,不显示的字段可以不配或配置为null
或配置为""
,推荐至少要有Usage
。命令提示的作用是告诉用户命令的含义及其使用方法,根据实际需求配置即可。
命令提示的格式如下:
Usage: <命令格式>
<简单描述>
<参数说明 Name: Description>
Example:
<示例说明>
例如ipmcset -d fanmode
的命令提示为:
openUBMC:/->ipmcset -d fanmode
Usage: ipmcset -d fanmode -v <mode> [timeout]
mode:
0 auto regulate fan speed, without parameter [timeout]
1 manual regulate fan speed
without parameter [timeout], default timeout(30 seconds)
with parameter [timeout], timeout range <0-100000000>,(0 means max timeout)
Example:
ipmcset -d fanmode -v 0
ipmcset -d fanmode -v 1
ipmcset -d fanmode -v 1 100
其对应的配置应该为:
{
"Uri": "/cli/v1/_/fanmode",
"Interfaces": [
{
"Type": "PATCH",
"Description": "Set fan mode,you can choose manual or auto",
"Usage": "ipmcset -d fanmode -v <mode> [timeout]",
"ReqBody": {
"Type": "object",
"Required": false,
"Properties": {
"mode": {
"Required": false,
"Type": "integer",
"Validator": [
{
"Type": "Enum",
"Formula": [0, 1, 2]
}
]
},
"timeout": {
"Type": "integer",
"Required": false
}
}
}
}
]
}
ReqBody
字段配置含义
CLI接口与Redfish接口有所不同,并没有传统意义上的请求体,CLI接口请求体ReqBody
配置来源为命令-v
后接参数。参数与ReqBody.Properties
的key一一对应,如上述例子,<mode>
对应ReqBody.Properties.mode
。
各字段配置含义:
- Name: 参数名称;
- Required: 取值
true
/false
, 未配置时默认值false
。true
表示必填参数,false
表示选填参数; - Description: 参数说明,
-v
后接参数用于命令提示打印;交互参数用于回显提示。
ReqBody
字段数据类型调整
默认情况下,CLI接口的-v
后接参数为字符串类型。当前一些命令,例如ipmcset -t sol -d timeout -v <value>
, value
的可能取值为0-480
, 为整数。如果按照字符串来处理,会增加配置的复杂度。
对于CLI接口的-v
后接参数,即ReqBody
配置,做以下类型转换规则:
如果存在Type
字段,并且取值为integer
或者number
, 会尝试进行类型转换;如果原始数据可以转换为对应类型,则进行转换,否则保持原有数值。
以ipmcset -t sol -d timeout -v <value>
中value
的配置为例:
{
"Name": "Value",
"Required": true,
"Type": "integer",
"Validator": [
{
"Type": "Range",
"Formula": [0, 480]
}
],
"Description": "\n 0 No limit\n 1-480 SOL timeout period(min)"
}
当<value>
取值:
xxx
: 无法转换为integer
, 保持"xxx"
, 数据类型校验失败123
: 可以转换为整数123
, 范围在0-480
, 校验通过123.0
: 可以转换为integer
, 会转换为123
, 数据类型校验成功1234
: 可以转换为整数1234
, 范围不在0-480
, 范围校验失败0x123
: 可以转换为十进制整数291
, 范围在0-480
, 校验通过
常规命令
常规命令是指命令下发后,经业务层处理后,CLI接口映射配置获取响应数据,按照回显模板直接打印,例如ipmcget -d version
。
{
"Uri": "/cli/v1/_/version",
"Interfaces": [
{
"Type": "GET",
"Description": "Get openUBMC version",
"Usage": "ipmcget -d version",
"RspBody": {
"ActiveVersion": "${ProcessingFlow[1]/Destination/ActiveVersion}",
"ActiveBuildNum": "${ProcessingFlow[1]/Destination/ActiveBuildNum}",
"ActiveReleaseDate": "${ProcessingFlow[1]/Destination/ActiveReleaseDate}",
"BackupVersion": "${ProcessingFlow[2]/Destination/BackupVersion}",
"AvailableVersion": "${ProcessingFlow[3]/Destination/AvailableVersion}",
"AvailableBuildNum": "${ProcessingFlow[3]/Destination/AvailableBuildNum}"
},
"ProcessingFlow": [
{
{
"Type": "Property",
"Path": "/bmc/kepler/UpdateService/FirmwareInventory/ActiveBMC",
"Interface": "bmc.kepler.UpdateService.FirmwareInfo",
"Destination": {
"Version": "ActiveVersion",
"BuildNum": "ActiveBuildNum",
"ReleaseDate": "ActiveReleaseDate"
}
},
{
"Type": "Property",
"Path": "/bmc/kepler/UpdateService/FirmwareInventory/BackupBMC",
"Interface": "bmc.kepler.UpdateService.FirmwareInfo",
"Destination": {
"Version": "BackupVersion"
}
},
{
"Type": "Property",
"Path": "/bmc/kepler/UpdateService/FirmwareInventory/AvailableBMC",
"Interface": "bmc.kepler.UpdateService.FirmwareInfo",
"Destination": {
"Version": "AvailableVersion",
"BuildNum": "AvailableBuildNum"
}
}
}
],
"Echoes": [
"ipmcget/_version",
""
]
}
]
}
RspBody
为接口映射响应体,需要与回显模板配置Echoes
字段配合使用。
分页命令
分页命令指获取一系列相同格式文本的命令,由于条数可能会很大,一次性显示会显示内容过多,需要分成多页显示。 以ipmcget -d operatelog
配置为例:
{
"Uri": "/cli/v1/_/operatelog",
"Interfaces": [
{
"Type": "GET",
"Usage": "ipmcget -d operatelog",
"Query": {
"Skip": 0,
"Top": 20
},
"Description": "Print operation log",
"RspBody": {
"Count": "${ProcessingFlow[1]/Destination/Count}",
"Log": "${ProcessingFlow[1]/Destination/Log}"
},
"ProcessingFlow": [
{
"Type": "Paging",
"Path": "/bmc/kepler/Managers/1/LogServices/OperateLog",
"Interface": "bmc.kepler.Managers.LogService",
"Name": "GetItems",
"Params": [
"${Query/Skip}",
"${Query/Top}"
],
"Destination": {
"Count": "Count",
"Log": "Log"
}
}
],
"Echoes": [
"ipmcget/_operatelog",
""
]
}
]
}
上例中,当ProcessingFlow
中有Type
取值为Paging的有效配置时,命令被识别为分页命令,一般也同时配置有关键字Query.Skip和Query.Top。一般情况下都是配置Skip=0, Top=20
, 表明一页的数据条数为20
条,按q
可退出命令,按其它按键继续显示下一页,直到所有条数显示完成,退出命令。 ProcessingFlow
只需要配置单次获取的规则,映射器框架和后台组件会执行分页处理,每获取一页就下发一次请求,并且更新传递给资源数的Skip
和Top
的取值。
资源协作接口方法Method
格式要求
仍然以ipmcget -d operatelog
接口为例,要正确获取指定文本内容并响应,需要满足以下格式要求:
方法入参
方法入参包含两个字段(接口映射配置中传入字段名称可以不同,但是一定要有该字段,且类型、取值正确)
Skip
: 表示跳过的条数,与Redfish接口查询参数的$skip
含义一致Top
: 表示获取的条数,与Redfish接口查询参数的$Top
含义一致
方法响应
方法入参包含两个字段(接口映射配置中传入字段名称可以不同,但是一定要有该字段)
Count
: 总条数Log
: 数组,请求的Top
条信息组成的数组
结果顺序
方法获取结果是按顺序排列的,分页显示则是按倒序打印的。获取数据时会保存该时刻的数据,分页过程中获取数据都是基于调用方法时保存下来的数据。
任务命令
有时资源协作接口方法需要执行较长时间,这时一般会将该方法做异步处理,例如一键收集日志。CLI命令下发任务,并轮询任务进度直至任务完成或异常退出。通用任务机制定义可见《rackmount组件接口说明》资源协作接口映射配置Task章节。
以ipmcget -d diaginfo
接口为例:
openUBMC:/->ipmcget -d diaginfo
Downloading...
100%
Download diagnose info to /tmp/ successfully.
对应接口映射配置样例如下:
{
"Uri": "/cli/v1/_/diaginfo",
"Interfaces": [
{
"Type": "GET",
"Description": "Get diagnostic info of management subsystem",
"Usage": "ipmcget -d diaginfo",
"RspBody": {
"TaskId": "${ProcessingFlow[1]/Destination/TaskId}"
},
"ProcessingFlow": [
{
"Type": "Task",
"Path": "/bmc/kepler/Managers/1/LogServices",
"Interface": "bmc.kepler.Managers.LogServices",
"Name": "Dump",
"Params": [
0,
"${Statements/GetDestination()}"
],
"Destination": {
"TaskId": "TaskId"
}
}
],
"Echoes": [
"ipmcget/_diaginfo"
]
}
]
}
交互命令
交互命令指命令下发后需用户再输入指令,命令才能继续执行。当前CLI命令涉及的交互命令可分为三类:
Y/N
确认
部分命令,在执行资源协作接口映射配置前,需要输入Y
/N
来确认是否进行下一步动作。例如ipmcset -d reset
会重启BMC, 属于高危动作,需要预先进行确认操作。
openUBMC:/->ipmcset -d reset
This operation will reboot openUBMC system.
Continue? [Y/N]:
对应的配置为:
{
"Uri": "/cli/v1/_/reset",
"Interfaces": [
{
"Type": "PATCH",
"Usage": "ipmcset -d reset",
"Description": "Reboot openUBMC system",
"Confirm": {
"Condition": true,
"Description": "This operation will reboot openUBMC system.\nContinue? [Y/N]:"
},
"ProcessingFlow": [xxx],
"Echoes": [xxx]
}
]
}
Confirm.Condition
: 表示是否需要Y/N
确认,取值true
/false
。Condition
也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
。如下述接口映射配置,当ReqBody.option
取值为disabled
时需要确认。Confirm.Description
:Y/N
确认时的提示信息。也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
。
"Confirm": {
"Condition": "${Statements/condition()}",
"Description": "WARNING: Disabling the complexity checking function may reduce the system security.\nDo you want to continue?[Y/N]:",
},
"Statements": {
"condition": {
"Steps": [
{
"Type": "Script",
"Formula": "return ReqBody.option == 'disabled'"
}
]
}
}
密码鉴权确认
出于安全考虑,部分命令需再次输入登录用户密码以进行鉴权确认,例如命令ipmcset -t user -d state -v <username> <state>
:
openUBMC:/->ipmcset -t user -d state -v Test enabled
Input your password:
Enable user:Test successfully.
对应的配置为:
{
"Uri": "/cli/v1/user/state",
"Interfaces": [
{
"Type": "PATCH",
"Usage": "ipmcset -t user -d state -v <username> [enabled|disabled]",
"Description": "Enabled/Disabled user",
"Authentication": {
"Description": "Input your password:",
"Condition": true
},
"ReqBody": {xxx},
"RspBody": {xxx},
"ProcessingFlow": [xxx],
"Echoes": [xxx]
}
]
}
- Authentication.Condition: 表示是否需要密码鉴权确认,取值
true
/false
。Condition
也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
- Authentication.Description: 密码鉴权确认时的提示信息。
Description
也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
输入新密码
部分命令例如新增用户-d adduser
, 除了输入当前登录用户的密码外,还需要两次输入新增用户的新密码,并且输入无回显:
openUBMC:/->ipmcset -d adduser -v Test1
Input your password:
Password:
Confirm password:
Add user successfully.
接口映射配置提供无回显输入接口,后台组件封装了两次输入密码的插件。
"Statements": {
"GetPwd": {
"Steps": [
{
"Type": "Plugin",
"Formula": "orchestrator.account.get_pwd()"
}
]
}
},
"ProcessingFlow": [
{
"Type": "Method",
"Path": "/bmc/kepler/AccountService/Accounts",
"Interface": "bmc.kepler.AccountService.ManagerAccounts",
"Name": "New",
"Params": [
0,
"${ReqBody/username}",
"${Statements/GetPwd()[2]}",
0,
[1, 2, 4, 8, 16, 64, 128],
2
],
"CallIf": {
"${Statements/GetPwd()[1]}": 0
},
"Destination": {
"AccountId": "AccountId"
}
}
]
回显模板
Resources[].Interfaces[].Echoes
为字符串数组,当前仅使用Echoes[1]
,表示内置的回显模板配置,例如ipmcget -d version
的Echoes[1]
取值为ipmcget/_version
, 那么在rackmount代码仓CLI接口回显模板路径下需要有ipmcget/_version
文件,其内容如下:
------------------- openUBMC INFO -------------------
Active openUBMC Version: {* ActiveVersion *}
Active openUBMC Build: {* ActiveBuildNum *}
Active openUBMC Built: {* ActiveReleaseDate *}
Backup openUBMC Version: {* BackupVersion *}
Available openUBMC Version: {* AvailableVersion *}
Available openUBMC Build: {* AvailableBuildNum *}
------------------- Product INFO --------------------
Product Name: {* ProductName *}
模板引擎规则:
{{var}}
输出
var
的结果,一些特殊符号会被转义,不推荐使用此规则{* var *}
输出
var
的结果,不会转义任何特殊符号{% code %}
执行一段lua代码,如:
{% for i = x, y do ... end %}
{# comments #}
comments
仅作为注释,不会包含在输出字符串内{{template}}
导入其它模板文件;同时支持传参:
{(file.html, { message = "Hello, World" })}
特别注意
RspBody
的返回值如果是bool
类型,在回显模板中只能接受到true
,false
会变为nil
值。若回显模板中出现以下写法,echo内的内容将无法打印。目前可使用
io.write('xxx')
。shellif xx then echo('xxx') return end