CLI接口映射配置指南
更新时间:2025/08/12
在Gitcode上查看源码

openUBMC社区的CLI接口采用接口映射配置方案实现,需要将命令配置到json文件中。CLI命令的接口映射配置文件位于rackmount代码仓的cli路径下。

本篇指导仅介绍CLI接口独有的配置规则,接口映射配置公共机制可见《接口映射配置》

CLI命令映射

CLI命令格式为ipmcget/ipmcset [-t <target>] -d <dataitem> [-s <systemid>] [-v <value> ...]

映射规则:

  1. ipmcget对应方法GET, ipmcset对应方法PATCH
  2. Uri格式/cli/v1/<target>/<dataitem>,没有-t参数时<target>用下划线_替代;
  3. -v参数<value>不参与Uri组成,用于构造成请求体数据;
  4. -s参数<systemid>用于构造成请求头参数SystemId

在配置文件中,Uri对应字段Resources[].Uri, 方法对应字段Resources[].Interfaces[].Type

示例如下:

shell
ipmcget -t service -d list   GET /cli/v1/service/list
ipmcset -d upgrade -v /tmp/image.hpm   PATCH /cli/v1/_/upgrade

命令提示

输入的指令无法匹配到唯一命令时,会提示-t/-d的部分或全部命令及对应命令描述,例如:

shell
openUBMC:/->ipmcset -t se
    -t <target>
        service                 Operate with service
        sensor                  Operate with sensor
        securitybanner          Operate login security banner information
        securityenhance         Operate security enhance
shell
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,配置如下:
json
{
    "Uri": "/cli/v1/service",
    "Interfaces": [
        {
            "Type": "PATCH",
            "Description": "Operate with service"
        }
    ]
}
  • ipmcset -t service -d port对应的Uri为/cli/v1/service/Port,其命令描述为Operate with service,配置如下:
json
{
    "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。命令提示的作用是告诉用户命令的含义及其使用方法,根据实际需求配置即可。

命令提示的格式如下:

shell
Usage: <命令格>
<简单描述>
<参数说明 Name: Description>

Example:
    <示例说明>

例如ipmcset -d fanmode的命令提示为:

shell
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

其对应的配置应该为:

json
{
    "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, 未配置时默认值falsetrue表示必填参数,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的配置为例:

json
{
    "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

json
{
    "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配置为例:

json
{
    "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.SkipQuery.Top。一般情况下都是配置Skip=0, Top=20, 表明一页的数据条数为20条,按q可退出命令,按其它按键继续显示下一页,直到所有条数显示完成,退出命令。 ProcessingFlow只需要配置单次获取的规则,映射器框架和后台组件会执行分页处理,每获取一页就下发一次请求,并且更新传递给资源数的SkipTop的取值。


资源协作接口方法Method格式要求

仍然以ipmcget -d operatelog接口为例,要正确获取指定文本内容并响应,需要满足以下格式要求:

  • 方法入参

    方法入参包含两个字段(接口映射配置中传入字段名称可以不同,但是一定要有该字段,且类型、取值正确)

    • Skip: 表示跳过的条数,与Redfish接口查询参数的$skip含义一致
    • Top: 表示获取的条数,与Redfish接口查询参数的$Top含义一致
  • 方法响应

    方法入参包含两个字段(接口映射配置中传入字段名称可以不同,但是一定要有该字段)

    • Count: 总条数
    • Log: 数组,请求的Top条信息组成的数组
  • 结果顺序

    方法获取结果是按顺序排列的,分页显示则是按倒序打印的。获取数据时会保存该时刻的数据,分页过程中获取数据都是基于调用方法时保存下来的数据。


任务命令

有时资源协作接口方法需要执行较长时间,这时一般会将该方法做异步处理,例如一键收集日志。CLI命令下发任务,并轮询任务进度直至任务完成或异常退出。通用任务机制定义可见《rackmount组件接口说明》资源协作接口映射配置Task章节

ipmcget -d diaginfo接口为例:

shell
openUBMC:/->ipmcget -d diaginfo
Downloading...
100%
Download diagnose info to /tmp/ successfully.

对应接口映射配置样例如下:

json
{
    "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, 属于高危动作,需要预先进行确认操作。

shell
openUBMC:/->ipmcset -d reset
This operation will reboot openUBMC system.
Continue? [Y/N]:

对应的配置为:

json
{
    "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/falseCondition也可以配置成数据引用,引用的来源原则上只允许来自ReqBody。如下述接口映射配置,当ReqBody.option取值为disabled时需要确认。
  • Confirm.Description: Y/N确认时的提示信息。也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
json
"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>:

shell
openUBMC:/->ipmcset -t user -d state -v Test enabled
Input your password:
Enable user:Test successfully.

对应的配置为:

json
{
    "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/falseCondition也可以配置成数据引用,引用的来源原则上只允许来自ReqBody
  • Authentication.Description: 密码鉴权确认时的提示信息。Description也可以配置成数据引用,引用的来源原则上只允许来自ReqBody

输入新密码

部分命令例如新增用户-d adduser, 除了输入当前登录用户的密码外,还需要两次输入新增用户的新密码,并且输入无回显:

shell
openUBMC:/->ipmcset -d adduser -v Test1
Input your password:
Password:
Confirm password:
Add user successfully.

接口映射配置提供无回显输入接口,后台组件封装了两次输入密码的插件。

json
"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 versionEchoes[1]取值为ipmcget/_version, 那么在rackmount代码仓CLI接口回显模板路径下需要有ipmcget/_version文件,其内容如下:

shell
------------------- 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')

    shell
    if xx then
        echo('xxx')
        return
    end