openubmc-bingo 0.5.240__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openubmc-bingo might be problematic. Click here for more details.

Files changed (242) hide show
  1. bmcgo/__init__.py +12 -0
  2. bmcgo/bmcgo.py +22 -0
  3. bmcgo/bmcgo_config.py +176 -0
  4. bmcgo/cli/__init__.py +10 -0
  5. bmcgo/cli/cli.py +584 -0
  6. bmcgo/codegen/__init__.py +14 -0
  7. bmcgo/codegen/c/__init__.py +9 -0
  8. bmcgo/codegen/c/annotation.py +52 -0
  9. bmcgo/codegen/c/argument.py +42 -0
  10. bmcgo/codegen/c/codegen.py +153 -0
  11. bmcgo/codegen/c/comment.py +22 -0
  12. bmcgo/codegen/c/ctype_defination.py +353 -0
  13. bmcgo/codegen/c/helper.py +87 -0
  14. bmcgo/codegen/c/interface.py +63 -0
  15. bmcgo/codegen/c/method.py +82 -0
  16. bmcgo/codegen/c/property.py +180 -0
  17. bmcgo/codegen/c/renderer.py +21 -0
  18. bmcgo/codegen/c/signal.py +64 -0
  19. bmcgo/codegen/c/template/client.c.mako +145 -0
  20. bmcgo/codegen/c/template/client.h.mako +36 -0
  21. bmcgo/codegen/c/template/interface.c.mako +0 -0
  22. bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
  23. bmcgo/codegen/c/template/micro_component.c.mako +32 -0
  24. bmcgo/codegen/c/template/public.c.mako +228 -0
  25. bmcgo/codegen/c/template/public.h.mako +128 -0
  26. bmcgo/codegen/c/template/server.c.mako +104 -0
  27. bmcgo/codegen/c/template/server.h.mako +36 -0
  28. bmcgo/codegen/lua/.lua-format +7 -0
  29. bmcgo/codegen/lua/Makefile +101 -0
  30. bmcgo/codegen/lua/__init__.py +9 -0
  31. bmcgo/codegen/lua/codegen.py +171 -0
  32. bmcgo/codegen/lua/proto/Makefile +87 -0
  33. bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
  34. bmcgo/codegen/lua/proto/types.proto +52 -0
  35. bmcgo/codegen/lua/script/check_intfs.py +161 -0
  36. bmcgo/codegen/lua/script/dto/__init__.py +11 -0
  37. bmcgo/codegen/lua/script/dto/exception.py +53 -0
  38. bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
  39. bmcgo/codegen/lua/script/dto/options.py +33 -0
  40. bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
  41. bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
  42. bmcgo/codegen/lua/script/dto/url_route.py +195 -0
  43. bmcgo/codegen/lua/script/gen_db_json.py +444 -0
  44. bmcgo/codegen/lua/script/gen_depends.py +89 -0
  45. bmcgo/codegen/lua/script/gen_entry.py +263 -0
  46. bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
  47. bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
  48. bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
  49. bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
  50. bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
  51. bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
  52. bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
  53. bmcgo/codegen/lua/script/gen_schema.py +302 -0
  54. bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
  55. bmcgo/codegen/lua/script/loader/__init__.py +11 -0
  56. bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
  57. bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
  58. bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
  59. bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
  60. bmcgo/codegen/lua/script/lua_format.py +62 -0
  61. bmcgo/codegen/lua/script/mds_util.py +385 -0
  62. bmcgo/codegen/lua/script/merge_model.py +330 -0
  63. bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
  64. bmcgo/codegen/lua/script/proto_loader.py +47 -0
  65. bmcgo/codegen/lua/script/proto_plugin.py +140 -0
  66. bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
  67. bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
  68. bmcgo/codegen/lua/script/render_utils/base.py +25 -0
  69. bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
  70. bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
  71. bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
  72. bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
  73. bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
  74. bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
  75. bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
  76. bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
  77. bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
  78. bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
  79. bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
  80. bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
  81. bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
  82. bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
  83. bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
  84. bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
  85. bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
  86. bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
  87. bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
  88. bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
  89. bmcgo/codegen/lua/script/template.py +166 -0
  90. bmcgo/codegen/lua/script/types_pb2.py +516 -0
  91. bmcgo/codegen/lua/script/utils.py +663 -0
  92. bmcgo/codegen/lua/script/validate.py +80 -0
  93. bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
  94. bmcgo/codegen/lua/templates/Makefile +114 -0
  95. bmcgo/codegen/lua/templates/apps/Makefile +261 -0
  96. bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
  97. bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
  98. bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
  99. bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
  100. bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
  101. bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
  102. bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
  103. bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
  104. bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
  105. bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
  106. bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
  107. bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
  108. bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
  109. bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
  110. bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
  111. bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
  112. bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
  113. bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
  114. bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
  115. bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
  116. bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
  117. bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
  118. bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
  119. bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
  120. bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
  121. bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
  122. bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
  123. bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
  124. bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
  125. bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
  126. bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
  127. bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
  128. bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
  129. bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
  130. bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
  131. bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
  132. bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
  133. bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
  134. bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
  135. bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
  136. bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
  137. bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
  138. bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
  139. bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
  140. bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
  141. bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
  142. bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
  143. bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
  144. bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
  145. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
  146. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
  147. bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
  148. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
  149. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
  150. bmcgo/component/__init__.py +10 -0
  151. bmcgo/component/analysis/analysis.py +183 -0
  152. bmcgo/component/analysis/build_deps.py +165 -0
  153. bmcgo/component/analysis/data_deps.py +333 -0
  154. bmcgo/component/analysis/dep-rules.json +912 -0
  155. bmcgo/component/analysis/dep_node.py +110 -0
  156. bmcgo/component/analysis/intf_deps.py +163 -0
  157. bmcgo/component/analysis/intf_validation.py +254 -0
  158. bmcgo/component/analysis/rule.py +211 -0
  159. bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
  160. bmcgo/component/analysis/sr_validation.py +391 -0
  161. bmcgo/component/build.py +222 -0
  162. bmcgo/component/component_dt_version_parse.py +348 -0
  163. bmcgo/component/component_helper.py +114 -0
  164. bmcgo/component/coverage/__init__.py +11 -0
  165. bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
  166. bmcgo/component/coverage/incremental_cov.py +464 -0
  167. bmcgo/component/deploy.py +110 -0
  168. bmcgo/component/gen.py +169 -0
  169. bmcgo/component/package_info.py +236 -0
  170. bmcgo/component/template/conanbase.py.mako +278 -0
  171. bmcgo/component/template/conanfile.deploy.py.mako +40 -0
  172. bmcgo/component/test.py +947 -0
  173. bmcgo/errors.py +119 -0
  174. bmcgo/frame.py +217 -0
  175. bmcgo/functional/__init__.py +10 -0
  176. bmcgo/functional/analysis.py +96 -0
  177. bmcgo/functional/bmc_studio_action.py +98 -0
  178. bmcgo/functional/check.py +185 -0
  179. bmcgo/functional/conan_index_build.py +251 -0
  180. bmcgo/functional/config.py +332 -0
  181. bmcgo/functional/csr_build.py +724 -0
  182. bmcgo/functional/deploy.py +263 -0
  183. bmcgo/functional/diff.py +235 -0
  184. bmcgo/functional/fetch.py +235 -0
  185. bmcgo/functional/full_component.py +391 -0
  186. bmcgo/functional/maintain.py +381 -0
  187. bmcgo/functional/new.py +166 -0
  188. bmcgo/functional/schema_valid.py +111 -0
  189. bmcgo/functional/simple_sign.py +104 -0
  190. bmcgo/functional/upgrade.py +78 -0
  191. bmcgo/ipmigen/__init__.py +13 -0
  192. bmcgo/ipmigen/ctype_defination.py +82 -0
  193. bmcgo/ipmigen/ipmigen.py +309 -0
  194. bmcgo/ipmigen/template/cmd.c.mako +366 -0
  195. bmcgo/ipmigen/template/ipmi.c.mako +25 -0
  196. bmcgo/ipmigen/template/ipmi.h.mako +51 -0
  197. bmcgo/logger.py +176 -0
  198. bmcgo/misc.py +117 -0
  199. bmcgo/target/app.yml +17 -0
  200. bmcgo/target/install_sdk.yml +15 -0
  201. bmcgo/target/personal.yml +53 -0
  202. bmcgo/target/publish.yml +45 -0
  203. bmcgo/tasks/__init__.py +11 -0
  204. bmcgo/tasks/download_buildtools_hm.py +124 -0
  205. bmcgo/tasks/misc.py +15 -0
  206. bmcgo/tasks/task.py +354 -0
  207. bmcgo/tasks/task_build_conan.py +714 -0
  208. bmcgo/tasks/task_build_rootfs_img.py +595 -0
  209. bmcgo/tasks/task_buildgppbin.py +88 -0
  210. bmcgo/tasks/task_buildhpm_ext4.py +82 -0
  211. bmcgo/tasks/task_create_interface_config.py +122 -0
  212. bmcgo/tasks/task_download_buildtools.py +99 -0
  213. bmcgo/tasks/task_download_dependency.py +72 -0
  214. bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
  215. bmcgo/tasks/task_packet_to_supporte.py +87 -0
  216. bmcgo/tasks/task_prepare.py +105 -0
  217. bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
  218. bmcgo/utils/__init__.py +10 -0
  219. bmcgo/utils/buffer.py +128 -0
  220. bmcgo/utils/combine_json_schemas.py +170 -0
  221. bmcgo/utils/component_post.py +54 -0
  222. bmcgo/utils/component_version_check.py +86 -0
  223. bmcgo/utils/config.py +1067 -0
  224. bmcgo/utils/fetch_component_code.py +232 -0
  225. bmcgo/utils/install_manager.py +61 -0
  226. bmcgo/utils/installations/__init__.py +10 -0
  227. bmcgo/utils/installations/base_installer.py +70 -0
  228. bmcgo/utils/installations/install_consts.py +30 -0
  229. bmcgo/utils/installations/install_plans/bingo.yml +11 -0
  230. bmcgo/utils/installations/install_workflow.py +50 -0
  231. bmcgo/utils/installations/installers/apt_installer.py +177 -0
  232. bmcgo/utils/installations/installers/pip_installer.py +46 -0
  233. bmcgo/utils/installations/version_util.py +100 -0
  234. bmcgo/utils/mapping_config_patch.py +443 -0
  235. bmcgo/utils/perf_analysis.py +114 -0
  236. bmcgo/utils/tools.py +704 -0
  237. bmcgo/worker.py +417 -0
  238. openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
  239. openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
  240. openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
  241. openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
  242. openubmc_bingo-0.5.240.dist-info/top_level.txt +1 -0
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+
13
+ import json
14
+ import os
15
+ import sys
16
+
17
+ from typing import List, Set
18
+ from bmcgo.logger import Logger
19
+
20
+ global log
21
+ log = Logger()
22
+
23
+ TABLE_CONFLICT_WHITE_LIST = {"nsm": "t_snmp_config", "event_policy": "t_snmp_config"}
24
+
25
+
26
+ class DepNode():
27
+ ref: str
28
+ options: str
29
+ package_id: str
30
+ revision: str
31
+
32
+ def __init__(self, node: dict, index):
33
+ self.ref = node.get("ref")
34
+ self.options = node.get("options")
35
+ self.package_id = node.get("package_id", "")
36
+ self.revision = node.get("revision")
37
+ self.requires: List[DepNode] = []
38
+ self.name = self.ref.split("@", 1)[0]
39
+ self.package_name = self.name.split("/", 1)[0]
40
+ self.package_version = self.name.split("/", 1)[-1]
41
+ self.index = int(index)
42
+ self.model_path = "unknown"
43
+ self.subsys_name = "unknown"
44
+ self.subsys_level = 1000
45
+ self.package_type = [] # 可选library, app, tool, configuration, command
46
+ self.intf_impl: Set[str] = set()
47
+ self.intf_deps: Set[str] = set()
48
+ self.local_tables = {}
49
+ self.remote_tables = {}
50
+ self.table_conflict = False
51
+ self._parse_mds()
52
+
53
+ @staticmethod
54
+ def _get_class_properties(class_data):
55
+ properties = set()
56
+ for _, intf_data in class_data.get("interfaces", {}).items():
57
+ for prop, prop_data in intf_data.get("properties", {}).items():
58
+ properties.add(prop_data.get("alias", prop))
59
+ for prop, prop_data in class_data.get("properties", {}).items():
60
+ properties.add(prop_data.get("alias", prop))
61
+ return properties
62
+
63
+ def set_subsys(self, subsys_name, subsys_level):
64
+ self.subsys_name = subsys_name
65
+ self.subsys_level = subsys_level
66
+
67
+ def set_package_type(self, package_type):
68
+ if package_type not in ["Library", "App", "Tool", "Configuration", "Command"]:
69
+ raise Exception("包类型错误")
70
+ self.package_type.append(package_type)
71
+
72
+ def _collect_table_info(self, class_data):
73
+ if "tableName" not in class_data:
74
+ return
75
+
76
+ table_name = class_data["tableName"]
77
+ if class_data.get("tableLocation", "") == "Local":
78
+ if table_name in self.local_tables:
79
+ log.error("%s中本地持久化表名冲突: %s", self.package_name, table_name)
80
+ self.table_conflict = True
81
+ self.local_tables[table_name] = True
82
+ else:
83
+ if table_name in self.remote_tables:
84
+ log.error("%s中远程持久化表名冲突: %s", self.package_name, table_name)
85
+ self.table_conflict = True
86
+ if self.package_name in TABLE_CONFLICT_WHITE_LIST \
87
+ and table_name == TABLE_CONFLICT_WHITE_LIST[self.package_name]:
88
+ self.remote_tables[table_name] = DepNode._get_class_properties(class_data)
89
+ else:
90
+ self.remote_tables[table_name] = True
91
+
92
+ def _parse_mds(self):
93
+ pkg_dir = self.ref.split("#")[0].replace("@", "/")
94
+ package_source = os.path.join(os.environ["HOME"], ".conan/data", pkg_dir, "package", self.package_id)
95
+ mds_path = os.path.join(package_source, "include/mds")
96
+ self.model_path = os.path.join(mds_path, "model.json")
97
+ if os.path.exists(self.model_path):
98
+ with open(self.model_path, "r") as file_descriptor:
99
+ model_data = json.load(file_descriptor)
100
+ for class_name in model_data:
101
+ self._collect_table_info(model_data[class_name])
102
+ for intf in model_data[class_name].get("interfaces", {}):
103
+ self.intf_impl.add(intf)
104
+ service_path = os.path.join(mds_path, "service.json")
105
+ if os.path.exists(service_path):
106
+ with open(service_path, "r") as file_descriptor:
107
+ service_data = json.load(file_descriptor)
108
+ for intf_entry in service_data.get("required", []):
109
+ if "interface" in intf_entry:
110
+ self.intf_deps.add(intf_entry.get("interface"))
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+
13
+ from collections import defaultdict
14
+ from typing import Dict, List
15
+ import json
16
+ import os
17
+ import stat
18
+
19
+ from pyecharts import options as opts
20
+ from pyecharts.charts import Graph
21
+ from pyecharts.options import GraphLink, GraphNode
22
+
23
+ from bmcgo.component.analysis.dep_node import DepNode
24
+ from bmcgo.component.analysis.rule import Rules
25
+ from bmcgo.logger import Logger
26
+ from bmcgo import misc
27
+
28
+ global log
29
+ log = Logger()
30
+ INTERFACE_DEPENDENCIES = "interfaceDependencies"
31
+
32
+
33
+ class InterfaceDependenciesAnalysis():
34
+ def __init__(self, nodes: List[DepNode], rules: List[Rules]):
35
+ # All packages in the conan build data
36
+ self._nodes: List[DepNode] = list()
37
+ # Select packages that have dependencies on d-bus
38
+ for node in nodes:
39
+ if len(node.intf_impl) != 0 or len(node.intf_deps) != 0:
40
+ self._nodes.append(node)
41
+ self._rules = rules
42
+
43
+ # All d-bus interfaces that the package implements
44
+ self.node_impl_intfs: Dict[str, List[DepNode]] = defaultdict(list)
45
+
46
+ # All d-bus interfaces the package depends on
47
+ self.node_deps_intfs: Dict[str, List[DepNode]] = defaultdict(list)
48
+
49
+ # The package dependency graph: vertex are conan packages and edges are interfaces
50
+ self.intf_deps_graph: Dict[str, Dict[str, List[str]]] = defaultdict(dict)
51
+ self.intf_deps_unallowed_graph: Dict[str, Dict[str, List[str]]] = defaultdict(dict)
52
+
53
+ self._node_intf_relation()
54
+
55
+ def is_dependency_allowed(self):
56
+ return not bool(self.intf_deps_unallowed_graph)
57
+
58
+ def assemble_deps_json_desc(self, path):
59
+ node_name_map = dict()
60
+ for node in self._nodes:
61
+ node_name_map[node.package_name] = {
62
+ misc.NAME: node.package_name,
63
+ "version": node.package_version,
64
+ "subsystem": node.subsys_name,
65
+ "type": node.package_type
66
+ }
67
+
68
+ json_dict = {"InterfaceDependencyGraph": [], "IllegalInterfaceDependencyGraph": []}
69
+ for src in self.intf_deps_graph:
70
+ entry = {"sourceComponent": node_name_map.get(src), INTERFACE_DEPENDENCIES: []}
71
+ for tgt, intfs in self.intf_deps_graph[src].items():
72
+ entry[INTERFACE_DEPENDENCIES].append({"targetComponent": node_name_map.get(tgt), "interfaces": intfs})
73
+ json_dict["InterfaceDependencyGraph"].append(entry)
74
+
75
+ for src in self.intf_deps_unallowed_graph:
76
+ entry = {"sourceComponent": node_name_map.get(src), INTERFACE_DEPENDENCIES: []}
77
+ for tgt, intfs in self.intf_deps_unallowed_graph[src].items():
78
+ entry[INTERFACE_DEPENDENCIES].append({"targetComponent": node_name_map.get(tgt), "interfaces": intfs})
79
+ json_dict["IllegalInterfaceDependencyGraph"].append(entry)
80
+
81
+ log.info("保存 BMC 组件 d-bus 接口依赖信息到: %s", path)
82
+ flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
83
+ modes = stat.S_IWUSR | stat.S_IRUSR
84
+ with os.fdopen(os.open(path, flags, modes), 'w') as file_descriptor:
85
+ file_descriptor.write(json.dumps(json_dict, indent=4))
86
+
87
+ def visualize_graph(self, path):
88
+ subsystems = set()
89
+ for pkg in self._nodes:
90
+ subsystems.add(pkg.subsys_name)
91
+ categories = []
92
+ for subsys in subsystems:
93
+ categories.append({misc.NAME: subsys, "symbolSize": 100})
94
+ categories.append({misc.NAME: "unknown", "symbolSize": 100})
95
+ category_id_map: Dict[str, int] = dict()
96
+ for index, category in enumerate(categories):
97
+ category_id_map[category[misc.NAME]] = index
98
+
99
+ graph_nodes: List[GraphNode] = []
100
+ for pkg in self._nodes:
101
+ graph_nodes.append(GraphNode(name=pkg.package_name, symbol_size=5, \
102
+ category=category_id_map.get(pkg.subsys_name, len(categories))))
103
+
104
+ links: list[GraphLink] = []
105
+ for src in self.intf_deps_graph:
106
+ for dest, intfs in self.intf_deps_graph[src].items():
107
+ if src in self.intf_deps_unallowed_graph and dest in self.intf_deps_unallowed_graph[src]:
108
+ links.append(GraphLink(
109
+ source=src,
110
+ target=dest,
111
+ linestyle_opts=opts.LineStyleOpts(color=misc.COLOR_RED, curve=0.2, width=1.5),
112
+ value=self.intf_deps_unallowed_graph[src][dest]))
113
+ else:
114
+ links.append(GraphLink(source=src, target=dest, value=intfs))
115
+
116
+ log.info("保存 BMC 组件 d-bus 接口依赖信息到: %s", path)
117
+ (Graph(init_opts=opts.InitOpts(width="100%", height="1200px", page_title="BMC-Interface-Dependency-Graph"))
118
+ .add("", graph_nodes, links, categories,
119
+ repulsion=100,
120
+ is_draggable=False,
121
+ edge_symbol="arrow",
122
+ edge_symbol_size=[0, 5],
123
+ is_layout_animation=False,
124
+ label_opts=opts.LabelOpts(position="right", formatter="{b}"))
125
+ .set_global_opts(
126
+ title_opts=opts.TitleOpts(title="Graph-BMC-Interface-Dependency-Graph"),
127
+ legend_opts=opts.LegendOpts(orient="vertical", pos_left="2%", pos_top="20%"))
128
+ .render(path))
129
+
130
+ def _node_intf_relation(self):
131
+ self._construct_node_intf_detail()
132
+
133
+ for intf, nodes in self.node_deps_intfs.items():
134
+ if intf not in self.node_impl_intfs:
135
+ continue
136
+ for src in nodes:
137
+ for tgt in self.node_impl_intfs[intf]:
138
+ self._add_two_node_relation(src, tgt, intf)
139
+
140
+ def _construct_node_intf_detail(self):
141
+ for node in self._nodes:
142
+ for intfi in node.intf_impl:
143
+ self.node_impl_intfs[intfi].append(node)
144
+ for intfd in node.intf_deps:
145
+ self.node_deps_intfs[intfd].append(node)
146
+
147
+ def _add_two_node_relation(self, src: DepNode, tgt: DepNode, intf: str):
148
+ interface_relation = self.intf_deps_graph[src.package_name].get(tgt.package_name, [])
149
+ interface_relation.append(intf)
150
+ self.intf_deps_graph[src.package_name][tgt.package_name] = interface_relation
151
+ if self._check_intf_dependency(src, tgt, intf):
152
+ return
153
+ unallowed_interface_relation = self.intf_deps_unallowed_graph[src.package_name].get(tgt.package_name, [])
154
+ unallowed_interface_relation.append(intf)
155
+ self.intf_deps_unallowed_graph[src.package_name][tgt.package_name] = unallowed_interface_relation
156
+
157
+ def _check_intf_dependency(self, src: DepNode, tgt: DepNode, intf: str):
158
+ for rules in self._rules:
159
+ if rules.intf_dep_check(src, tgt, intf):
160
+ return True
161
+ log.error("发现不合规的总线接口依赖, 源包: %s, 目标包: %s",
162
+ src.name, tgt.name)
163
+ return False
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+
13
+ from collections import defaultdict
14
+ from typing import Dict, Set
15
+ import json
16
+ import os
17
+ import re
18
+ import shutil
19
+ import subprocess
20
+
21
+ from bmcgo.logger import Logger
22
+ from bmcgo.codegen.c.helper import Helper
23
+ from bmcgo import misc
24
+
25
+ global log
26
+ log = Logger()
27
+
28
+
29
+ class InterfaceValidation:
30
+ def __init__(self, remote):
31
+ self.intf_impl: Set[str] = set()
32
+ self.intf_deps: Set[str] = set()
33
+ self.intf_hardcoded: Dict[str, Set[str]] = defaultdict(set)
34
+ self.all_predefined_intfs: Set[str] = set()
35
+ self.remote = remote
36
+ self._parse_mds_interfaces()
37
+ self._parse_hardcoded_interfaces()
38
+ self._pull_all_interfaces()
39
+
40
+ @staticmethod
41
+ def extract_dbus_intf_in_file(file_path):
42
+ all_intfs = list()
43
+ with open(file_path, "r") as file_descriptor:
44
+ # iBMC d-bus interface pattern: bmc.(kepler|dev).[A-Z]
45
+ pattern = "[\"\']bmc\.(?:kepler|dev)(?:\.[A-Z].*?)?[\"\']"
46
+ intf_match = re.findall(pattern, file_descriptor.read())
47
+ for intf in intf_match:
48
+ all_intfs.append(intf[1:-1])
49
+ return all_intfs
50
+
51
+ @staticmethod
52
+ def _check_bus_call_in_file(file_path):
53
+ patterns = ["bus:p?call\(.+\n?"]
54
+ has_pattern = False
55
+ with open(file_path, "r") as file_descriptor:
56
+ src_lua = file_descriptor.read()
57
+ for pattern in patterns:
58
+ bus_call = re.findall(pattern, src_lua)
59
+ if len(bus_call) != 0:
60
+ log.error("在 %s 发现非自动生成的代码调用, 匹配到: %s. 请使用代码自动生成(generation)", file_path, pattern)
61
+ has_pattern = True
62
+ return has_pattern
63
+
64
+ @staticmethod
65
+ def _parse_mds_package_deps():
66
+ channel = f"@{misc.ConanUserEnum.CONAN_USER_RELEASE.value}/{misc.StageEnum.STAGE_RC.value}"
67
+ package = f"mdb_interface/[>=0.0.1]{channel}"
68
+ service_path = os.path.join(os.getcwd(), "mds/service.json")
69
+ if not os.path.exists(service_path):
70
+ return package
71
+ with open(service_path, "r") as service_fp:
72
+ try:
73
+ content = json.load(service_fp)
74
+ except json.decoder.JSONDecodeError as error:
75
+ return package
76
+ dependencies = content.get("dependencies")
77
+ if not dependencies:
78
+ return package
79
+ dep_list = dependencies.get("test", [])
80
+ dep_list.extend(dependencies.get("build", []))
81
+ for dep in dep_list:
82
+ conan_package = dep.get(misc.CONAN, "")
83
+ if not conan_package.startswith("mdb_interface"):
84
+ continue
85
+ if "@" in conan_package:
86
+ package = conan_package
87
+ else:
88
+ package = f"{conan_package}{channel}"
89
+ return package
90
+
91
+ def run(self):
92
+ intf_validation_passed = self._validate_mds_intf() and self._validate_hardcoded_intf() and \
93
+ self._check_dbus_call()
94
+ if intf_validation_passed:
95
+ log.info("接口检验通过")
96
+ else:
97
+ log.error("接口校验未通过")
98
+ return intf_validation_passed
99
+
100
+ def _parse_mds_interfaces(self):
101
+ mds_model_path = os.path.join(os.getcwd(), "mds/model.json")
102
+ if not os.path.exists(mds_model_path):
103
+ return
104
+ with open(mds_model_path, "r") as file_descriptor:
105
+ try:
106
+ model_data = json.load(file_descriptor)
107
+ except json.decoder.JSONDecodeError as error:
108
+ raise OSError(f"无法加载文件 {mds_model_path}, 错误消息: {error.msg}") from error
109
+ else:
110
+ for class_name in model_data:
111
+ self.intf_impl.update(model_data[class_name].get("interfaces", {}).keys())
112
+
113
+ mds_service_path = os.path.join(os.getcwd(), "mds/service.json")
114
+ if not os.path.exists(mds_service_path):
115
+ return
116
+ with open(mds_service_path, "r") as file_descriptor:
117
+ try:
118
+ service_data = json.load(file_descriptor)
119
+ except json.decoder.JSONDecodeError as error:
120
+ raise OSError(f"无法加载文件 {mds_model_path}, 错误消息: {error.msg}") from error
121
+ else:
122
+ for require_object in service_data.get("required", []):
123
+ self.intf_deps.add(require_object.get("interface"))
124
+
125
+ """
126
+ @brief: parse the d-bus interface claimed in the source code
127
+ """
128
+ def _parse_hardcoded_interfaces(self):
129
+ for root, _, files in os.walk(os.path.join(os.getcwd(), "", "src")):
130
+ for file_name in files:
131
+ if not file_name.endswith(".lua"):
132
+ continue
133
+ file_path = os.path.join(root, file_name)
134
+ for intf in self.extract_dbus_intf_in_file(file_path):
135
+ self.intf_hardcoded[intf].update([file_path])
136
+
137
+ def _pull_interfaces_from_repo(self):
138
+ mdb_interface_repo_url = "https://gitcode.com/openUBMC/mdb_interface.git"
139
+ mktemp_cmd = subprocess.run(["/usr/bin/mktemp", "-d", "--suffix", "_mdb_interface"], capture_output=True)
140
+ if mktemp_cmd.returncode != 0:
141
+ raise OSError(f"创建文件夹失败, 错误消息: {mktemp_cmd.stderr}")
142
+ temp_dir = mktemp_cmd.stdout.decode().strip('\n')
143
+
144
+ git_cmd = Helper.get_git_path()
145
+ repo_fetch = subprocess.run(
146
+ [git_cmd, "clone", mdb_interface_repo_url, temp_dir, "--depth=1"],
147
+ stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
148
+ if repo_fetch.returncode != 0:
149
+ log.error("克隆远端仓库 %s 失败, 错误信息: %s", mdb_interface_repo_url, repo_fetch.stderr)
150
+ intf_dir = os.path.join(temp_dir, "json/intf/mdb/bmc")
151
+
152
+ for root, _, files in os.walk(intf_dir):
153
+ for file_name in files:
154
+ if not file_name.endswith(".json"):
155
+ continue
156
+ file_path = os.path.join(root, file_name)
157
+ self.all_predefined_intfs.update(intf for intf in self.extract_dbus_intf_in_file(file_path))
158
+
159
+ shutil.rmtree(temp_dir, ignore_errors=True)
160
+
161
+ def _pull_interfaces_from_conan(self):
162
+ pkg = self._parse_mds_package_deps()
163
+ mktemp_cmd = subprocess.run(["/usr/bin/mktemp", "-d", "--suffix", "_mdb_interface"], capture_output=True)
164
+ if mktemp_cmd.returncode != 0:
165
+ raise OSError(f"创建文件夹失败, 错误消息: {mktemp_cmd.stderr}")
166
+ temp_dir = mktemp_cmd.stdout.decode().strip('\n')
167
+ cmd = [misc.CONAN, "install", pkg, f"-if={temp_dir}", "--build=missing", "-g", "deploy", "-s", "build_type=Dt"]
168
+ if self.remote:
169
+ cmd += ["-r", self.remote]
170
+ subprocess.call(cmd)
171
+ intf_dir = os.path.join(temp_dir, "mdb_interface/opt/bmc/apps/mdb_interface/intf/mdb/bmc")
172
+
173
+ for root, _, files in os.walk(intf_dir):
174
+ for file_name in files:
175
+ if not file_name.endswith(".json"):
176
+ continue
177
+ file_path = os.path.join(root, file_name)
178
+ self.all_predefined_intfs.update(intf for intf in self.extract_dbus_intf_in_file(file_path))
179
+ shutil.rmtree(temp_dir, ignore_errors=True)
180
+
181
+ def _pull_interfaces_from_codegen(self):
182
+ service_path = os.path.join(os.getcwd(), "mds/service.json")
183
+ try:
184
+ with open(service_path, 'r') as file_descriptor:
185
+ repo_name = json.load(file_descriptor).get('name')
186
+ except Exception as e:
187
+ log.error('mds/service.json 文件解析失败: %s', e)
188
+ return
189
+ generated_intf_dir = os.path.join(os.getcwd(), "gen", repo_name, "json_types")
190
+ for root, _, files in os.walk(generated_intf_dir):
191
+ for file_name in files:
192
+ if not file_name.endswith(".lua"):
193
+ continue
194
+ file_path = os.path.join(root, file_name)
195
+ self.all_predefined_intfs.update(intf for intf in self.extract_dbus_intf_in_file(file_path))
196
+ client_intf_path = os.path.join(os.getcwd(), "gen", repo_name, "client.lua")
197
+ if not os.path.exists(client_intf_path):
198
+ return
199
+ self.all_predefined_intfs.update(intf for intf in self.extract_dbus_intf_in_file(client_intf_path))
200
+
201
+ """
202
+ @brief: fetch the mdb_interface repository and parse all predefined d-bus interfaces
203
+ """
204
+ def _pull_all_interfaces(self):
205
+ self._pull_interfaces_from_repo()
206
+ self._pull_interfaces_from_conan()
207
+ self._pull_interfaces_from_codegen()
208
+
209
+ """
210
+ @brief: check the d-bus interfaces claimed in mds are defined in mdb_interface
211
+ """
212
+ def _validate_mds_intf(self):
213
+ intf_impl_in_mdb = True
214
+ intf_deps_in_mdb = True
215
+ for intf in self.intf_impl:
216
+ if intf not in self.all_predefined_intfs:
217
+ log.error("在 mds/model.json 中找到未定义的接口: %s", intf)
218
+ intf_impl_in_mdb = False
219
+
220
+ for intf in self.intf_deps:
221
+ if intf not in self.all_predefined_intfs:
222
+ log.error("在 mds/service.json 找到未定义的接口: %s", intf)
223
+ intf_deps_in_mdb = False
224
+
225
+ return intf_impl_in_mdb and intf_deps_in_mdb
226
+
227
+ """
228
+ @brief: check the hardcoded d-bus interfaces in the source lua code are claimed in mds and mdb_interface
229
+ """
230
+ def _validate_hardcoded_intf(self):
231
+ hardcoded_intf_in_mdb = True
232
+ hardcode_intf_in_mds = True
233
+ for intf, paths in self.intf_hardcoded.items():
234
+ if intf not in self.all_predefined_intfs:
235
+ log.error("在 %s 找到 未定义的接口 %s. 请检查你的源码", paths, intf)
236
+ hardcoded_intf_in_mdb = False
237
+ if intf not in self.intf_impl and intf not in self.intf_deps:
238
+ log.warning("在 %s 找到 未定义的接口 %s. 请使用 mds 模板", paths, intf)
239
+ hardcoded_intf_in_mds = False
240
+ return hardcoded_intf_in_mdb
241
+
242
+ """
243
+ @brief: check d-bus call snippet in source code. It is recommend to use generated templates for d-bus call.
244
+ """
245
+ def _check_dbus_call(self):
246
+ has_pattern = False
247
+ for root, _, files in os.walk(os.path.join(os.getcwd(), "src")):
248
+ for file_name in files:
249
+ if not file_name.endswith(".lua"):
250
+ continue
251
+ file_path = os.path.join(root, file_name)
252
+ if self._check_bus_call_in_file(file_path):
253
+ has_pattern = True
254
+ return not has_pattern