Considering the interconnection with resource collaboration interfaces based on interface definitions, configuration and mapping are introduced to design northbound interfaces (Redfish, Web-backend, CLI, and SNMP) in openUBMC, where an interface mapping configuration mechanism is used. The mechanism parses interface configuration frameworks, maps interface requests to resource collaboration interfaces, and assembles the returned data in corresponding formats. The interface mapping configuration mechanism has the following features:
- Easy customization: Encapsulate interface protocols and use standard resource collaboration interfaces to implement interface configuration.
- Efficient expansion: Use abstract interface data models, establish mapping rules, and modify configurations to expand interfaces.
- Service decoupling: Decouple interfaces from function logic to prevent incorrect interface invocation from affecting service functions.
This document describes configuration rules for common interface mapping. Some rules apply only to a single interface. For details, see the corresponding interface configuration guide.
Interface Support
| Interface | Description |
|---|---|
| Redfish | Machine-machine interface, used to connect to the upper-layer network management system (NMS) |
| Web_backend | Provides backend service support for the web frontend. |
| SNMP | Machine-machine interface, used to connect to early NMS and gradually replaced by Redfish |
| CLI | Man-machine interface, used by users to directly operate devices |
Keywords
Mapping Keywords
| Keyword | Type | Scope of Application | Description |
|---|---|---|---|
| Resources | array | All | Resource collection. Each element in an array describes a resource. |
| Resources.Uri | string | All | 1. Redfish/Web_backend: The original URI remains unchanged. 2. CLI: The URI starts with /cli/v1. The parameters following -t and -d are the third and fourth segments of the route, respectively. If -t does not exist, use _ instead.3. SNMP: The URI starts with /snmp/v1. The OID is the third segment, the command name is the fourth segment, and the read-write mode is the fifth segment. |
| Resources.IgnoreEtags | array | Redfish | Property collection without ETag validation. This field has to be used for shielding when frequently changing properties. Otherwise, the PATCH execution will fail due to property changes. |
| Resources.ResourceExist | object | All | Configuration of resource existence validation process, validating whether dynamic fields in a URI are valid. The key is the data source definition, and the value is the expected validation result. If the value is #WITH, the expected result is that the data exists. If the value is #WITHOUT, the expected result is that the data does not exist. Other fields indicate the actual expected results. |
| Resources.Sequence | array | SNMP | Sequence field configuration, used to define data in the object scenario of the SNMP interface |
| Sequence.Name | string | SNMP | Name of an object property. The value is the same as that defined in the MIB file. |
| Sequence.Type | string | SNMP | Type of an object property, which is the same as that defined in the MIB file. The value can be string, number, integer, object, array or boolean. |
| Sequence.Access | string | SNMP | Access permission of an object property, which is the same as that defined in the MIB file. The value can be Readonly or Readwrite. |
| Sequence.Primary | boolean | SNMP | Indicates whether an object property is the primary key. Multiple properties in the same object may be set as primary keys. The configuration information of this field is the same as that in the MIB file. |
| Resources.Interfaces | array | All | Resource method collection, including GET, PATCH, POST, and DELETE. The method mapping type of a single resource is configured as required. Only one method can be configured for each resource. |
| Interfaces.Type | string | All | Method type. The value can be GET, PATCH, POST or DELETE (case insensitive). The details are as follows:1. Redfish/Web_backend: GET, PATCH, POST and DELETE2. CLI: GET and PATCH. ipmcget corresponds to GET, and ipmcset corresponds to PATCH.3. SNMP: GET and PATCH, corresponding to the obtaining and setting operations, respectively |
| Interfaces.LockdownAllow | boolean | All | Indicates whether setting interfaces (PATCH/POST/DELETE) can be executed when the system is locked. After the system is locked, operations can only be performed when the value of this configuration is true. |
| Interfaces.Usage | string | CLI | If the entered CLI command can uniquely match a specified command, but the parameter following -v does not match, the usage method of the command has to be displayed. This field describes the correct command format. |
| Interfaces.Brief | string | CLI | If the entered CLI command can uniquely match a specified command, but the parameter following -v does not match, the brief description of the command has to be displayed. The description has to be configured in this field, or it will not be displayed. |
| Interfaces.Examples | array | CLI | If the entered CLI command can uniquely match a specified command, but the parameter following -v does not match, the usage example of the command has to be displayed. The example information has to be configured in this field (configuration of multiple examples supported), or it will not be displayed. |
| Interfaces.Description | string | CLI | If the entered CLI command does not match any specified command, commands that are closest to the current input are listed. The description of each command comes from this field. |
| Interfaces.Echoes | array | CLI | Template path for displaying data on a client |
| Interfaces.ReqBody | string | All | Request body definition of a method. Nested configuration is supported for properties, and the next-level properties are described using the keyword Properties. |
| ReqBody.Name | string | All | Property name in a request message body, which is the same as that defined in the external interface. |
| ReqBody.Type | [string, array] | All | Property type in a request message body, which is the same as that defined in the external interface. The value of this field can be string, number, integer, object, array, boolean, or null.If the field type is array, the property value can be of multiple types. |
| ReqBody.Items | [object, array] | All | Defines array elements when a request message body property is an array. The list validation mode array (with a same definition for array elements) can use the object type. The definition takes effect for all properties in the array. The tuple validation mode array (with various definitions for array elements) can use the array type. The definition index corresponds to each index in the request message body property. |
| ReqBody.maxItems | number | All | Defines the maximum number of array elements when a request message body property is an array. |
| ReqBody.minItems | number | All | Defines the minimum number of array elements when a request message body property is an array. |
| ReqBody.uniqueItems | boolean | All | Defines that each array element is unique when a request message body property is an array. By default, arrays can contain duplicate elements. |
| ReqBody.Properties | object | All | Collection of the next-level properties of the current property in a request message body |
| ReqBody.LockdownAllow | boolean | All | Functions the same as the Interfaces.LockdownAllow field. This field modifies a single property in the PATCH interface, instead of the entire interface. |
| ReqBody.Required | boolean | All | Indicates whether a request message body property is mandatory. |
| ReqBody.Description | string | CLI | If the entered CLI command can uniquely match a specified command, but the parameter following -v does not match, the description of the parameter following -v has to be displayed. The description has to be configured in this field, or it will not be displayed. |
| ReqBody.Sensitive | boolean | All | Indicates whether a request message body property is sensitive. Sensitive information is replaced by ****** in error information. |
| ReqBody.Validator | array | All | Validation rules for a request message body property. The property value is valid only when all validation rules in an array are met. |
| Interfaces.Query | object | All | Configures default query parameters. There are restrictions on using Redfish query parameters. |
| Interfaces.RspBody | object | All | Response body of a method |
| Interfaces.Statements | object | All | Definition of statements for data processing |
| Statements.x.Input | [string, array] | All | Source definition of the data to be processed |
| Statements.x.Steps | array | All | Processing process definition, executed in the defined sequence in an array. The execution result of the previous step is the input of the next step. |
| Interfaces.ProcessingFlow | array | All | Entry of the resource collaboration interface, executed in the defined sequence in an array. |
| ProcessingFlow.Path | string | All | Path of the resource collaboration interface, supporting dynamic parameters |
| ProcessingFlow.Interface | string | All | Resource collaboration interface |
| ProcessingFlow.Destination | object | All | Data destination area of the resource collaboration interface, through which data is stored in the temporary storage area. Key: property name of the resource collaboration interface; value: property name of the temporary data storage area |
| ProcessingFlow.Source | object | All | Data source area of the resource collaboration interface, where data from the defined source is stored. Key: property name of the resource collaboration interface; value: data source definition |
| ProcessingFlow.Name | string | All | Name of the resource collaboration interface method |
| ProcessingFlow.Params | array | All | Input parameters of the resource collaboration interface method, the sequence of which is the same as that of the parameters defined in an array |
| ProcessingFlow.CallIf | [object, string] | All | Dynamically determines the ProcessingFlow execution mode, which can be object or string. 1. Object: The key is the data source definition, and the value is the expected validation result. If the value is #WITH, the expected result is that the data exists. If the value is #WITHOUT, the expected result is that the data does not exist. Other fields indicate the actual expected results. The usage of this mode is the same as Resources.ResourceExist.2. String: Use the preset execution mode, which is currently as follows: · CheckUri: executed during resource existence validation, providing data in the temporary storage area |
| ProcessingFlow.Foreach | string | All | Iterates arrays. #INDEX indicates the current number of iterations. Use ${<Array path>[#INDEX]} to reference the array elements of the current iteration. |
| Interfaces.Authentication | object | CLI | Describes whether the command requires authentication. If this keyword is configured, a command will prompt the user to enter the password, and authentication will be performed automatically. |
| Interfaces.Confirm | object | CLI | Describes whether the command requires re-confirmation. If this keyword is configured, a command will prompt the user to complete confirmation. |
| Authentication.Description Confirm.Description | string | CLI | User interaction prompt |
| Authentication.Condition Confirm.Condition | string | CLI | Checks the parameter following -v. The interaction is performed if the result is true. The default value of this field is true.If this field is set to false, the Confirm keyword is used preferentially. |
Mapping Symbols
| Keyword | Description |
|---|---|
${...} | Data is referenced to a variable in the full path mode. The data sources include Uri, ReqBody, Statements, ProcessingFlow[...]/Destination, and Foreach.Examples: · ${Uri/Id}· ${ReqBody/IpAddr}· ${Statements/GetId()}· ${ProcessingFlow[1]/Destination/Name} |
[...] | Array reference. Array variables can be referenced by subscript. In the Foreach scenario, #INDEX indicates the current iteration.Example: ${Statements/GetPath()[#INDEX]} |
() | Used when invoking Statements |
/ | Lower-level property reference |
{{...}} | Global data reference. The referenced data is configured in the config.json file of the interface.Example: {{OemIdentifier}} |
#WITH | Indicates a resource exists in data validation. |
#WITHOUT | Indicates a resource does not exist in data validation. |
Statements Keywords
| Keyword | Description |
|---|---|
| Prefix-Add | Adds the prefix configured in Formula. |
| Prefix-Trim | Deletes the prefix configured in Formula. |
| Suffix-Add | Adds the suffix configured in Formula. |
| Suffix-Trim | Deletes the suffix configured in Formula. |
| Count | Number of elements contained in input properties |
| Convert | Converts the data type. The conversion mode is configured in Formula. Conversion modes: NumberToBool, BoolToNumber, NumberToString, StringToNumber, FloatToInteger, ToHex, and Tohex |
| DateFormat | Converts a timestamp to a date in a specified format. Formula is the array type. The first parameter indicates the specified date format, and the second parameter indicates whether to display the local time zone. |
| L-Pair | Processes array type data and Formula in pairs. The string in Formula serves as the key and the array element serves as the value to assemble an object. |
| Switch | Replaces data. Formula defines the array of replacement rules, where From is a matching item, and To is a replacement item. The rule without a matching item is the default rule.If the input data meets any matching item, it is converted to the replacement item in the replacement rule. Data that does not meet any matching item is considered to meet the default rule. If there is no default rule, the data is not replaced. |
| Expand | The input data serves as URIs for resource expansion. The input URI can be an internal URI. Formula indicates the number of expansion layers. Currently, openUBMC supports only one-layer expansion, that is, Formula is 1. |
| Script | Script-based custom rules, generally used when the code is simple and not coupled with services. Formula indicates the path of the code or the file where the code is located.The global variables that can be used in code include string, math, type, table, ipairs, pairs, next, error, base_messages, custom_messages, tonumber, tostring, cjson, null, lua_nil, Uri, ReqBody, Query, Context, ProcessingFlow, and Input. |
| Plugin | Plugin-based custom rules, generally used for coupled and heavy-load services. Formula is the form of "FileName.FunctionName(...)", where FileName indicates the plugin file name, FunctionName indicates the function name defined in plugins, and ... is the function input parameter.The function input parameter supports the following keywords: Uri, ReqBody, Query, Context, ProcessingFlow, and Input.Global variables that can be used in the plugin code include bus, mdb, require, libroutemapper_utils, mapper_interface, string, math, type, table, ipairs, pairs, next, pcall, xpcall, error, base_messages, custom_messages, tonumber, tostring, cjson, null, and lua_nil. |
Validator Keywords
| Keyword | Description |
|---|---|
| Range | Applies to the integer and number types. Validates the property value range, which includes maximum and minimum values. |
| Length | Applies to the string type. Validates the string length limit, which includes maximum and minimum values. |
| Enum | Applies to the integer, number, and string types. Validates the property enumeration type. |
| Nonempty | Applies to the string type. Validates whether a property is a non-empty string. |
| IPFormat | Applies to the string type. Validates whether a property is in the IP address format. |
| Regex | Applies to the string type. Validates whether a property meets the regular expression matching rule. |
| Script | Script-based custom validation rule |
General Format
General format of interface mapping configuration:
{
"Resources": [
{
"Uri": "xxxx",
"Interfaces": [
{
"Type": "GET/PATCH/POST/DELETE",
"ResourceExist": {xxxx},
"ReqBody": {xxxx},
"RspBody": {xxxx},
"RspHeader": {xxxx},
"Statements": {xxxx},
"ProcessingFlow": [xxxx]
}
]
}
]
}Resources: URI configuration object arrayInterfaces: request configuration array of multipleTypescorresponding to a URIType: request method, which can beGET, PATCH, POST, or DELETEResourceExist: URI validationReqBody: request body configurationRspBody: response body configurationRspHeader: response header configurationStatements: data processingProcessingFlow: mapping configuration for resource collaboration interfaces
URI Validation
URI configuration uses dynamic fields to specify a resource among resources of the same type. Therefore, the URI access validity has to be validated based on whether the resource exists, which functions equally as the interface input parameter validation. For example, in "Uri": "/redfish/v1/Managers/:managersid", :managersid is a dynamic parameter. For rack-mounted models, the valid value is 1. An external system has to access the URI /redfish/v1/Managers/1 to access the correct interface.
"ResourceExist": {
"${Uri/managersid}": "1",
"${Statements/GetName()}": "#WITH",
"${ProcessingFlow[1]/Destination/Valid}": true
}If key==value is determined in each key-value pair configured in the ResourceExist field, the input parameter validation succeeds, all resource existence conditions are met, and the URI validation is successful. In the preceding example, the value of Uri/managersid must be "1" to determine fixed results. Additionally, two other conditions have to be met. #WITH and #WITHOUT indicate whether a property is nil; true and false serve as the determination rules for the bool type value.
The URI validation succeeds only when all the following conditions are met: The value of Uri/managersid is "1", Statements/GetName() is not nil, and the value of ProcessingFlow[1]/Destination/Valid is true. (When the ProcessingFlow configuration is directly or indirectly referenced by ResourceExist, add the configuration "CallIf": "CheckUri".) Note: The PATCH interface invokes the corresponding GET interface before processing. Therefore, ResourceExist does not need to be configured for PATCH.
ReqBody Declaration
A request sent by users may contain a request body. Since the request body is entered by users, the data may not always match the expected format in actual use. For example, a property type must be string, but the user enters a number instead. Therefore, a syntax is required to declare the data content of the request body and perform basic validation on the request body format. Here, ReqBody is used for declaration. (ReqBody declaration is similar to the syntax standards in the JSON Schema official document.)
The following request body is used as an example (assuming UserName is mandatory and can only be set to Administrator or root):
{
"UserName": "root"
}The corresponding ReqBody configuration is as follows:
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"UserName": {
"Type": "string",
"Required": true,
"Validator": [
{
"Type": "Enum",
"Formula": ["Administrator", "root"]
}
]
}
}
}The following describes the rule configuration for request body validation.
Integrity Check
The keyword Required declares whether a request body property is mandatory. The value is true/false, and the default value is false if not configured.
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"PropA": {
"Required": true
},
"PropB": {
"Required": false
},
"PropC": {
"Type": "object",
"Properties": {
"Prop1": {
"Required": true
}
}
}
}
}For example, in the preceding declaration, the request body is valid if it is{"PropA": 1} or {"PropA": 1, "PropB": 2} (integrity check not required for PropC/Prop1 if the PropC object does not exist). The request body is not valid if it is {"PropA": 1, "PropC": {}} or {"PropB": 2}, as the former lacks PropC/Prop1 and the latter lacks PropA.
Data Type Validation
The Type keyword is the foundation of data type validation and can be a string or an array.
- If it is a string, it must be a specified data type. The value can be
array, boolean, integer, number, null, object, or string. - If it is an array of strings, it contains multiple types, with each string specifying a basic type. Each element is unique. In this case, the request body data has to match any of the element types.
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"PropA": {
"Type": "string"
},
"PropB": {
"Type": ["number", "boolean"]
}
}
}For example, in the preceding declaration, the request body {"PropA": "str", "PropB": 1} is valid, and {"PropA": 1, "PropB": "str"} is not valid. The PropA type must be string, and the PropB type can be number or boolean.
In addition to the basic types that are easy to understand, such as boolean, integer, number, null, and string, the following describes the composite types object and array.
Object
object is a mapping type in JSON, which maps keys to values. In JSON, the keys must always be strings. Each of these pairs is usually referred to as a property. The object properties (key-value pairs) are defined using the Properties keyword. The value of Properties is an object array. Each array element is used to declare property features. Keywords such as Type and Required can also be used to configure data types and integrity checks.
Array
Arrays are used for ordered elements. In JSON, each element in an array may be of a different type, and there are two ways in which arrays are generally used:
List validation: a sequence of arbitrary length where each element matches the same schema
Tuple validation: a sequence of fixed length where each element may have a different schema
List validation: A list contains keywords such as
Items, minItems, maxItems, and uniqueItems.Items: Defines single-element validation in a list. Keywords such asTypecan be used.maxItems: Defines the maximum number of elements in a list, which is not validated by default.minItems: Defines the minimum number of elements in a list, which is not validated by default.uniqueItems: Defines whether each array element must be unique. If the value is set totrue, each array element must be unique. If it is set tofalse, an array can contain duplicate elements. The default value isfalse.json"ReqBody": { "Type": "object", "Required": true, "Properties": { "PropA": { "Type": "array", "Items": { "Type": "number" }, "minItems": 2, "maxItems": 5, "uniqueItems": true } } }In the preceding configuration, the
PropAproperty is an array, where each element is a number. The array contains at least two elements and at most five elements. Each element is unique.Tuple validation
Tuple validation is useful when the array is a collection of elements where each has a different schema. For example, a 3-tuple [ID, user name, locked or not] has a different schema for each field:
Id: ID, which must be a numberUserName: user name, which must be a stringLocked: locked or not, which must be a boolean value (true/false)The Items keyword is set to an array, where each element is a schema corresponding to each index of the tuple. That is, the first element in an array validates the first input element, the second element validates the second input element, and so on.
json"ReqBody": [ { "Name": "PropA", "Type": "array", "Items": [ { "Type": "number" }, { "Type": "string" }, { "Type": "boolean" } ] }, ]
In the preceding example, if the value of PropA is [10086, 10001, true], it is not valid, as the second element must be a string, but 10001 is a number. [10086, "root", true], [10086, "root"], and [10086, "root", true, "str"] are valid.
Data Content Validator
Sometimes, simple validation is required for the content of request body properties. For example, the string length must be within a specified range or a group of fixed values. Here, the Validator keyword declares the validation of the related content. The validation type is represented by the Type field. The following sections describe the supported Type.
{
"Name": "Prop",
"Validator": [
{
"Type": xxx,
"Formula": xxx
}
]
}Enum
{
"Type": "Enum",
"Formula": ["Administrator", "root", "Admin"]
}Enumeration validation. Formula configures value arrays within a specified range. Each element in the array is unique. This can validate simple data types, such as boolean, integer, number, null, and string. (Complex structures like object or array can also be configured, but are not recommended. The complex structures must be declared.)
Length
{
"Type": "Length",
"Formula": [1, 16]
}Validates the string length. Formula specifies the upper and lower limits (closed interval). If no limits are required, set it to null.
Nonempty
{
"Type": "Nonempty"
}Non-empty string validation. The value "" is not valid.
Range
{
"Type": "Range",
"Formula": [1, 16]
}Number range validation, which can be used for the integer and number data types. Formula specifies the upper and lower limits (closed interval). If no limits are required, set it to null.
Regex
{
"Type": "Regex",
"Formula": "^xx[0-9]"
}Regular expression matching validation (standard regular expressions, not Lua regular expressions), which can be used for the string data type. In the preceding example, the value "xx1" is valid, while "xxx" is not valid.
IPFormat
{
"Type": "IPFormat",
}IP address format validation, which can be used for the string data type
Script
{
"Type": "Script",
"Formula": "if Input % 5 == 0 then local err = base_messages.PropertyValueFormatError(Input, PropertyName) err.RelatedProperties = {'#/' .. PropertyName} error(err) end return true"
}Reuses the Script in data processing. For details about the usage rules, see Data Processing Statements. If the validation fails, execute error to throw the errors, which must be common errors defined by BMC. If the validation succeeds, return true or nil. Compared with the data processing Script, the environment variables are changed as follows:
Input: value of the property to be validatedPropertyName: new variable, indicating the name of the property to be validated, for example,Oem/openubmc/PropAProcessingFlow: The resource collaboration interface is not accessed during validation. Therefore, this variable is deleted.
Sensitive Information Masking
If a request body contains sensitive data, the field value in the error message must be masked as ******. The Sensitive keyword is introduced to indicate that the property value has to be masked, preventing sensitive data from being directly displayed in the Message information. Sensitive information must be configured with "Sensitive": true. Sensitive information in openUBMC includes but is not limited to user passwords and session tokens.
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"Password": {
"Type": "string",
"Sensitive": true
}
}
}If the request body value is {"Password": 111}, the type validation fails. The obtained error information is as follows:
"MessageId": "Base.1.0.PropertyValueTypeError",
"Message": "The value ****** for the property Password is of a different type than the property can accept.",
"MessageArgs": [
"******",
"Password"
],
...RspBody Definition
RspBody is a keyword for configuring the response body format of an interface. It assembles the property values obtained from the resource collaboration interface or data processing, and returns the values to the user side as command output of interface invocation. The following is an example RspBody configuration:
"RspBody": {
"@odata.context": "/redfish/v1/$metadata#AccountService/Accounts/Members/$entity",
"Name": "User Account",
"UserName": "${ProcessingFlow[1]/Destination/UserName}",
"Oem": {
"openubmc": {
"LoginRule": null
}
}
}${ProcessingFlow[1]/Destination/UserName} indicates that data must be obtained from resource collaboration interfaces. For details, see the next section ProcessingFlow Configuration for Resource Collaboration Interface Mapping. If the obtained value is "Administrator", the response body received by the user is as follows:
{
"@odata.context": "/redfish/v1/$metadata#AccountService/Accounts/Members/$entity",
"Name": "User Account",
"UserName": "Administrator",
"Oem": {
"openubmc": {
"LoginRule": null
}
}
}ProcessingFlow Configuration for Resource Collaboration Interface Mapping
The general format is as follows:
"ProcessingFlow": [
{
"Type": "Property/Method/List/Task/Paging"
"Path": "xx",
"Interface": "xxx",
"Name": "xxx",
"Params": [xxx],
"Destination": {xxx},
"Source": {xxx},
"CallIf": {xxx},
"Foreach": "xxx"
},
xxx
]Common fields:
ProcessingFlow: The value must be an object array. Each object specifies a resource collaboration interface mapping. The object mapping data is executed in sequence.Type: mapping types, includingProperty/Method/List/Task/Paging. For details, see the following sections (Paging used by CLI interfaces only).Path: MDS objectInterface: resource collaboration interfaceName: method nameParams: method parameterDestination: return value configurationSource: used when setting propertiesCallIf: Indicates whether to invoke resource collaboration interfaces, applying to all mapping types. For details about the rules, see CallIf.Foreach: The resource collaboration interface is invoked for multiple times. This field applies to all mapping types. For details about the rules, see Foreach.
Property
Obtain properties.
json{ "Type": "Property", "Path": "/bmc/kepler/Managers/1/EthernetInterfaces/Ipv4", "Interface": "bmc.kepler.Managers.EthernetInterfaces.Ipv4", "Destination": { "IpMode": "IpModeIpv4", "IpAddr": "IpAddrIpv4", "SubnetMask": "SubnetMask" } }, { "Type": "Property", "Path": "/bmc/kepler/Managers/1/EthernetInterfaces/Ipv6", "Interface": "bmc.kepler.Managers.EthernetInterfaces.Ipv6", "Destination": { "IpMode": "IpModeIpv6" } }Destinationconfigures a series of key-value pairs.keyindicates the property name on the resource collaboration interface. Obtain the property and rename it asvalue. Since different resource collaboration interfaces may have the same property name, renaming can avoid naming conflicts. In the preceding example,${ProcessingFlow[1]/Destination/IpModeIpv4}indicates that the IpMode property of the IPv4 resource collaboration interface is obtained, and${ProcessingFlow[2]/Destination/IpModeIpv6}indicates that the IpMode property of the IPv6 resource collaboration interface is obtained.Set properties.
json{ "Type": "Property", "Path": "/bmc/kepler/Managers/1", "Interface": "bmc.kepler.Managers.Ntp", "Source": { "Preferred": "${ReqBody/PreferredServer}" } }The structure is similar to that of property obtaining. The keyword is changed to
Source. In the preceding example, thePreferredServerproperty value in the request body is set to thePreferredproperty of the resource collaboration interface.
Method
{
"Type": "Method",
"Path": "/bmc/kepler/Systems/Events",
"Interface": "bmc.kepler.Systems.Events",
"Name": "GetSelInfo",
"Params": [
"123"
],
"ContextParams": {
"SystemId": "1"
},
"Destination": {
"Version": "Version",
"CurrentEventNumber": "CurrentEventNumber",
"MaxEventNumber": "MaxEventNumber"
}
}Name: method nameParams: method parameter. A default value can be used to indicate there is no parameter (excluding context parameters).ContextParams: context parameter configuration, corresponding to the a{ss} context parameter required for invoking methods in resource collaboration interfacesDestination: similar to the configuration for obtaining properties. The key on the left corresponds to the variable name of the method return value, and the value on the right corresponds to the variable name configured by developers.
Using the preceding configuration as an example, when busctl is used to invoke methods in actual environments, the following information is returned:
> busctl --user call bmc.kepler.event /bmc/kepler/Systems/Events bmc.kepler.Systems.Events GetSelInfo a{ss} 0
suu "1.0.0" 0 10000The return value is suu "1.0.0" 0 10000. suu indicates that the subsequent data types are String, U32, and U32 in sequence. The Version, CurrentEventNumber, and MaxEventNumber fields are not displayed.
Check the declaration of GetSelInfo (the mdb_interface repository contains the return field declaration of resource collaboration interfaces). rsp contains the return field declaration.
"GetSelInfo" :{
"req": {},
"rsp": {
"Version": {
"baseType": "String"
},
"CurrentEventNumber": {
"baseType": "U32"
},
"MaxEventNumber": {
"baseType": "U32"
}
}
}When using proxy objects to invoke method, the return value is encapsulated in a structured manner. For example, the return value of the GetSelInfo method is as follows:
{
Version = "1.0.0",
CurrentEventNumber = 0,
MaxEventNumber = 1000
}List
{
"Type": "List",
"Path": "/bmc/kepler/Managers/1/NetworkProtocol",
"Interface": "bmc.kepler.Managers.NetworkProtocol.Protocol",
"Params": [1],
"Destination": {
"Members": "service_table"
}
}Obtain the resource collaboration interface collection.
Interface: If this field is not configured, all resource collaboration interfaces of the MDS sub-object are obtained. If configured, resource collaboration interfaces that contain Interface are obtained.Params: configured as required. Params[1] indicates the retrieval depth. For example, 1 indicates the MDS sub-object, and 2 indicates the MDS sub-sub-object. If Params is not configured, the default depth is 1.
In the preceding example, the /bmc/kepler/Managers/1/NetworkProtocol resource has the following MDS sub-objects (all resource collaboration interfaces of the sub-objects have bmc.kepler.Managers.NetworkProtocol.Protocol):
> busctl --user tree bmc.kepler.nsm
└─/bmc
└─/bmc/kepler
└─/bmc/kepler/Managers
│ └─/bmc/kepler/Managers/1
│ └─/bmc/kepler/Managers/1/NetworkProtocol
│ ├─/bmc/kepler/Managers/1/NetworkProtocol/HTTP
│ ├─/bmc/kepler/Managers/1/NetworkProtocol/HTTPS
│ ├─/bmc/kepler/Managers/1/NetworkProtocol/KVMIPAs a result, the following key-value pairs are added to the Destination:
"service_table": [
"/bmc/kepler/Managers/1/NetworkProtocol/HTTP",
"/bmc/kepler/Managers/1/NetworkProtocol/HTTPS",
"/bmc/kepler/Managers/1/NetworkProtocol/KVMIP",
......
]Task
{
"Type": "Task",
"Path": "/bmc/kepler/Managers/1/LogServices",
"Interface": "bmc.kepler.Managers.LogServices",
"Name": "Dump",
"Params": [
0
],
"Destination": {
"TaskId": "TaskId"
},
"PostTaskProcess": [
{
"Type": "ChangeOwner",
"Params": [
"/tmp/web/operate.log"
]
}
]
}Task is a special Method used for asynchronous execution.
PostTaskProcess: post-task operation, configuring the specified operation to be performed after a task is executed. Type indicates the operation type. Currently, the owner and permission of a file can be modified after the file is exported.ChangeOwner: Changes the file owner to the current user and the file permission to 600. The parameter is the absolute path of the local file (remote file paths not supported).
Note: Multiple Task methods can be configured in a ProcessingFlow, but only one of them takes effect. Use CallIf to control the Task to be executed.
CallIf
"CallIf": {
"${ReqBody/PropA}": "#WITH"
"${ReqBody/PropB}": "#WITHOUT",
"${ReqBody/PropC}": "str1",
"${Uri/id}": 1
}The CallIf condition is met and the corresponding Methods are executed only when all properties are valid. #WITH and #WITHOUT are introduced to indicate whether a property exists. The preceding example indicates that the CallIf condition is met only when all the four conditions are met: ReqBody/PropA exists, ReqBody/PropB does not exist, the value of ReqBody/PropC is "str1", and the value of Uri/id is 1.
Foreach
"ReqBody": {
"Type": "object",
"Required": true,
"Properties": {
"SnmpTrapNotification": {
"Type": "object",
"Properties": {
"TrapServer": {
"Type": "array",
"Items": {
"Type": "object",
"Properties": {
"TrapServerPort": {
"Type": "number"
}
}
}
}
}
}
}
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/EventService/Subscriptions/Snmp/Nmses/${#INDEX}",
"Interface": "bmc.kepler.EventService.Subscriptions.Snmp.Nms",
"Source": {
"Port": "${ReqBody/SnmpTrapNotification/TrapServer[#INDEX]/TrapServerPort}"
},
"Foreach": "${ReqBody/SnmpTrapNotification/TrapServer}"
}
]In the preceding configuration example, SnmpTrapNotification/TrapServer in the request body is an array. The properties of bmc.kepler.EventService.Subscriptions.Snmp.Nms must be set for multiple times based on the array size.
{
"SnmpTrapNotification": {
"TrapServer": [
{
"TrapServerPort": 3162
},
{
"TrapServerPort": 3163
},
{
"TrapServerPort": 3164
},
{
"TrapServerPort": 3165
}
]
}
}Assume that a request body is configured as above and the size of the SnmpTrapNotification/TrapServer array is 4. The statement "Foreach": "${ReqBody/SnmpTrapNotification/TrapServer}" indicates that the properties must be set for four times (Foreach can also configure the number directly). For the first time, the Path is /bmc/kepler/EventService/Subscriptions/Snmp/Nmses/1, and the data source is ${ReqBody/SnmpTrapNotification/TrapServer[1]/TrapServerPort}. (#INDEX is used together with Foreach and will be replaced with the number of iterations.)
Data Reference
Data reference: Some positions (DEST) need to use data from external sources (SRC). For example, the response body needs to use the data on the resource collaboration interface collection. To simplify data reference and obtain SRC data in the same format, the following rule is defined: ${var} indicates that the value of var comes from external data SRC. For example, ${ReqBody/xxx} indicates that the xxx property in the request body ReqBody is referenced. The data type obtained through data reference is JsonObject, that is, ordered JSON.
Data Source
For interface mapping configuration, the external data is as follows:
Uri: dynamic fields contained in a URIQuery: query parameterReqBody: data in the request bodyReqBodyOriginal: original data in the request body. Abnormal data is deleted during ReqBody validation and cannot be obtained during ProcessingFlow configuration. In this case, ReqBodyOriginal can be obtained.ReqHeader: data in the request headerContext: context information, including the following fields:- CLI: Interface (value: CLI), UserName, ClientIp, and Privilege
- Redfish user password authentication mode: Interface (value: Redfish), UserName, ClientIp, Privilege, RoleId, and AccountId
- Redfish session authentication mode: In addition to the fields of the user password authentication mode, the following fields are also supported: AuthType, Token, and SessionId.
- Web_backend: Interface (value: WEB), UserName, ClientIp, Privilege, AccountId, RoleId, AuthType, Token, and SessionId
- SNMP: Interface (value: SNMP), UserName, ClientIp, and Privilege
ProcessingFlow[].Destination: data obtained from resource collaboration interfaces
URI Configuration
- Fixed properties
(Non–data reference) Ideally, most URI values should be fixed pure data.
"RspBody": {
"Prop": "redfish/v1/Systems/1"
}- Simple mode
The framework replaces ${var} with the value of var in the external data. For example, if the value of var is 1, the value of Prop is "redfish/v1/Systems/1".
"RspBody": {
"Prop" : "redfish/v1/Systems/${var}"
}- Statements
In most cases, external data has to be processed before usage."${Statements/Prop()}" indicates that the data is configured in Statements.Prop. (Note: Statements/Prop is followed by a pair of parentheses.)Statements.Prop indicates the value of the data referencing var after being processed by multiple Steps. Statements support multiple types of configurations. For details, see Data Processing Statements.
"RspBody": {
"Prop" : "${Statements/Prop()}"
},
"Statements": {
"Prop": {
"Input": "${var}"
"Steps": [ {xxxx} ]
}
}Data Processing Statements
Data processing: Data from resource collaboration interfaces has to be processed before usage.
"Statements": {
"Prop": {
"Input": "${var}"
"Steps": [
{
"Type": "xxxx",
"Formula": "xxxxx"
},
{
"Type": "xxxx",
"Formula": "xxxxx"
},
]
}
}Input: data source to be processed. The value must reference external data.
Steps: array type. Multiple types of processing logic can be configured. Input is the input of Steps[1], the output of Steps[1] is the input of Steps[2], and so on. The output of Steps[n] is the final processing result.
Steps[].Type: Specifies the data processing type. For details, see the following sections.
Steps[].Formula: data processing formula and rule. Nested data reference configuration is supported.
Convert
{
"Type": "Convert",
"Formula": "StringToNumber"
}Data type conversion. In the preceding example, a string is converted to a number. For example, the output of "12" is 12. Formula specifies the converted types. The following values are supported:
NumberToBool: Converts a number to a boolean value (0 converted to false, and non-zero values converted to true).BoolToNumber: Converts a boolean value to a number (false converted to 0, and true converted to 1).NumberToString: Converts a number to a string.StringToNumber: Converts a string to a number.FloatToInteger: Converts a floating point integer to an integer. If the fractional part is not 0, the value is converted to nil. For example, the output of 3.1 is nil.ToHex: Converts a number to a hexadecimal string. The letters are in uppercase.Tohex: Converts a number to a hexadecimal string. The letters are in lowercase.
If the input data type does not match the pre-conversion type declared by Formula, the output is nil.
Count
{
"Type": "Count"
}The input data must be an array. The array size is calculated, and the Formula field is not required. For example, the output of ["1", "2", "3"] is 3.
Expand
{
"Type": "Expand",
"Formula": "1"
}The input data must be an accessible URI string. The default value of Formula is "1".
Expand is used to replace a URI with its corresponding response body.
Note: If the result of Expand is not a URI which is expected to be accessed independently, do not start with /redfish or /UI/Rest. Use /expand or /bmc/kepler instead. In this way, the URI will be intercepted directly by nginx during access and will not be redirected to the interface layer or service layer.
If the response body of /redfish/v1/AccountService/Accounts/2 is as follows:
{
"UserName": "Administrator",
"RoleId": "Administrator",
"Locked": false,
}When the input is /redfish/v1/AccountService/Accounts/2, the output is the same as the above response body.
The input data can also be an array of strings. Each string must be an accessible URI. The Expand operation replaces each string with the corresponding response body of the URI. If the response body of /redfish/v1/AccountService/Accounts/3 is as follows:
{
"UserName": "Admin",
"RoleId": "Administrator",
"Locked": false,
}When the input is ` ["/redfish/v1/AccountService/Accounts/2", "/redfish/v1/AccountService/Accounts/3"] , the output is as follows:
[
{
"UserName": "Administrator",
"RoleId": "Administrator",
"Locked": false,
},
{
"UserName": "Admin",
"RoleId": "Administrator",
"Locked": false,
}
]During path traversal processing of resource collaboration interfaces, the URI of the resource collaboration interface can be added to obtain the response data.
{
"Uri": "/bmc/kepler/AccountService/Accounts/:id",
"Interfaces": [
{
"Type": "Get",
"RspBody": {
"UserName": "${ProcessingFlow[1]/Destination/Id}",
"RoleId": "${ProcessingFlow[1]/Destination/Source}",
"Locked": "${ProcessingFlow[1]/Destination/Destination}",
},
"ProcessingFlow": [
{
"Type": "Property",
"Path": "/bmc/kepler/AccountService/Accounts/${Uri/id}",
"Interface": "bmc.kepler.AccountService.ManagerAccount",
"Destination": {
"UserName": "UserName",
"RoleId": "RoleId",
"Locked": "Locked"
}
}
]
}
]
}The input data can also be an object array. Each object has only one key-value pair. The key must be @odata.id, and the value must be an accessible URI string. The Expand operation replaces each object with the corresponding response body of the URI.
L-Pair
{
"Type": "L-Pair",
"Formula": "@odata.id"
}The input must be an array, and Formula can be any string.L-Pair uses Formula as key and the array element as value to assemble objects and replace the original elements.
For example, if the input is ["/redfish/v1/System/Blade1", "/redfish/v1/System/Blade2", "/redfish/v1/System/Blade3"], and Formula is @odata.id, the output is as follows:
[
{"@odata.id": "/redfish/v1/System/Blade1"},
{"@odata.id": "/redfish/v1/System/Blade2"},
{"@odata.id": "/redfish/v1/System/Blade3"}
]Prefix-Add
{
"Type": "Prefix-Add",
"Formula": "/redfish/v1/"
}Formula is the prefix string to be added.
- If the input is a string or a number, the output is a string consisting of Formula and the input data.
- If the input is an array, the Formula prefix is added to each element in the array as the output.
Assume that the value of Formula is /redfish/v1/. If the input is "System", the output is "/redfish/v1/System". If the input is ["System/Blade1", "System/Blade2"], the output is ["/redfish/v1/System/1", "/redfish/v1/System/Blade2"].
Prefix-Trim
{
"Type": "Prefix-Trim",
"Formula": "/bmc/kepler/"
}Prefix-Trim is used to delete a prefix. The usage rules are similar to Prefix-Add.
Suffix-Add
{
"Type": "Suffix-Add",
"Formula": "/Function/1"
}Suffix-Add is used to add a suffix. Formula is the suffix string to be added. In the preceding example, if the input is "PCIeCard", the output is "/PCIeCard/Function/1". If the input is ["PCIeCard1", "PCIeCard2"], the output is ["/PCIeCard1/Function/1", "/PCIeCard2/Function/1"].
Suffix-Trim
{
"Type": "Suffix-Trim",
"Formula": "/Function/1"
}Suffix-Trim is used to delete a suffix. The usage rules are similar to Suffix-Add.
Switch
{
"Type": "Switch",
"Formula": [
{
"Case": "Administrator",
"To": 1
},
{
"Case": "root",
"To": 2
},
{
"Case": null,
"To": 3
},
{
"To": 0
}
]
}Data replacement, similar to the switch statements of C/Java. Case is a branch, and To indicates the replacement data (with break by default).
Only the To configuration corresponds to the default branch, which can be default and must be placed at the end.
In the preceding example:
If the input is "Administrator", the output is 1.
If the input is "root", the output is 2.
If the input is null or nil (empty data), the output is 3.
If the input is "Admin", the output is 0.
DateFormat
{
"Type": "DateFormat",
"Formula": ["%Y-%m-%dT%H:%M:%S", true]
}The input is a timestamp (a number or a numeric string), and the output is a time string.Formula[1] specifies the time format (see the parameter format of the os.date function in Lua). If this parameter is not set or is set to null, use the default value "%Y-%m-%dT%H:%M:%S".Formula[2] indicates whether to display the time zone. The default value is false.
In the preceding example, if the input is 1 and the system time zone is UTC+8, the output is "1970-01-01T08:00:01+08:00".
Script
{
"Type": "Script",
"Formula": "return ReqBody.Option == 'all'"
}The content of Formula is a Lua script, which can process any complex logic (not recommended for use with other processing types).
In the preceding example, if Option of ReqBody is "all", the output is true. Otherwise, the output is false.
For a long script, if it is inconvenient to read the content in one line, the script can be saved in an external file, and the file name can be configured using Formula. For example, if the value is get_operate_log.lua, the script/get_operate_log.lua file must exist in the same-level directory of the configuration file.
Note: Reduce the use of Script unless complex logic cannot be configured. Interface mapping configuration implements interfaces in the configuration mode, while Script is actually using code.
Plugin
{
"Type": "Plugin",
"Formula": "orchestrator.bios.get_registry_version(Uri.systemid)"
}The content of Formula is a function. Input parameters are supported and can use data sources like ReqBody.Plugin can process services with complex logic (not recommended for use with other processing types).
For example, if Redfish plugins are stored in the /opt/bmc/apps/redfish/interface_config/plugins directory, the preceding configuration requires that the orchestrator/bios.lua file exists in the directory and the file has the get_registry_version function.
Note: Reduce the use of Plugin, which provides functions that can be invoked. In essence, it is also using code.
Differences Between Script and Plugin
Script is used for pure logic processing. Formula configures a Lua script or file name, which cannot be reused. Plugin is used to compile service-related logic. Formula configures function invocation, which requires corresponding function implementation and can be reused. The following table lists the data variables that can be used in Script and Plugin.
| Variable | Description | Script Environment Variable | Plugin Function Input Parameter | Plugin Environment Variable |
|---|---|---|---|---|
| bus | dbus | ✔ | ||
| mdb | MDB library | ✔ | ||
| require | Lua built-in function | ✔ | ||
| libroutemapper_utils | C library encapsulated by interface mapping configuration | ✔ | ||
| mapper_interface | Lua library encapsulated by interface mapping configuration | ✔ | ||
| string | Lua standard library | ✔ | ✔ | |
| math | Lua standard library | ✔ | ✔ | |
| type | Lua built-in function | ✔ | ✔ | |
| table | Lua standard library | ✔ | ✔ | |
| ipairs | Lua built-in function | ✔ | ✔ | |
| pairs | Lua built-in function | ✔ | ✔ | |
| next | Lua built-in function | ✔ | ✔ | |
| pcall | Lua built-in function | ✔ | ||
| xpcall | Lua built-in function | ✔ | ||
| error | Lua built-in function | ✔ | ✔ | |
| base_messages | Basic message definition | ✔ | ✔ | |
| custom_messages | Custom error message | ✔ | ✔ | |
| tonumber | Lua built-in function | ✔ | ✔ | |
| tostring | Lua built-in function | ✔ | ✔ | |
| cjson | cjson library | ✔ | ✔ | |
| null | cjson.null | ✔ | ✔ | |
| lua_nil | Nil value of Lua. If the RspBody property is unable to be obtained, the value is converted to null. If the property is not displayed, use lua_nil. | ✔ | ✔ | |
| Uri | Data source | ✔ | ✔ | |
| ReqBody | Data source | ✔ | ✔ | |
| Query | Data source | ✔ | ✔ | |
| Context | Data source | ✔ | ✔ | |
| ProcessingFlow | Data source | ✔ | ✔ | |
| Input | Input of Steps[ ] | ✔ | ✔ |
LockdownAllow System Lock Validation
LockdownAllow configures whether an operation is allowed when the system is locked. The value true indicates that the operation is allowed, while the value false indicates that the operation is not allowed. Interface- and property-level configurations are supported. The inner layer can overwrite the outer layer. The default value is false if this parameter is not configured. The following is an example configuration:
{
"Uri": "/redfish/v1/AccountService",
"Interfaces": [
{
"Type": "PATCH",
"LockdownAllow": false,
"Properties": {
"Oem": {
"Type": "object",
"Properties": {
"openubmc": {
"Type": "object",
"Properties": {
"SystemLockDownEnabled": {
"LockdownAllow": true,
},
"SecurityBannerEnabled": {
"Type": "boolean",
}
}
}
}
}
}
}
]
}