配置导入导出适配指导
配置导入导出功能主要涉及的组件是: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文件
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文件,内容如下
{
"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中,增加依赖相关代码
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()函数内部,增加初始化代码
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相关代码
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 })
endexport的第二个参数是export_type,有configuration和custom,当前使用的是configuration,如果是客户定制化功能,使用custom分支(本例子不使用),这里面data.MY_APP,表示导出的数据中,组件的数据集合名称名字是MY_APP;
导出后的json文件里面内容如下
"my_app": {
"ConfigData": {
"MY_APP": {
"WelcomeMessage": {
"Value": "WelcomeMessage!",
"AttributeType": "ImportAndExport",
"Import": true
}
}
},
"Description": "Configurations of my_app"
},如果配置的json文件里面是ExportOnly,得到导出文件里面内容如下
"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相关代码
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属性修改为
"my_app": {
"ConfigData": {
"MY_APP": {
"WelcomeMessage": {
"Value": "WelcomeMessage! haha!",
"AttributeType": "ImportAndExport",
"Import": true
}
}
},
"Description": "Configurations of my_app"
},导入后在设备上查询相关属性得到:
~ ~ $ 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,方便问题定位:
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日志,有类似打印
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,在如下代码中会被校验掉
if not value or not value.Import then
log:notice('my_app property [%s] import not supported.', key)
return
end校验对应的app.log日志:
my_app property [WelcomeMessage] import not supported.