Northbound Interface Mapper Adaptation Guide
Understanding the Northbound Interface Mapper Model
Model Design Goals
Northbound interfaces are standardized management interfaces provided by the BMC. Their core design goal is to implement abstraction and service-oriented hardware resources, and support flexible docking with upper-layer management protocols and ecosystem partners. The northbound interface mapper is a rackmount module that maps internal BMC data to the standardized interfaces provided by the BMC for external systems.
Main Content
The northbound interface mapper provides northbound interfaces such as Redfish, web, CLI, SNMP and IPMI.
Visit rackmount to obtain the code.
Configuring Northbound Interfaces
To configure a new interface, you need to obtain the code corresponding to the current version. First, find the rackmount library of the node used by the current product in manifest.yaml and download the corresponding node code.
New Configuration for the Redfish Interface
The Redfish interface is located in rackmount\interface_config\redfish.
Example: To add a query interface for the WelcomeMessage property of my_app (an existing community example), assume that the following D-Bus exists and contains the WelcomeMessage property:
~ ~ $ busctl --user introspect bmc.kepler.my_app /bmc/demo/MyMDSModel/1 | cat
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
bmc.demo.OpenUBMC.Community interface - - -
.GetRepoURL method a{ss}u s -
.WelcomeMessage property s "hello" emits-change writable
bmc.kepler.Object.Properties interface - - -
...
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.ObjectManager interface - - -
.GetManagedObjects method - a{oa{sa{sv}}} -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -If the expected new path is /redfish/v1/Chassis/1/Myapp, perform the following steps:
Search for
ThresholdSensorsin the existinginterface_config/redfish/mapping_config/Chassis/Chassis.jsonfile, and add the following nearby:json"MyApp": { "@odata.id": "/redfish/v1/Chassis/${Uri/chassisid}/MyApp" },The purpose is to display the
MyApplink when the/redfish/v1/Chassis/1path is accessed.Search for
ThresholdSensorsin theinterface_config\redfish\mapping_config\AccountService\PrivilegeMap\PrivilegeMap.jsonfile, and add the following nearby:json{ "Entity": "MyApp", "OperationMap": { "GET": [ { "Privilege": [ "Login" ] } ] } },If this is not added, a compilation error occurs:
PrivilegeMap: GET interface: /redfish/v1/Chassis/{id}/MyApp, type: MyApp PrivilegeMap is not configured.Add the
interface_config\redfish\mapping_config\Chassis\MyApp.jsonfile with the following content:json{ "Resources": [ { "Uri": "/redfish/v1/Chassis/:chassisid/MyApp", "Interfaces": [ { "Type": "GET", "ResourceExist": { "${Statements/IsValidChassisId()}": true }, "RspBody": { "@odata.context": "/redfish/v1/$metadata#MyApp.MyApp", "@odata.id": "/redfish/v1/Chassis/${Uri/chassisid}/MyApp", "@odata.type": "#MyApp.MyApp", "Id": "MyApp", "Name": "New MyApp Interface", "WelcomeMessage": "${ProcessingFlow[1]/Destination/WelcomeMessage}" }, "Statements": { "IsValidChassisId": { "Steps": [ { "Type": "Plugin", "Formula": "utils.is_valid_chassis_id(Uri.chassisid)" } ] } }, "ProcessingFlow": [ { "Type": "Property", "Path": "/bmc/demo/MyMDSModel/1", "Interface": "bmc.demo.OpenUBMC.Community", "Destination": { "WelcomeMessage": "WelcomeMessage" } } ] } ] } ] }When the
/redfish/v1/Chassis/1/MyAppinterface is called, the content inRspBodyis returned. The value of theWelcomeMessageproperty is obtained according to the D-Bus property inProcessingFlow. The source of theWelcomeMessageproperty is theWelcomeMessageproperty inbmc.demo.OpenUBMC.Community. The@odatarelated properties here are new and require new configuration. Refer to the next steps for the configuration method.In the
interface_config\redfish\static_resource\redfish\v1\jsonschemas\path, add amyappfolder and create aindex.jsonfile:json{ "@odata.context": "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile", "@odata.id": "/redfish/v1/JSONSchemas/MyApp", "@odata.type": "#JsonSchemaFile.v1_0_2.JsonSchemaFile", "Id": "MyApp", "Description": "MyApp Schema File Location", "Name": "MyApp", "Languages": [ "en" ], "Schema": "#MyApp.MyApp", "Location": [ { "Language": "en", "Uri": "/redfish/v1/SchemaStore/en/MyApp.json" } ] }To compile
MyApp.json, the corresponding@odatastatic resource file needs to be found. TheUripath here must be configured correctly. Although the name of the final corresponding JSON file is entirely in lowercase, the system can handle this case discrepancy without issue.In the
interface_config\redfish\static_resource\redfish\v1\schemastore\en\directory, add amyapp.jsonfile:json{ "$schema": "http://redfish.dmtf.org/schemas/v1/redfish-schema.v1_1_0.json", "title": "#MyApp.MyApp", "$ref": "#/definitions/MyApp", "definitions": { "MyApp": { "anyOf": [ { "$ref": "http://redfish.dmtf.org/schemas/v1/odata.4.0.0.json#/definitions/idRef" }, { "type": "object", "patternProperties": { "^([a-zA-Z_][a-zA-Z0-9_]*)?@(odata|Redfish|Message|Privileges)\\.[a-zA-Z_][a-zA-Z0-9_.]+$": { "type": [ "array", "boolean", "number", "null", "object", "string" ], "description": "This property shall specify a valid odata or Redfish property." } }, "additionalProperties": false, "properties": { "@odata.context": { "$ref": "http://redfish.dmtf.org/schemas/v1/odata.4.0.0.json#/definitions/context" }, "@odata.id": { "$ref": "http://redfish.dmtf.org/schemas/v1/odata.4.0.0.json#/definitions/id" }, "@odata.type": { "$ref": "http://redfish.dmtf.org/schemas/v1/odata.4.0.0.json#/definitions/type" }, "Description": { "anyOf": [ { "$ref": "http://redfish.dmtf.org/schemas/v1/Resource.json#/definitions/Description" }, { "type": "null" } ], "readonly": true }, "Name": { "$ref": "http://redfish.dmtf.org/schemas/v1/Resource.json#/definitions/Name", "readonly": true }, "WelcomeMessage": { "type": [ "string", "null" ], "readonly": true, "description": "The value of this property shall be the name of WelcomeMessage." } } } ], "updatable": false, "insertable": false, "deletable": false, "uris": [ "/redfish/v1/Chassis/:chassisid/MyApp" ], "description": "This is myapp resource." } }, "copyright": "Copyright © xxx Technologies Co., Ltd. 2018. All rights reserved." }The
WelcomeMessageproperty must match the property of the source interface. Fill in the corresponding source interface URI inuris.In the
interface_config\redfish\static_resource\redfish\v1\schemastore\en\oem\huawei_chassis.jsonfile, search forThresholdSensors, and add the following nearby:json"MyApp": { "$ref": "http://redfish.dmtf.org/schemas/v1/MyApp.json#/definitions/MyApp", "readonly": true, "description": "A list of MyApp objects.", "longDescription": "Show all of the MyApp objects." },The
Chassis.jsonfile is associated withhuawei_chassis.json. Therefore, you also need to add the file here. Otherwise, an error will be reported during compilation.Compile and run the code on the device, and access
https://ip/redfish/v1/Chassis/1/MyAppto get the results.json{ "@odata.context": "/redfish/v1/$metadata#MyApp.MyApp", "@odata.id": "/redfish/v1/Chassis/1/MyApp", "@odata.type": "#MyApp.MyApp", "Id": "MyApp", "Name": "New MyApp Interface", "WelcomeMessage": "hello" }- When you access the
/redfish/v1/Chassis/1path, the/redfish/v1/Chassis/1/MyApplink is displayed.
json{ "@odata.context": "/redfish/v1/$metadata#Chassis.Chassis", "@odata.id": "/redfish/v1/Chassis/1", "@odata.type": "#Chassis.v1_15_7.Chassis", "Id": "1", "Name": "Computer System Chassis", ... "Oem": { "openUBMC": { "ChassisID": null, ... "ThresholdSensors": { "@odata.id": "/redfish/v1/Chassis/1/ThresholdSensors" }, "MyApp": { "@odata.id": "/redfish/v1/Chassis/1/MyApp" }, "DiscreteSensors": { "@odata.id": "/redfish/v1/Chassis/1/DiscreteSensors" }, ... }, ... }- When you access the
New Configuration for the Web Interface
The web interface is located in the rackmount\interface_config\web_backend path.
For example, to add a query interface for the WelcomeMessage property of my_app (an existing community example) to the System path (the expected path is /UI/Rest/System/Myapp), perform the following steps:
Add the
MyApp.jsonfile to theinterface_config\web_backend\mapping_config\Systemdirectory.json{ "Resources": [ { "Uri": "/UI/Rest/System/MyApp", "Interfaces": [ { "Type": "GET", "Authentication": { "Condition": false }, "RspBody": { "WelcomeMessage": "${ProcessingFlow[1]/Destination/WelcomeMessage}" }, "ProcessingFlow": [ { "Type": "Property", "Path": "/bmc/demo/MyMDSModel/1", "Interface": "bmc.demo.OpenUBMC.Community", "Destination": { "WelcomeMessage": "WelcomeMessage" } } ] } ] } ] }The
WelcomeMessageinRspBodymatches theWelcomeMessagevalue found by runningbusctl --user introspect bmc.kepler.my_app /bmc/demo/MyMDSModel/1 | cat.WebUI verification: Use Postman to access
https://ip/UI/Rest/System/MyApp. When using Postman, you need to add thecookieparameter under thekeycolumn in theheaderpage, and fill in thecookievalue in thevaluecolumn. You can press F12 in the browser to open DevTools and find the cookie for the corresponding interface. Verify if the results are normal.json{ "WelcomeMessage": "Hello" }
New Configuration for the CLI Interface
Example: To add a query interface for the WelcomeMessage property of my_app (an existing community example), under the ipmcget -d version command, perform the following steps:
In the
interface_config\cli\ipmcget\system.jsonfile, search for"Uri": "/cli/v1/_/version":- Add the
WelcomeMessagefield inRspBody.
json"WelcomeMessage": "${ProcessingFlow[13]/Destination/WelcomeMessage}",- Add the corresponding property mapping in
ProcessingFlow.
json{ "Type": "Property", "Path": "/bmc/demo/MyMDSModel/1", "Interface": "bmc.demo.OpenUBMC.Community", "Destination": { "WelcomeMessage": "WelcomeMessage" } }- Add the
In the
interface_config\cli\echoes\ipmcget_versionfile, search forFirmwareInfo.ActiveBMCSDK.Version, and add the following below it:jsonMYAPP INFO Version: {* WelcomeMessage *}In SSH, run the
ipmcget -d versioncommand. The new information is displayed underActive BMCSDK.jsonMYAPP INFO Version: Hello
Common Issues and Solutions
Zone.Identifier Temporary File Issue
When files are copied to in a directory, a Zone.Identifier temporary file is often generated. This file also participates in compilation and causes a compilation error.
The error information is similar to the following:
ERROR: rackmount/1.90.222@openubmc/rc: Error in build() method, line 37
MapperCheck.check()
JSONDecodeError: Expecting value: line 1 column 2 (char 1)The solution is to delete the relevant Zone.Identifier files. You can use the git status command to check if there are redundant Zone.Identifier files in Untracked files.
JSON File Debugging
If you modify multiple JSON files and are unsure which one causes an error, you can add debugging information to the mapper_check\MapperCheck.py file to help locate the error JSON file. The following is the git diff result for reference.
- with open(path, 'r', encoding='utf-8') as fp:
- return json.load(fp)
+ try:
+ print(f"Reading JSON file: {path}")
+ with open(path, 'r', encoding='utf-8') as fp:
+ data = json.load(fp)
+ print(f"✅ Successfully read: {path}")
+ return data
+ except Exception as e:
+ print(f"❌ Failed to read JSON file: {path}")
+ print(f"❌ Error message: {e}")
+ # Check if the file exists.
+ if not os.path.exists(path):
+ print(f"❌ File does not exist: {path}")
+ else:
+ # Check the file content.
+ with open(path, 'r', encoding='utf-8') as fp:
+ content = fp.read()
+ print(f"File content: {content}")
+ raiseProperty Acquisition Processing Method: ProcessingFlow
If the Type under ProcessingFlow for a normally added property is Property, use List if multiple objects are obtained, and use Method if a method is used. A ProcessingFlow can contain multiple objects, each with an index starting from 1.
{
"Type": "Method",
"Path": "/bmc/kepler/MdbService",
"Interface": "bmc.kepler.Mdb",
"Name": "GetPath",
"Params": [
"bmc.kepler.Systems.FruData.Overview",
{
"FruId": 0
},
false
],
"Destination": {
"Path": "Path"
}
},Property Acquisition Processing Method: Statements
If data on D-Bus needs to be processed, use Statements, which can contain ProcessingFlow.
"Steps": [
{
"Type": "Plugin",
"Formula": "orchestrator.bios.get_registry_version(Uri.systemid)"
}The content of Formula is a Lua script that can implement any service logic processing with complex logic. It supports input parameters, which can use data sources such as ReqBody.
Plugin can implement service processing with complex logic (not recommended for use with other processing types).
Taking Redfish as an example, the current storage directory for Redfish plugins is /opt/bmc/apps/redfish/interface_config/plugins. The preceding configuration requires the orchestrator\bios.lua file to exist in the storage directory and contain the get_registry_version function.
Redfish URI Configuration Issue
When configuring the Redfish interface, you may encounter a URI error. This is actually due to incorrect configurations in @odata.context, @odata.id, or @odata.type. Check and modify them.
Conclusion
Reference documents: