配置导入导出
更新时间: 2025/11/19
在Gitcode上查看源码

配置导入导出适配指导

配置导入导出功能主要涉及的组件是:profile_schema组件,oms组件,需要导出的组件

profile_schema代码路径是:profile_schema

功能介绍

BMC内部的部分配置项,可以通过配置导出功能,生成config.json的文件,下载到本地,客户可以修改部分属性,通过导入功能,将配置导入到本机BMC中,或者把配置文件导入到其他同款设备的BMC之中,使其生效,在配置多设备,多属性相同内容的时候,可以保证配置一致,节约时间;

配置导出功能实现原理介绍

开始学习此功能时,可以参考\profile_schema\schema\account.json,参考其中的配置,熟悉配置项的格式; 先分析导出配置,然后对比配置项和当前的配置,熟悉导出后的格式,导出后的数据是可以再导入回去的; 在需要导出的组件代码中,搜索mc.mdb.micro_component.config_manage,一般可以找到导入导出代码的入口;

哪些服务能够导出数据

配置导入导出时,通过oms组件承载,可以在app.log中看到部分日志。导出时先从maca服务获取全量组件名称,如下所示,在对应的服务,调用相关的export接口,收集数据生成导出的config.json文件

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";
        };
};

已有服务新增数据导入导出功能

举例:已有的my_app模块,内部包含了WelcomeMessage的属性,实现其导出,导入的功能;

在\profile_schema\schema,增加my_app.json文件,内容如下

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

以上配置表示需要导出的内容是WelcomeMessage,类型是string,导出项的自定义数据集合名称是MY_APP;

在my_app的模块my_app/src/lualib/my_app_app.lua中,增加依赖相关代码

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

此处定义的mdb_config_manage表示需要依赖mc.mdb.micro_component.config_manage进行on_export和on_import函数的注册,注册后才可以调用到export函数; 增加json是因为要使用json的encode和decode进行数据处理;

在function app:init()函数内部,增加初始化代码

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")

这里注册到mdb_config_manage的on_export和on_import,在下命令配置导入导出时oms会调用本身的函数实现;

增加export的代码实现

在my_app的模块my_app/src/lualib/my_app_app.lua中,增加export相关代码

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

export的第二个参数是export_type,有configuration和custom,当前使用的是configuration,如果是客户定制化功能,使用custom分支(本例子不使用),这里面data.MY_APP,表示导出的数据中,组件的数据集合名称名字是MY_APP;

导出后的json文件里面内容如下

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

如果配置的json文件里面是ExportOnly,得到导出文件里面内容如下

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

增加import的代码实现

在my_app的模块my_app/src/lualib/my_app_app.lua中,增加import相关代码

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
        -- 根据实际数据结构获取值
        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))
        -- 设置属性
        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

-- 配置导入接口
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

    -- 打印原始数据
    log:notice('Raw import data: ' .. tostring(datas))
    -- 解析 JSON 数据
    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

以上函数是导入流程,同样先处理import_type,然后注意传入configuration_import的时候,要传入config.MY_APP对象,最终把需要导入的属性设置到内存对象中;

比如把导入文件的congfig.json里面的WelcomeMessage属性修改为

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

导入后在设备上查询相关属性得到:

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 -           -                       -

在执行导入时候,会打印代码里面记录的的日志到app.log,方便问题定位:

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

装备定制化项

在profile_schema中对应的服务中,搜索CustomSettings,可以看到装备定制化项,关注CustomDefault属性,表示配置数据默认取值

常见问题

如果导入的json文件配置有错误​

在web页面上也有错误提示: 配置文件导入失败,请核对修改后重新导入,查看操作日志获取更多信息。

如果profile配置有错误​

在编译时不一定报错,但在web页面上也有错误提示,根据提示查找相关的错误日志。 配置文件导入失败,请核对修改后重新导入,查看操作日志获取更多信息。

可以查看app.log日志,有类似打印

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

如果导入的数据没有生效

比如配置的congfig.json里面的Import属性是false,在如下代码中会被校验掉

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

校验对应的app.log日志:​

text
my_app property [WelcomeMessage] import not supported.

参考文档