自动生成Lua代码说明
1. 自动生成文件目录结构
| 目录 | 文件名 | 依据的文件 | 说明 |
|---|---|---|---|
| gen/class | model.lua | model.json以及mdb_interface接口定义文件 | 包含每个类的属性(包括资源树属性和私有属性)校验信息,以及服务端资源树方法注册函数 |
| gen/class/types | 类名.lua | model.json | 每个类一个文件,完成私有属性的校验和默认值配置,会被model.lua引用 |
| gen/class/types | types.lua | types.json | 包含枚举、结构体、字典等自定义类型的定义 |
| gen/App名 | client.lua | service.json以及mdb_interface接口定义文件 | 根据required部分定义的接口依赖生成,客户端资源树接口方法调用、对象获取和信号订阅等函数 |
| gen/App名 | datas.lua | datas.yaml | 远程持久化内存数据库/本地持久化数据库初始化加载的默认数据 |
| gen/App名 | db.lua | model.json | 远程持久化内存数据库表格创建和数据库操作函数 |
| gen/App名 | local_db.lua | model.json | 本地持久化数据库表格创建和数据库操作函数(model.json中配置了"tableLocation": "Local"的表) |
| gen/App名 | orm_classes.lua | model.json | 为配置了远程持久化的每个类初始化ORM对象 |
| gen/App名 | service.lua | model.json、service.json以及mdb_interface接口定义文件 | 服务入口,包含App初始化和服务端资源树方法注册、对象创建等 |
| gen/App名/ipmi | ipmi.lua | ipmi.json | IPMI命令定义,是IPMI模块的入口 |
| gen/App名/ipmi | ipmi_message.lua | ipmi.json | IPMI命令请求和响应汇总,会被ipmi.lua引用 |
| gen/App名/ipmi/cmds | 命令名.lua | ipmi.json | 每个IPMI命令一个文件,包含请求和响应参数定义和校验,会被ipmi_message.lua引用 |
| gen/App名/json_types | 接口末段.lua | model.json、service.json以及mdb_interface接口定义文件 | 每个接口一个文件,包含资源树接口注册属性定义方法参数校验 |
2. mdb_interface依赖配置
自动生成代码会使用service.json中dependencies配置的mdb_interface版本进行代码生成。如果build和test部分都配置了mdb_interface依赖,则优先选用build部分的配置。
本地开发调试时,修改mdb_interface后,可以在mdb_interface目录执行bingo build,然后将构建生成的包配置到组件的service.json中,再到组件目录下执行bingo gen生成代码。
3. 代码生成策略配置
代码生成策略需要在组件MDS/service.json文件中的codegen_policy中指定,具体配置方式参考《代码生成策略版本特性说明》文档。
4. 校验说明
4.1 model.json中配置的资源树属性、方法、信号没有在mdb_interface对应接口下定义
例如,Temperature类在interfaces下配置了TemperatureType属性,但是对应的接口bmc.kepler.Systems.HistoryTemperature在mdb_interface中没有定义该属性。
修复建议: 在mdb_interface对应的接口定义下补充定义。
4.2 mdb_interface中接口属性options配置错误
属性options可选字段为emitsChangedSignal、explicit、deprecated、volatile。其中emitsChangedSignal取值必须是字符串类型,其他取值必须是布尔类型。
修复建议: 在mdb_interface对应的属性定义下纠正配置。
4.3 model.json中配置了持久化的类没有配置表名
配置了持久化指的是类配置了tableType或者至少一个属性的usage里配置了持久化类型,并且类型取值在允许范围内。目前支持的持久化类型有PoweroffPer、ResetPer、TemporaryPer、PoweroffPerRetain、ResetPerRetain、TemporaryPerRetain、PermanentPer,其中PermanentPer只支持远程持久化。
表名可以通过tableName字段配置。
修复建议: 如果需要持久化,在model.json对应的类补充表名配置;如果不需要持久化,则去掉持久化类型配置。
4.4 model.json中配置了远程持久化的类没有配置主键
配置了远程持久化指的是配置了持久化并且没有配置tableLocation: "Local"。配置主键指的是至少一个属性配置了primaryKey: true。
修复建议: 如果需要远程持久化,在model.json对应的类选择属性配置为主键;如果不需要持久化,则去掉表名和持久化类型配置。
4.5 service.json中配置的接口和路径在mdb_interface中没有匹配的定义
自动生成代码会根据组件service.json中required部分配置的path,去掉动态参数后按/分段与json/path/mdb/拼接得到mdb_interface下的目录路径,在该目录下寻找与service.json配置的接口和路径匹配的定义(路径匹配忽略动态参数的不同写法)。
例如,service.json配置了路径/bmc/kepler/Systems/Bios和接口bmc.kepler.Systems.Bios时,则在mdb_interface/json/path/mdb/bmc/kepler/Systems/Bios目录下必须存在path与/bmc/kepler/Systems/Bios匹配并且interfaces至少一个元素与bmc.kepler.Systems.Bios一致。
修复建议: 纠正service.json的接口和路径,与mdb_interface中定义的一致。
5. 注意事项
5.1 如果组件配置的不同资源树接口末段重复,生成代码时相关的命名会进行扩展,手写代码需要适配修改
不同资源树接口末段重复时,所有使用接口末段命名的文件和代码都会防冲突重命名。
例如,gen/App名/json_types目录下生成的文件是以接口末段命名的,如果原先配有接口bmc.kepler.Aa.Bb,生成Bb.lua,新增接口bmc.kepler.Cc.Bb之后,会新生成CcBb.lua,并且原先的Bb.lua也会重命名为AaBb.lua,文件内所有命名用到Bb的地方也会修改为AaBb。包括client.lua中命名用Bb拼接的函数,都会修改为用AaBb拼接,所以手写代码中所有调用这些函数的地方都需要适配修改。
5.2 model.json配置的类名、资源树路径和接口需要与mdb_interface中定义的一致
model.json类配置中定义了path时,其取值去掉动态参数后,必须在mdb_interface/json/path/mdb中目录层级匹配的子目录下有对应的路径定义文件 例如,path定义为
/bmc/kepler/Systems/${SystemId}/Boards/CpuBoard/${Id},去掉动态参数后为/bmc/kepler/Systems/Boards/CpuBoard,所以mdb_interface中对应的路径定义文件必须在mdb_interface/json/path/mdb/bmc/kepler/Systems/Boards/CpuBoard目录下mdb_interface路径定义文件的名称必须与model.json里配置了该path的类名一致 例如,model.json配置类名为
CpuBoardpath,则对应的路径定义文件必须命名为CpuBoardpath.jsonmodel.json在interfaces中配置的接口名称,必须在mdb_interface/json/intf/mdb中存在目录层级匹配的接口定义文件 例如,model.json配置了接口
bmc.kepler.Systems.Board,则mdb_interface中对应的接口定义文件路径必须是mdb_interface/json/intf/mdb/bmc/kepler/Systems/Board.json
6. 自动生成代码调试
调试方法:本地bingo仓修改代码并重新安装本地bingo
git clone远程bingo仓后,可以在本地bingo代码仓修改代码,再在本地bingo代码仓中执行sh install_local.sh命令重新安装本地bingo工具,然后再到组件目录生成代码进行验证。
7. 常见问题
7.1 Bingo gen没有报错但是生成的文件变成空的
通常是因为Lua格式化失败,生成的文件Lua语法错误。原因包括MDS或MDB中定义了非法的属性名(Lua变量名不能以数字开头)等。
可以修改自动生成代码逻辑,注释掉bingo仓template.py文件中的格式化逻辑,然后重新执行bingo gen并检查生成文件的语法错误:
7.2 接口权限错误地配置在methods下,自动生成报"方法 privilege 在mdb_interface中没有定义"
问题是因为MDS/model.json类配置的methods中配置了mdb_interface对应接口下没有定义的方法,纠正错误配置即可。
7.3 mdb_interface文件找不到
报错信息:FileNotFoundError: [Errno 2] No such file or directory: '../temp/opt/bmc/apps/mdb_interface/..'
问题是因为MDS/model.json类配置的path字段配置了mdb_interface中没有定义的路径,需要在mdb_interface补充定义。
注意: 如果查看了mdb_interface里是有定义的,请参考常见问题7.6。
7.4 报错mds_class["interfaces"][intf_name]出现keyError: 'bmc.kepler.xxx'
问题是因为mdb_interface中路径文件定义的interfaces中某个接口在MDS/model.json中没有定义,需要在MDS/model.json补充定义。
例如,/bmc/kepler/Managers/:Id/LogServices/:LogType这个路径在mdb_interface中定义的interfaces包含接口bmc.kepler.Managers.LogService,那么MDS/model.json中对应的类LogService的interface部分也必须配置bmc.kepler.Managers.LogService这个接口。
7.5 组件仓库MDS什么都没有改,为什么生成的代码变了,或者生成的时候报错配置错误
问题是因为变更或报错的资源树配置不在组件仓库,而在mdb_interface仓库。
自动生成代码是根据组件仓库MDS配置,加上MDS里资源树接口/路径在mdb_interface仓库的配置,两者结合生成的。mdb_interface仓库修改了也会影响代码生成。需要排查对应的属性、方法等在mdb_interface的配置。
7.6 查看了mdb_interface是没问题的,为什么生成代码还是变了/报错
问题是因为查看的mdb_interface版本跟自动生成使用的版本不一致。从bingo gen的输出可以看出使用的mdb_interface版本。
7.7 自动生成时mdb_interface没有拉最新版本
问题主要有以下两个原因:
由于conan的机制,生成代码时如果本地conan缓存中的mdb_interface满足service.json配置的版本范围,会优先使用本地缓存,而不会拉取最新的mdb_interface版本。如果需要使用最新版本,可以使用官方命令
conan remove "*" -c手动删除本地缓存。可以执行
conan remote list查看是否有配置openubmc_dev,没有的话需要配置如下:
conan config init
conan remote add openubmc_dev "https://conan.openubmc.cn/conan_1/" false -f
conan user <openUBMC社区用户名> -p <openUBMC社区用户密码> -r openubmc_dev说明: openUBMC社区用户指的是 https://openubmc.cn/ 里的账号。
7.8 查看了mdb_interface中是有定义的,但是service.lua没有生成资源树对象和接口的代码
组件在model.json中字段配置错误会导致对象和接口无法识别。
对象路径是path,接口是interfaces。
7.9 报错/bin/sh: line 0: cd: too many arguments,直接退出
问题是因为本地组件仓库路径包含空格,导致执行cd命令报错。
自动生成代码调用的入口是组件目录下的Makefile,可以在Makefile文件中给TPL_DIR变量加引号解决此问题。
7.10 报错 model.json中类XXX接口XXX的字段XXX超出取值范围
接口下面只能配置properties、signals、methods、privilege这些字段。资源树接口下面挂的属性要放在properties下面。
7.11 报错 protoc: No such file or directory
问题原因是缺少protobuf工具,可以执行命令安装:
apt update
apt install libprotobuf-dev protobuf-compiler7.12 报错 get_ref_type ... KeyError: '$ref'
原因是baseType配置了复杂类型(Array、Struct、Dictionary、Enum),但是没有引用复杂类型的定义。正确配置参考如下例子:
7.13 报错 属性 XXX 没有基类定义或找不到引用
原因是MDS或者mdb_interface中的属性定义没有配置baseType,需要补充baseType字段。
7.14 报错 ALLOW_BASIC_TYPES[prop_data["baseType"]] ... KeyError: XXX
原因是MDS或者mdb_interface中属性配置的baseType不是允许的类型。
baseType配置的值必须在这个范围内:"U8", "U8[]", "U16", "U16[]", "U32", "U32[]", "U64", "U64[]", "S8", "S16", "S16[]", "S32", "S32[]", "S64", "S64[]", "Double", "Double[]", "String", "String[]", "Boolean", "Boolean[]", "Array", "Struct", "Enum", "Dictionary"。
7.15 yaml_include中报错TypeError: 'type' object is not subscriptable
原因是Python版本与pyyaml-include包版本不匹配,以Python 3.8为例,执行以下命令安装与Python版本匹配的pyyaml-include包:
pip install pyyaml-include==1.4.17.16 为什么自动生成的db.lua和orm_classes.lua中的某个类被删除了
问题是因为这个类在model.json中只配置了tableName,没有配置tableType。
旧版本的自动生成代码(codegenPolicy版本 < 14),只配置了tableName,没有配置tableType,并且不是本地持久化的表,默认使用内存数据库。
新版本(codegenPolicy版本 >= 14)需要在model.json中明确声明tableType: Memory。
7.17 报错CalledProcessError: Command 'LUA_FORMAT...', Exec format error: '/usr/bin/lua-format'
问题是因为开发者环境没有安装lua-format工具,需要执行manifest仓库的init.py脚本初始化开发者环境。
如果执行之后仍没有/usr/bin/lua-format文件,建议联系软件工程组构建同事定位问题。
如果执行之后仍有报错,可删除lua-format工具(rm /usr/bin/lua-format),重新在manifest仓库执行init.py脚本初始化。
7.18 merge_model.py报错intf_json[intf_name]出现keyError: 'bmc.kepler.xxx'
问题是因为mdb_interface对应的接口定义文件中,没有定义报错的接口名。
通常是因为开发人员的配置错误基础问题:接口定义文件格式错误,或者接口名拼写错误。
原理: 自动生成代码时,根据model.json中定义接口在mdb_interface的json/intf中找到对应的文件路径,再从文件中读取接口定义,如果文件中没有这个接口的定义就会报此错误。