Redfish定制指南(开发中)
更新时间: 2025/07/22
在Gitcode上查看源码

本文主要介绍如何在定制仓定制Redfish服务相关内容

目前Redfish的插件机制主要用于以下两种场景:

  • 定制Redfish接口的响应内容,包括响应体和响应头;
  • 定制Redfish接口的请求参数,包括请求体、请求头和查询参数。

构建过程搭建

NOTE

下述说明中用<>包裹起来的是变量,变量定义如下:

CUSTOMER: 定制的产商名称

确保定制仓中存在custom_request_response.lua文件,且该文件在bmc上位于:

shell
/opt/bmc/extend/<CUSTOMER>/apps/<CUSTOMER>/plugins/redfish/custom_request_response.lua

可参考如下步骤实现:

  1. 在定制仓中,在src目录下建立plugins/redfish/custom_request_response.lua文件
  2. CMakeLists.txt文件中,添加如下命令,用于将定制仓中plugins文件夹以及下面的文件放到/opt/bmc/extend/<CUSTOMER>/apps/<CUSTOMER>/中:
cmake
    set(APP_INSTALL_DIR opt/bmc/extend/<CUSTOMER>/apps/<CUSTOMER>)
    install(DIRECTORY src/plugins DESTINATION ${APP_INSTALL_DIR} OPTIONAL)

定制Redfish接口的响应内容

custom_request_response.lua文件中返回rsp_postprocess函数,该函数用于实现响应内容定制。

传入参数

参数名称参数类型参数说明
codeintHTTP响应码
bodystring响应体
headertable响应头
manufacturestring定制化产商名称

返回值

NOTE

返回顺序从上往下

参数名称参数类型参数说明
rsp_bodystring定制后的响应体
rsp_headertable定制后的响应头

具体示例

在Redfish响应体里:

  • 新增Status属性;
  • 在header里面删除charset=utf-8

custom_request_response.lua文件示例如下:

lua
local cjson = require 'cjson'
local http = require 'http'

local function rsp_postprocess(code, body, header, manufacture)
    local rsp_body
    -- 将body转化为table进行定制
    if body ~= nil and body ~= '' then
        rsp_body = cjson.json_object_ordered_decode(body)
    else
        rsp_body = cjson.json_object_new_object()
    end
    if not rsp_body.Oem then
        rsp_body.Oem = cjson.json_object_new_object()
    end
    if not rsp_body.Oem[manufacture] then
        rsp_body.Oem[manufacture] = cjson.json_object_new_object()
    end

    -- 假设-1表示url执行失败
    local status = -1
    -- 判断响应码是否为2xx,若为2xx且响应体没有错误则设置status的值为0,即成功
    if code >= http.HTTP_OK and code < http.HTTP_SPECIAL_RESPONSE then
        -- 若是patch接口设置多个请求体,在部分成功时会返回200,同时返回@Message.ExtendedInfo字段展现错误信息。此时也视为失败。
        if not rsp_body['@Message.ExtendedInfo'] then
            status = 0
        end
    end
    -- 在oem中加上status
    rsp_body.Oem[manufacture].Status = status

    -- 在响应头中修改Content-Type
    local rsp_header = header ~= nil and header or {}
    rsp_header['Content-Type'] = 'application/json'

    -- 返回时记得将响应体转化为string类型
    return cjson.json_object_ordered_encode(rsp_body), rsp_header
end

return {
    ...
    ['rsp_postprocess'] = rsp_postprocess
}

定制前:

json
// 响应体:
{
    ...
    "oem": {
        "openubmc": {
            "xxxx": yyyy
        }
    }
}

// header:
{
    "Content-Type": "application/json;charset=utf-8"
}

定制后:

json
// 响应体:
{
    ...
    "oem": {
        "openubmc": {
            "xxxx": yyyy,
            "Status": 0
        }
    }
}

// header:
{
    "Content-Type": "application/json"
}

定制Redfish接口的请求参数

custom_request_response.lua文件中返回get_req_param函数,该函数用于实现请求参数定制。具体属性见下表

传入参数

参数名称参数类型参数说明
reqtable请求内容,包含body、header、query、url、method和path

req数据体的定义:

参数名称参数类型参数说明
bodystring请求体
headertable请求头
querystring查询参数
urlstring资源标识,包含路径和查询参数
methodstring请求方法
pathstring路径参数,本次请求的资源路径(不含查询参数)

返回值

NOTE

返回顺序从上往下

参数名称参数类型参数说明
req_bodystring定制后的请求体
req_headertable定制后的请求头
req_querytable定制后的查询参数

具体示例

在Redfish请求体里:

  • 修改DeliveryRetryAttempts属性的输入;
  • header里面修改Authorization
  • 在查询参数中添加"$Expand=."

custom_request_response.lua文件示例如下:

lua
local cjson = require 'cjson'
local urllib = require 'http.url'

local function build_query(params)
    local parts = {}
    for key, value in pairs(params) do
        if type(value) == 'table' then
            for _, v in ipairs(value) do
                table.insert(parts, tostring(key) .. "=" .. tostring(v))
            end
        else
            table.insert(parts, tostring(key) .. "=" .. tostring(value))
        end
    end
    return table.concat(parts, "&")
end

local function get_req_param(req)
    -- 若是请求体中含有DeliveryRetryAttempts属性,则修改为5
    local req_body
    if req.body == nil or req.body == '' then
        req_body = cjson.json_object_new_object()
    else
        req_body = cjson.json_object_ordered_decode(req.body)
    end
    if req_body.DeliveryRetryAttempts then
        req_body.DeliveryRetryAttempts = 5
    end
    req_body = cjson.json_object_ordered_encode(req_body)

    -- 向请求头中添加Authorization
    local req_header = req.header
    req_header['Authorization'] = 'Basic xxxxxxxxxx'

    -- 向查询参数中添加"$Expand=."
    local req_query = req.query
    local params = urllib.parse_query(req_query or '')
    params['$Expand'] = '.'
    req_query = build_query(params)

    return req_body, req_header, req_query
end

return {
    ...
    ['get_req_param'] = get_req_param
}

定制前:

json
// 请求URL:"https://ip/redfish/v1"

//请求体
{
    "DeliveryRetryAttempts": 3
}

// header
{
    "Authorization": "Basic yyyyyyyyyy"
}

定制后:

json
// 请求URL:"https://ip/redfish/v1?$Expand=."

//请求体
{
    "DeliveryRetryAttempts": 5
}

// header
{
    "Authorization": "Basic xxxxxxxxxx"
}