Foreword: In openUBMC, the MDS data model is defined. To simplify the code development process of the data model, openUBMC embeds the interface code automatic generation script in bingo to help developers quickly develop MDS data model.
Before using automatic interface code generation , you must understand the meaning of the MDS data model and its role in openUBMC.
Automatic Interface Code Generation
This section describes the automatic code generation process and the mapping between the generated interface code and the MDS.
In this section, you will learn the following skills:
- Understand the source and usage of each piece of automatically generated code.
- Learn how to add MDS objects, interfaces, properties, and methods.
- Learn how to add an IPMI command.
- Learn how to subscribe to the app resource collaboration interface of other components.
Time for Automatic Code Generation
Before starting automatic interface code generation, you need to determine the time. When a component needs to add external capabilities or add references to other components, the code needs to be automatically generated. When the following conditions are met, the automatic generation of interface code can reduce the amount of manually developed code:
- Objects, interfaces, properties (private and public), and methods are added to the component app.
- IPMI methods are added to the component app.
- Objects are added to types.json.
- The component app needs to subscribe to interfaces of other component apps. (The code can be used as an alternative.)
Relationships Between Dependencies for Automatic Code Generation
Before starting automatic code generation, you need to determine the participants involved in the automatic code generation from the perspective of developers.
- bingo (executor of automatic code generation)
- Definition of the component MDS (including the definition of property sources, object interface relationships, and request & receiving formats of methods)
- mdb_interface (type of interface properties, and definition of the request and receiving formats of common interface methods)
Definition of MDS
During the development of the component app, the MDS needs to be defined. The following json files are involved (all placed in the /mds/ directory):
- model.json
- service.json
- ipmi.json
- types.json
For details about how to configure the MDS, see MDS.
Environment
In the Dependency description, it is specified that the automatic code generation depends on the interface definition of mdb_interface. On the component side, the source of mdb_interface can be configured through dependencies in service.json. The following is an example:
{
"name": app_name,
....
"dependencies":{
"test":[
{
"conan":"mdb_interface/[>=x.x.x]"
},
...
],
}
}In the preceding service.json, the mdb_interface code is defined to be obtained from the Conan image repository, and the latest version of >=x.x.x will be captured. Developers can build mdb_interface locally and replace the mdb_interface in service.json with the local package, for example:
{
"name": app_name,
....
"dependencies":{
"test":[
{
"conan":"mdb_interface/x.x.x@xxx.dev/dev"
},
...
],
}
}Executing Automatic Code Generation
If you have installed the bingo, defined the MDS, and introduced the dependency of the mdb_interface, you can run the following command to execute automatic code generation:
bingo genBefore executing automatic code generation, ensure that the
mdb_interfacein /.conan/data is the latest version. If not, run therm -rf ~/.conan/data/mdb_interfacecommand to clear the cached mdb_interface and run thebingo gencommand again.
Mapping of Automatically Generated Code
After the code is automatically generated, all the generated code is stored in the /gen directory. All the code can be quickly called in Lua using the require command. The directory structure of the automatically generated code is as follows:
.
├── class
│ ├── model.lua
│ └── types
│ ├── TypesName_1.lua
│ ├── ...
│ ├── TypesName_n.lua
│ └── types.lua
└── app_name
├── client.lua
├── datas.lua
├── db.lua
├── lcoal_db.lua
├── ipmi
│ ├── cmds
│ │ ├── Getxxx.lua
│ │ ├── ...
│ │ └── Setxxx.lua
│ ├── ipmi.lua
│ └── ipmi_message.lua
├── json_types
│ ├── JsonTypes_1.lua
│ ├── ...
│ └── JsonTypes_k.lua
├── local_db.lua
├── orm_classes.lua
└── service.luaThe relationship between the automatically generated code file and the MDS and the brief description are as follows:
Directory Name | File Name | Reference File | Description |
|---|---|---|---|
| /gen/class | model.lua | model.json and mdb_interface interface definition | Converts the configuration in model.json to Lua code, which is used to verify the type of each class property, format of the method request body and response body, default value settings of the property, and the registration function of the server resource collaboration interface method. For details, see MDS Object. |
| /gen/class/types | TypesName_x.lua | model.json | A TypesName_x.lua file is generated for the definition of each class in model.json, which declares the default value of the private property of the class, index mode, unpacking, and verification method. The file is referenced by model.lua to assist in class verification. |
| /gen/types | types.lua | types.json | Defines custom types such as enumerations, structures, and dictionaries, which can be used to define some properties in model.json. For example, a custom structure defined in types.lua can be used as the type of a member variable in the corresponding class. |
| /gen/app_name | client.lua | service.json and mdb_interface interface definition | The required part in service.json defines the resource collaboration interface of other component apps required for the component app service processing. The corresponding resource collaboration interface method calling, object obtaining, and signal subscription functions are automatically generated in client.lua. For details, see Cross-Component Communication. |
| /gen/app_name | datas.lua | datas.yaml | Local persistent database, which is loaded by default during component app initialization. The database can be referenced in lua require mode. |
| /gen/app_name | db.lua | model.json | Creates remote persistent database tables (including data fields, primary key declaration, and default value definition) and encapsulates remote database operation methods (including database addition, deletion, modification, and query methods). |
| /gen/app_name | local_db.lua | model.json | Creates local persistent database tables (including data fields, primary key declaration, and default value definition) and encapsulates remote database operation methods (including database addition, deletion, modification, and query methods). The local persistent database is distinguished from the remote persistent database by configuring "{tableLocation": "Local}" in service.json. |
| /gen/app_name/ipmi | ipmi.lua | ipmi.json | Defines the IPMI method of the component app, encapsulates the IPMI netfn, cmd, and subcmd, and encapsulates the request body and response body. |
| /gen/app_name/ipmi | ipmi_message.lua | ipmi.json | Collects IPMI message body (request body and response body), which is called by ipmi.lua. |
| /gen/app_name/ipmi/cmds | IpmiMethod_x.lua | ipmi.json | Defines the message body of the IPMI method and generates the verification method. |
| /gen/app_name/json_types | Interface endpoint name.lua | Generated by combining model.json and service.json with mdb_interface | Defines each interface, including the definition method of the registration property and the parameter verification method. The model.lua is referenced to assist in interface property verification. |
| /gen/app_name | orm_classes.lua | model.json | Describes ORM object, which requires configuring tableName and property persistence in the model.json |
| /gen/app_name | service.lua | Generated by combining model.json and service.json with mdb_interface | Service entry, including app initialization, server resource collaboration interface method registration, and object creation. For details, see Microcomponent Framework. |
Detailed Description and Usage of Automatically Generated Code
In this section, we will analyze the functions of the automatically generated code from the perspective of app initialization. As shown in the following figure, the relationship between the automatically generated code and the service app is as follows:
Microcomponent Framework
During automatic interface code generation, openUBMC provides the microcomponent framework of components and uses service.lua as the service framework of service components. In service.lua, the basic initialization method of service components, MDS object creation method, and external method definition are defined. openUBMC uses the object-oriented approach to help developers quickly complete development. For details, see Lua Development Framework.
Initializing App
The basic construction method of the service component is defined in service.lua, as shown in the following:
function app_name_service:ctor(){...} -- Constructor definition, which is executed when app_name_app is initialized
function app_name_service:pre_init(){...} -- Pre-initialization definition, which can be called using app.super.pre_init() in app_name_app
function app_name_service:init(){...} -- Initialization definition, which can be called using app.super.init() in app_name_appDevelopers can quickly develop services by inheriting service.lua in the service development code /src/lualib/app_name_app.lua.
local c_service = require 'app_name.service'
local class = reuquire 'mc.class'
local app = class(c_service)
-- Component app initialization
function app:ctor(){...}
function app:init(){...}Creating an MDS Object
Developers can quickly define an MDS object by defining the object name, interfaces in the object, and private properties of the object in model.json, and create an object through auto generation. The following is an example:
{
"ResourceObject":{
"path" : "/bmc/kepler/Systems/:SystemId/ResourceObject/:ID" ,
"privilege" : ["ConfigureSelf"],
"interface" : {
"bmc.kepler.Systems.ResourceObjectInterface1" : {
"properties" : {
"ID" :{
...
},
...
}
},
...
},
"method" : {
...
},
"properties" : {
"ObjectProperty_1" : {
...
},
...
}
}
}
path: MDS object path declaration
interface: resource collaboration interface of the MDS object, wherepropertiesindicates the properties of the resource collaboration interface
method: method definition provided by the MDS object for external systems
properties: private property definition of the MDS object
After the model.json object is configured and the code is automatically generated, the service.lua defines the MDS object interface (including the interface name and type) and the MDS object construction method. In addition, the method of quickly creating an MDS object in the service code is provided.
function app_name_service:CreateResourceObject(SystemID, ID, prop_setting_cb)
local path = '/bmc/kepler/Systems/' .. SystemId .. '/ResourceObject' -- External path of the object
return object_manage.create_object('ResourceObject', path, path, prop_setting_cb) -- Open the object external capability
endAn MDS object can be quickly created by calling CreateResourceObject in the service code. The following is an example:
function c_resource_object.create_mdb_object(value)
local app = c_object_manage.get_instance().app
return app:CreateResourceObject(1, value.ID, fucntion(obj)
... -- Service processing
end)
endExternal Method Implementation
The microcomponent framework defines the rpc method to enhance the external capabilities of components. The generation of the rpc method depends on the definitions of model.json and mdb_interface. The rpc method is demonstrated using GetPortSpeed in network_adapter.
{
"NetworkAdapters":{
...
"method":{
"GetPortSpeed": {
"privilege": [
"ConfigureSelf"
],
"req": {
"Type": {
"baseType": "U8"
},
"Slot": {
"baseType": "U8"
},
"PortID": {
"baseType": "U8"
}
},
"rsp": {
"Status": {
"baseType": "U8"
},
"Speed": {
"baseType": "U32"
}
}
},
}
}
}Multiple rpc methods can be defined in
method. The structure of each method is shown inGetPortSpeed, which defines the structures of request body and response body.
In GetPortSpeed, three integer input parameters Type (NIC type), Slot (NIC slot number), and PortID (network port ID) are defined for the request body, and two return values Status (response status) and Speed (network port rate) are defined for the response body. When the methods are defined under the interface in model.json (corresponding to the definition in mdb_interface), the implementation interfaces of the corresponding methods are generated in service.lua during automatic generation.
function M.ImplNetworkAdaptersNetworkAdaptersGetPortSpeed(cb)
class('NetworkAdapters')['bmc.kepler.Systems.NetworkAdapters'].GetPortSpeed = function(obj, ctx, ...)
local req = network_adapters_intf_types.GetPortSpeedReq.new(...):validate(nil, nil, true)
local rsp = network_adapters_intf_types.GetPortSpeedRsp.new(cb(obj, ctx, req:unpack())):validate()
return rsp:unpack(true)
end
endIn the preceding information, cb is the abbreviation of the callback function callback. In the network_adapter_app.lua file, the registration mode is used to implement specific services.
function app:register_app_name_rpc()
self:ImplNetworkAdaptersNetworkAdaptersGetPortSpeed(function(obj, ctx, ...)
return self.device_manager:method_get_netport_speed(...)
end)
end
function c_device_manager:method_get_netport_speed(type, slot, port_id)
... -- Service processing code
endRewrite the cb function of the method. When the rpc method is called, the corresponding service can be processed. The input parameters, such as obj and ctx, are verified in model.lua. obj is the MDS object accessed when the rpc method is called, and ctx indicates the context information stored in key-value format when parameters are input.
After the app service processing is defined, you can run the busctl command to call the rpc method. The introspect method can be used to view the method definition of NetworkAdapters.
busctl --user introspect bmc.kepler.network_adapter /bmc/kepler/Systems/1/NetworkAdapters
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
bmc.kepler.Systems.NetworkAdapters interface - - -
.GetPortSpeed method a{ss}yyy yu -The signature of the GetPortSpeed method is a{ss}yyy. For details about the signature, see Component Development and Code Compilation. The input parameter ctx of the rpc method is the input of a{ss}, and the variable-length parameter ... corresponds to the input of yyy. Therefore, you can run the following command to call the GetPortSpeed method to view the rate of the network port whose type is 1, slot is 2, and network port number is 0:
busctl --user call bmc.kepler.network_adapter /bmc/kepler/Systems/1/NetworkAdapters bmc.kepler.Systems.NetworkAdapters GetPortSpeed a{ss}yyy 0 1 2 0The following command output is displayed:
yu 0 4294967295In the preceding command, yu indicates the returned signature, 0 indicates that the response code is returned successfully, and 4294967295 indicates the queried network port rate.
The process of calling the rpc method is as follows:
To add a method, you need to add the method configuration to the model.json and mdb_interface interfaces.
MDS Object
In the relationship between automatically generated code and MDS files, we have introduced the functions of model.lua, which is mainly to define the interface and property types of MDS objects, the types of method request bodies and response bodies, and the interface of the MDS method.
If the developers define the type of these properties, the operations will be complex and error-prone. The automatic code generation function of openUBMC ensures that repetitive and complex code such as the parameter verification method can be automatically generated when the configuration is correct.
The interface and property types of the MDS object are mainly used for verification, as shown in the following:
local ResourceObject = {
['table_name'] = 't_resource_object',
['alias_map'] = {
...
},
['prop_configs'] = { -- Private property definition
['Property1'] = {
['usage'] = {'CSR'},
['baseType'] = 'U8', -- Type definition
['validator'] = require'class.types.ResourceObject'.Property1 -- Verification method (in /class/types)
},
... -- Other private property definitions
},
['default_props'] = {
['Property1'] = require'class.types.ResourceObject'.Property1.default[1], -- Default value
...
},
['mdb_prop_configs'] = {
['bmc.kepler.Systems.ResourceObjectInterface1'] ={ -- Interfaces contained in the MDS object
['ID'] = {
['baseType'] = 'String',
['readOnly'] = true,
['description'] = 'NIC ID',
['primaryKey'] = true,
['validator'] = require'app_name.json_types.ResourceObjectInterface1'.ID -- Verification method (in /app_name/json_types)
},
... -- Other interface property definitions
},
... -- Other interface definitions
},
['mdb_method_configs'] = { -- Resource collaboration interface method
['bmc.kepler.Systems.ResourceObjectInterface1'] = { -- Method definition under the interface
['StarMethod'] = {
['req'] = {{['baseType'] = 'String', ['param'] = 'ID'}},
['rsp'] = {},
['privilege'] = {'BasicSetting'}
},
... -- Request response body definition of other methods
}
},
['mdb_classes'] = mdb.get_class_obj('/bmc/kepler.Systems/:SystemID/ResourceObject/:ID'), -- MDS object obtaining method
['new_mdb_object'] = mdb.new_objects_builder({
['bmc.kepler.System.ResourceObjectInterface1'] = {
['property_defaults'] = {
['ID'] = ResourceObjectInterface1_intf_types.ID.default[1], -- Interface property initialization
...
},
['privileges'] = {
['path'] = privilege.ConfigureSelf,
['method'] = {['StarMethod'] = privilege.BasicSetting}
},
['interface_types'] = ResourceObjectInterface1_intf_types -- Interface type definition, which is derived from **/json_types**
},
... -- Initialization of other interface properties
})
}In the preceding code example, model.lua defines the type and verification method of each property of each interface of each class, and defines the types of method requests and returned parameters. Then, the method interface definition in model.lua will be introduced. In the service.lua introduction, it is known that the interface definition exposed by service.lua to the app is essentially calling the method of model.lua. In model.lua, the request body and response body of the method are initialized, and the verification is complete. The following is an example:
function M.ImplNetworkAdapterNetworkAdapterStartRemovingDevice(cb)
class('ResourceObject')['bmc.kepler.Sytems.ResourceObjectInterface1'].StarMethod = function(obj, ctx, ...)
local req = ResourceObjectInterface1_intf.types.StarMethodReq.new(...):validate(nil, nil, true)
local rsp = ResourceObjectInterface1_intf.types.StarMethodRsp.new(cb(obj, ctx, req.unpack())):validate()
return rsp:unpack(true)
endSo far, the introduction of model.lua functions have been completed. In a word, model.lua is the lua script convered from the MDS definition. It helps developers quickly obtain MDS objects, simplifies the process of exposing objects to external systems, and enables developers to focus more on service development.
Using MDS Objects
openUBMC provides intuitive mapping for object property access during object creation. So, the property can be accessed directly through the member variables.
function app:do_something()
self.resource_obj = app:CreateResourceObject(1, value.ID, fucntion(obj)
... -- Service processing
end)
-- Obtain the properties under the interface, such as ID
local id = self.resource_obj.ID
-- Obtain private properties
local private_prop = self.resource_obj.Property1
endSometimes, an MDS object integrates multiple interfaces containing properties that share the same name. For example, the property ID exists under both interface A and interface B, the duplicate property names will be detected and an error will be reported during the automatic code generation unless modifications are made. To solve this problem, an alias can be used to define one of the properties, as shown in the following in model.json:
"bmc.kepler.Systems.ResourceObjectInterface1": {
"properties":{
"ID": {}
}
},
"bmc.kepler.Systems.ResourceObjectInterface2": {
"properties":{
"ID": {
"alias": "ResourceID"
}
}
}After automatic code generation is completed, the alias ID can be accessed through self.resource_obj.ResourceID.
Cross-Component Communication
In client.lua, subscription and access to the APPMDS object of other components are defined to implement the communication between components. The MDS object can be quickly accessed by calling the client.xxx method in the service code.
Cross-Component rpc Method Calling
In service.json, the access to other resource collaboration interfaces can be defined in required. For example, to access the bmc.kepler.System.OtherResourceOInterface interface, define the access as follows:
-- service.json
-- Definition of other component app interfaces
{
...
"required" : [
{
"path" : "*",
"interface" : "bmc.kepler.System.OtherResourceOInterface",
"properties" : {}
}
...
]
}The path can be omited in required. This is because all MDS objects that have the interface are automatically found during client calling. For example, the following method is generated in the client:
-- client.lua
-- Automatically generate the method under the corresponding interface
-- Obtain all MDS objects that have the interface
function app_name_client:GetOtherResourceOInterfaceObjects()
return get_non_virtual_interface_objects(self.get_bus(), 'bmc.kepler.Systems.OtherResourceOInterface', true)
end
-- Obtain the traversal method of MDS objects that have the interface
function app_name_client:ForeachOtherResourceOInterfaceObjects(cb)
return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.OtherResourceOInterface', cb, true)
end
-- Listen for the interface addition signal
function app_name_client:OnOtherResourceOInterfacesAdded(cb)
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb, 'bmc.kepler.Systems.OtherResourceOInterface')
end
-- Listen for the interface removal signal
function app_name_client:OnOtherResourceOInterfacesRemoved(cb)
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb, 'bmc.kepler.Systems.OtherResourceOInterface')
endAfter the access method of the resource collaboration interface is automatically generated, the MDS objects of other components' interfaces can be accessed by referencing the method in client, as shown in the following:
-- /src/lualib/your_service.lua
local client = require 'app_name.client'
...
function your_service_process()
local objects = client:GetOtherResourceOInterfaceObjects()
...
endThe objects can be filtered using cb by calling the Foreach method. The following code uses Foreach to filter the objects that meet the bond_id condition among all objects that have the interface.
-- Foreach usage
local function find_bond_object(bond_id)
local object
client:ForeachOtherResourceOInterfaceObjects(function(obj)
log:info('obj.Id = %s, bond_id = %s', obj.Id, bond_id)
if obj.Id == bond_id then
object = obj
end
end)
return object
endThe addition and removal of interfaces of an object can also be listened for.
client:OnOtherResourceOInterfacesAdded(function (sender, path, props)
self.status = props.Status:value()
end)sender indicates the identity of the sender. If there is no sender, use _ instead.
path indicates the interface change path.
props: indicates the corresponding interface and interface property value.
The usage of the OnOtherResourceOInterfacesRemoved method is similar to that of the OnOtherResourceOInterfacesAdded method.
Interface Property Subscription
The subscription to the MDS object can be listened for using signals. For example:
-- service.json
-- Property subscription definition
{
"required" : [
{
"path" : "/bmc/kepler/Systems/${SystmeId}",
"interface" : "bmc.kepler.Systems.OtherResourceObject2",
"properties" : {
"State" : ["subscribe"] -- Property subscription configuration
}
}
]
}-- client.lua
function app_name_client:OnOtherResourceObject2PropertiesChanged(cb, path_params)
local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] ) or '/bmc/kepler/Systems')
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), path_namespace, cb, 'bmc.kepler.Systems.OtherResourceObject2', {'State'}) -- Definition of the listening signal slot
end-- /src/lualib/your_service.lua
local client = require 'app_name.client'
...
function your_service_process()
client:OnOtherResourceObject2PropertiesChanged(function(values, msg_path, interface)
local state = values.State:value()
-- Actual service processing after signal listening
if state == 1 then
...
else if state == 0 then
...
end
end)
endvalues indicates the property values changed during the listening.
msg_path indicates the message sending path, which can be replaced by _ by default.
interface indicates the interface path, which can be replaced by _ by default.
IPMI
The openUBMC provides a template for automatically generating IPMI methods and searches for this IPMI based on the configured command words. ipmi.lua defines parameters such as netfn (network function number) and cmd (command words) of the IPMI command, the search path of the IPMI command (consisting of parameters in req), the encoding and decoding formats, and the formats of the request body and response body. The following is an example:
-- ipmi.json
{
"package" : "AppNameIpmiCmds",
"cmds": {
"GetMethod" : {
"netfn" : "0x30",
"cmd" : "0x93",
...
"req" : [
{"data" : "ManuId", "baseType": "U32", "len": "3B", "customizedRule": "Manufacturer"},
{"data": "SubCommand", "baseType": "U8", "len": "1B", "value": "0x00"},
{"data": "FruId", "baseType": "U8", "len": "1B"},
],
"rsp" : [
{"data" : "CompletionCode", "baseType" : "U8", "len": "1B"},
{"data": "result", "baseType": "U8", "len": "1B"}
]
},
...
}
}In the IPMI configuration, three parameters are configured for req. The first parameter manuId indicates the manufacturer ID, which consists of three bytes. Because no default value is configured, any value can be used for sending when the IPMI is used. The second parameter is SubCommand, the subcommand word of the IPMI. It consists of one byte and is set to a fixed value 0x00, indicating that the IPMI command can be routed only when the parameter is set to 0x00. The third parameter is FruId, the input parameter required by the service. It consists of one byte and can be sent as any value.
Therefore, the IPMI command can be sent by using ipmitool + corresponding command word. For example:
ipmitool [options ...] raw 0x30 0x93 0xdb 0x07 0x00 0x00 0x010x30 corresponds to netfn; 0x93 corresponds to cmd; 0xdb 0x07 0x00 represents three bytes of ManuId. The original ManuId is 0x0007db. When a command is sent, the low byte is placed first, and ManuId may be another value. 0x00 corresponds to SubCommand, which is a fixed value. 0x01 corresponds to FruId, which can be any value.
After automatic code generation, the following definition is obtained:
-- ipmi.lua
NetworkAdapterIpmiCmds.GetMethod = {
name = 'GetMethod',
prio = types.Priority.Default,
netfn = 0x30,
cmd = 0x93,
...
filters = [=[*,*,*,00]=], -- IPMI search path. * indicates any value.
decode = [=[<<ManuId:3/unit:8, 0x00:1/unit:8, FruId:1/unit:8]=] , -- Decoding format definition
encode = [=[<<CompletionCode:1/unit:8, result:1/unit:8]=], -- Encoding format definition
req = msg.GetMethodReq, -- Request body type definition
rsp = msg.GetMethodRsp, -- Response body type definition
...
}In the preceding definition, filters corresponds to the IPMI search path. The first three bytes can be any value. The fourth byte must be 0x00. The subsequent bytes can be any value.
In the service processing code, the IPMI command needs to be processed and the response needs to be returned in the encode format. The registration method is as follows:
-- app_name_app.lua
local ipmi_struct = require 'app_name.ipmi.ipmi'
local ipmi = require 'ipmi'
...
function app:init_internal()
self:register_ipmi()
end
function app:register_ipmi()
self.register_ipmi_cmd(ipmi_struct.GetMethod, funciton(...)
return self.device_manager:get_method_from_ipmi(...) -- Service processing process
end)
end
-- device_manager.lua
local msg = require 'app_name..ipmi.ipmi_message'
function c_device_manager:get_method_from_ipmi(req, ctx)
... -- Service processing
return msg.GetMethodRsp(cc.Success, result)
endThe process of calling the IPMI command is as follows:
Summary
So far, we have completed the introduction to automatic code generation. Automatic code generation is a quick implementation of the MDS data model. In addition, it is an important step for objects to provide information externally.