Configuration Import and Export
更新时间: 2025/11/19
在Gitcode上查看源码

Configuration Import and Export Adaptation Guide

Key Components for Configuration Import and Export: profile_schema, oms, and Components for Export

The code of profile_schema can be found at profile_schema.

Introduction

For some internal BMC configuration items, a config.json file can be generated and downloaded locally using the configuration export function. Customers can modify some properties and import the configuration file into the local BMC or into the BMC of other devices of the same model for the configuration to take effect. This ensures configuration consistency and saves time when multiple devices with the same property values are configured.

Implementation Principles of Configuration Export

When learning this function, you can refer to the configuration of \profile_schema\schema\account.json to get familiar with the format of configuration items. Analyze the exported configuration, compare the configuration items with the current configuration, and understand the format of the exported data. The exported data can be imported back. In the code of the component to be exported, search for mc.mdb.micro_component.config_manage to find the entry for the import and export code.

Services Capable of Exporting Data

Configuration import and export are carried through the oms component. You can see some logs in the app.log file. During export, the system first obtains all component names from the maca service. Then, it calls the relevant export interface in the corresponding service to collect data and generate the exported config.json file.

text
busctl --user --verbose call bmc.kepler.maca /bmc/kepler/MdbService bmc.kepler.Mdb  GetServiceNames  a{ss} 0  | cat
MESSAGE "as" {
        ARRAY "s" {
                STRING "bmc.kepler.network_adapter";
                STRING "bmc.kepler.usb_entry";
                ......
                STRING "bmc.kepler.power_mgmt";
        };
};

Adding Data Import and Export to Existing Services

For example, the existing my_app module contains the WelcomeMessage property. Implement its export and import functions.

Add the my_app.json file to \profile_schema\schema with the following content:

json
{
    "type": "object",
    "properties": {
        "Description": {
            "const": "Configurations of my_app"
        },
        "ConfigData": {
            "type": "object",
            "properties": {
                "MY_APP": {
                    "type": "object",
                    "properties": {
                         "WelcomeMessage": {
                            "type": "string",
                            "AttributeType": "ImportAndExport"
                        }
                    }
                }
            }
        }
    }
}

The preceding configuration indicates that the content to be exported is WelcomeMessage, the type is string, and the name of the custom data collection of the exported item is MY_APP.

Add dependency-related code to the my_app/src/lualib/my_app_app.lua module of my_app:

text
local json = require 'cjson'
local mdb_config_manage = require 'mc.mdb.micro_component.config_manage'

mdb_config_manage defined here indicates dependency on mc.mdb.micro_component.config_manage to register the on_export and on_import functions. The export function can be invoked only after the registration. The json library is added for data processing using json.encode and json.decode.

Add initialization code inside the app:init() function:

text
mdb_config_manage.on_import(function(...)
    return self:import(...)
end)
mdb_config_manage.on_export(function(...)
    return self:export(...)
end)
log:notice("mdb_config_manage on_export end")

The on_export and on_import registered to mdb_config_manage are implemented by functions of the oms component when the configuration import or export command is executed.

Adding Export Implementation

Add export-related code to my_app/src/lualib/my_app_app.lua of the my_app module:

text
function app:configuration_export()
    local my_app_obj = self.my_mds_model
    local data = {}
    if not my_app_obj then
        log:error('get my_app_obj failed.')
        return data
    end
    local configuration_config = {}
    configuration_config.WelcomeMessage = my_app_obj.WelcomeMessage
    data.MY_APP = configuration_config
    log:notice('export configuration config successfully.')
    return data
end

function app:custom_export()
    local data = {}
    local customize_config = {}
    customize_config.WelcomeMessage = ''
    log:notice("app:custom_export")
    data.CustomSettings = customize_config
    log:notice('export custom config successfully.')
    return data
end

function app:export(ctx, export_type)
    local data = {}
    if export_type == 'configuration' then
        data = self:configuration_export()
    elseif export_type == 'custom' then
        data = self:custom_export()
    end
    log:notice("app:export end")
    return json.encode({ ConfigData = data })
end

The second parameter of export is export_type, which can be configuration or custom. Currently, configuration is used. If a custom function is used, use the custom branch (not used in this example). data.MY_APP indicates that the data set name of the component in the exported data is MY_APP.

The content in the exported JSON file is as follows:

json
"my_app": {
    "ConfigData": {
        "MY_APP": {
            "WelcomeMessage": {
                "Value": "WelcomeMessage!",
                "AttributeType": "ImportAndExport",
                "Import": true
            }
        }
    },
    "Description": "Configurations of my_app"
},

If the configuration JSON file specifies ExportOnly, the content in the exported file is as follows:

json
"my_app": {
    "ConfigData": {
        "MY_APP": {
            "WelcomeMessage": {
                "Value": "WelcomeMessage! haha!",
                "AttributeType": "ExportOnly",
                "Import": false
            }
        }
    },
    "Description": "Configurations of ums"
},

Adding Import Implementation

Add import-related code to my_app/src/lualib/my_app_app.lua of the my_app module:

text
function app:configuration_import(configuration_config, my_app_obj, ctx)
    for key, value in pairs(configuration_config) do
        if not value or not value.Import then
            log:notice('my_app property [%s] import not supported.', key)
            return
        end
        -- Obtaining the value based on the actual data structure
        local config_value
        if type(value) == "table" and value.Value then
            config_value = value.Value
        else
            config_value = value
        end
        log:notice('Setting key: ' .. key .. ' to value: ', tostring(config_value))
        -- Setting the property
        my_app_obj[key] = config_value
        log:notice('Successfully set ' .. key)
    end
end

function app:custom_import(custom_config, my_app_obj, ctx)
        log:notice("custom_import")
end

-- Configuration import interface
function app:import(ctx, datas, import_type)
    log:notice("app:import start")

    if not datas then
        log:error('app: import data is nil.')
        return
    end

    -- Printing raw data
    log:notice('Raw import data: ' .. tostring(datas))
    -- Parsing JSON data
    local data = json.decode(datas)
    if not data then
        log:error('JSON decode returned nil')
        return
    end
    log:notice('Decoded data type: ' .. type(data))

    if type(data) == "table" then
        for k, v in pairs(data) do
            log:notice('data[' .. tostring(k) .. '] type: ' .. type(v))
        end
    else
        log:error('Decoded data is not a table')
        return
    end

    local config = data.ConfigData
    if not config or type(config) ~= 'table' then
        log:error('import data ConfigData is invalid.')
        return
    end

    local my_app_obj = self.my_mds_model
    if not my_app_obj then
        log:error('get my_mds_model failed.')
        return
    end
    if import_type == 'configuration' then
        self:configuration_import(config.MY_APP, my_app_obj, ctx)
    elseif import_type == 'custom' then
        self:custom_import(config.CustomSettings, my_app_obj, ctx)
    else
        log:error('unknown import type(%s)', import_type)
    end
    log:notice('app:import successfully')
end

The preceding function handles the import process. Similarly, it processes import_type first. When configuration_import is called, the config.MY_APP object needs to be transferred. Finally, the properties to be imported are set to the memory object.

For example, if you change the WelcomeMessage property in the config.json import file to:

json
"my_app": {
    "ConfigData": {
        "MY_APP": {
            "WelcomeMessage": {
                "Value": "WelcomeMessage! haha!",
                "AttributeType": "ImportAndExport",
                "Import": true
            }
        }
    },
    "Description": "Configurations of my_app"
},

After the import, query the relevant property on the device:

text
~ ~ $ 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           "WelcomeMessage! haha!" emits-change writable
bmc.kepler.Object.Properties        interface -           -                       -

During the import, the system prints the logs recorded in the code to app.log to facilitate troubleshooting:

text
Raw import data: {"ConfigData":{"MY_APP":{"WelcomeMessage":{"Value":"WelcomeMessage! haha!","Import":true}}},"Description":"Configurations of my_app"}

Equipment Customization Items

Search for CustomSettings in the corresponding service in profile_schema to see equipment customization items. Pay attention to the CustomDefault property, which indicates the default value of the configuration data.

Common Issues

Errors in JSON Import Configuration

The web page also displays an error message: Failed to import the configuration file. Check and modify the configuration file and import it again. For more information, see the operation logs.

Errors in Profile Configuration

The compiler may not report errors during compilation, but the web page displays error messages. Search for relevant error logs according to the prompts. Failed to import the configuration file. Check and modify the configuration file and import it again. For more information, see the operation logs.

You can check app.log for logs similar to the following:

text
validate.lua(88): Attribute(MY_APP) import value invalid
 oms ERROR: validate.lua(88): Attribute(ConfigData) import value invalid
 oms ERROR: validate.lua(118): Validate import value failed
 oms ERROR: import.lua(144): Service(my_app) config is invalid, error info: /MY_APP/WelcomeMessage

Imported Data Does Not Take Effect

For example, if the Import property in the configured config.json is false, it will be filtered out by the following validation code:

text
if not value or not value.Import then
    log:notice('my_app property [%s] import not supported.', key)
    return
end

Corresponding validation log in app.log:

text
my_app property [WelcomeMessage] import not supported.

Reference