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 enhanceopenUBMC:/->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