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,211 @@
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 enum import Enum
14
+
15
+ from bmcgo.component.analysis.dep_node import DepNode
16
+ from bmcgo.logger import Logger
17
+
18
+ global log
19
+ log = Logger()
20
+
21
+
22
+ class SubSys():
23
+ def __init__(self, level: int):
24
+ self.level = level
25
+ self.apps: list[str] = []
26
+ self.libraries: list[str] = []
27
+ self.tools: list[str] = []
28
+ self.configurations: list[str] = []
29
+ self.commands: list[str] = []
30
+
31
+
32
+ class DepExcept():
33
+ def __init__(self, obj):
34
+ self.tag = obj.get("tag")
35
+ self.operator = obj.get("op")
36
+ self.value = obj.get("value", [])
37
+
38
+
39
+ class DepWhen():
40
+ def __init__(self, obj):
41
+ self.tag = obj.get("tag")
42
+ self.operator = obj.get("op")
43
+ self.value = obj.get("value", [])
44
+
45
+
46
+ class DepRuleType(Enum):
47
+ SUBSYSTEM_DEP = 1
48
+ INTERFACE_DEP = 2
49
+ BUILD_DEP = 3
50
+
51
+
52
+ class Rule():
53
+ def __init__(self, rule_type: DepRuleType, obj):
54
+ self.rule_type = rule_type
55
+ self.from_key = obj.get("from")
56
+ self.to_key = obj.get("to")
57
+ self.description = obj.get("description")
58
+ self.message = obj.get("message")
59
+ if not self.from_key or not self.to_key:
60
+ log.error("无法从 json 对象中获取 'from' 或 'to'")
61
+ self.whe = None
62
+ self.excpt = None
63
+ excpt = obj.get("except")
64
+ if excpt:
65
+ self.excpt = DepExcept(excpt)
66
+ whe = obj.get("when")
67
+ if whe:
68
+ self.whe = DepWhen(whe)
69
+
70
+ # 检查src和tgt是否适用当前的规则
71
+ def match_rule(self, src: DepNode, tgt: DepNode):
72
+ from_matched = self.from_key == "*" or self.from_key in src.package_type
73
+ to_matched = self.to_key == "*" or self.to_key in tgt.package_type
74
+ return from_matched and to_matched
75
+
76
+ # 检查from_key和to_key是否适用当前的规则
77
+ def match_rule(self, from_key: str, to_key: str):
78
+ from_matched = self.from_key == "*" or self.from_key == from_key
79
+ to_matched = self.to_key == "*" or self.to_key == to_key
80
+ return from_matched and to_matched
81
+
82
+ def build_dep_check(self, src: DepNode, tgt: DepNode):
83
+ if self.rule_type != DepRuleType.BUILD_DEP:
84
+ return False
85
+ return not self.whe
86
+
87
+ def subsystem_dep_check(self, src: DepNode, tgt: DepNode, intf: str):
88
+ if self.rule_type != DepRuleType.SUBSYSTEM_DEP:
89
+ return False
90
+ if self.from_key != src.subsys_name or self.to_key != tgt.subsys_name:
91
+ return False
92
+ if not self.excpt:
93
+ return True
94
+ # Currently the input rule only defines one single exception
95
+ return self.excpt.tag == "Interface" and self.excpt.operator == "oneOf" and intf not in self.excpt.value
96
+
97
+ def intf_dep_check(self, src: DepNode, tgt: DepNode, intf: str):
98
+ if self.rule_type != DepRuleType.INTERFACE_DEP:
99
+ return False
100
+ if self.from_key != src.package_name or self.to_key != tgt.package_name:
101
+ return False
102
+ if not self.excpt:
103
+ return True
104
+ return self.excpt.tag == "Interface" and self.excpt.operator == "oneOf" and intf not in self.excpt.value
105
+
106
+
107
+ class Rules():
108
+ def __init__(self, obj, allow: bool):
109
+ self.description = obj.get("description", "")
110
+ self.subsystem_deps: list[Rule] = []
111
+ self.interface_deps: list[Rule] = []
112
+ self.build_rules: list[Rule] = []
113
+ self.allow = allow
114
+
115
+ for rule in obj.get("SubsystemDeps", []):
116
+ self.subsystem_deps.append(Rule(DepRuleType.SUBSYSTEM_DEP, rule))
117
+
118
+ for sub in obj.get("IntfDeps", []):
119
+ for rules in sub.values():
120
+ for rule in rules:
121
+ self.interface_deps.append(Rule(DepRuleType.INTERFACE_DEP, rule))
122
+
123
+ for rule in obj.get("BuildDeps", []):
124
+ self.build_rules.append(Rule(DepRuleType.BUILD_DEP, rule))
125
+
126
+ # Check if the interface dependency between two packages is allowed based on the rules
127
+ def intf_dep_check(self, src: DepNode, tgt: DepNode, intf: str):
128
+ # Whitelist rules
129
+ if self.allow:
130
+ return self._intf_dep_check_whitelist(src, tgt, intf)
131
+
132
+ # Blacklist rules
133
+ return self._intf_dep_check_blacklist(src, tgt, intf)
134
+
135
+ def build_dep_check(self, src: DepNode, tgt: DepNode):
136
+ # Whitelist rules
137
+ if self.allow:
138
+ return self._build_dep_check_whitelist(src, tgt)
139
+
140
+ # Blacklist rules
141
+ return self._build_dep_check_blacklist(src, tgt)
142
+
143
+ def _intf_dep_check_whitelist(self, src: DepNode, tgt: DepNode, intf: str):
144
+ if src.package_name in ['event', 'sensor']:
145
+ return True
146
+ # Check the subsystem rules first and then interface rules
147
+ subsys_allowed = False
148
+ for rule in self.subsystem_deps:
149
+ if rule.subsystem_dep_check(src, tgt, intf):
150
+ subsys_allowed = True
151
+ break
152
+
153
+ if src.subsys_name != tgt.subsys_name or not subsys_allowed:
154
+ return subsys_allowed
155
+
156
+ intf_allowed = False
157
+ for rule in self.interface_deps:
158
+ if rule.intf_dep_check(src, tgt, intf):
159
+ intf_allowed = True
160
+ break
161
+ return intf_allowed
162
+
163
+ def _intf_dep_check_blacklist(self, src: DepNode, tgt: DepNode, intf: str):
164
+ subsys_unallowed = False
165
+ for rule in self.subsystem_deps:
166
+ if rule.subsystem_dep_check(src, tgt, intf):
167
+ subsys_unallowed = True
168
+ break
169
+ if src.subsys_name != tgt.subsys_name or subsys_unallowed:
170
+ return not subsys_unallowed
171
+
172
+ intf_unallowed = False
173
+ for rule in self.interface_deps:
174
+ if rule.intf_dep_check(src, tgt, intf):
175
+ intf_unallowed = True
176
+ break
177
+ return not intf_unallowed
178
+
179
+ def _build_dep_check_whitelist(self, src: DepNode, tgt: DepNode):
180
+ for rule in self.build_rules:
181
+ # 跳过不适用的规则
182
+ if not rule.match_rule(src, tgt):
183
+ continue
184
+ result = rule.build_dep_check(src, tgt)
185
+ # 白名单有一个匹配就满足
186
+ if result:
187
+ return True
188
+ # 白名单都不匹配时不满足
189
+ return False
190
+
191
+ def _match_rule(self, src: DepNode, tgt: DepNode, from_key: str, to_key: str):
192
+ for rule in self.build_rules:
193
+ if not rule.match_rule(from_key, to_key):
194
+ continue
195
+ if rule.build_dep_check(src, tgt):
196
+ return True
197
+
198
+ return False
199
+
200
+ def _build_dep_check_blacklist(self, src: DepNode, tgt: DepNode):
201
+ # 未配置黑名单时默认满足
202
+ if not bool(self.build_rules):
203
+ return True
204
+
205
+ # 源组件和目标组件只要有一组类型不在黑名单内就满足
206
+ for from_key in src.package_type:
207
+ for to_key in tgt.package_type:
208
+ if not self._match_rule(src, tgt, from_key, to_key):
209
+ return True
210
+
211
+ return False
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "UID": "00000001020302031825",
4
+ "Scanners": [
5
+ {
6
+ "SmcAddress": 96,
7
+ "ScannerOffset": 1006636292
8
+ }
9
+ ]
10
+ }
11
+ ]
@@ -0,0 +1,391 @@
1
+ #!/usr/bin/python3
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 stat
16
+ import re
17
+ from collections import defaultdict
18
+ from pathlib import Path
19
+ from typing import Dict, List
20
+ from colorama import Fore, Style
21
+ from bmcgo.logger import Logger
22
+
23
+ global log
24
+ log = Logger()
25
+
26
+ SOFT_SR_SUFFIX = "_soft.sr"
27
+ SOFTWARE_SUFFIX = "software"
28
+ CHIP_KEY = "Chip"
29
+ LEVEL_ERROR = "error"
30
+ LEVEL_WARNING = "warning"
31
+
32
+
33
+ class DirectedGraph:
34
+ VISITING = 1
35
+ VISITED = 2
36
+
37
+ def __init__(self):
38
+ self.edges = defaultdict(set)
39
+ self.flags = dict()
40
+
41
+ def add_edge(self, node_from: str, node_to: str):
42
+ self.edges[node_from].add(node_to)
43
+
44
+ def has_edge(self, node_from: str, node_to: str):
45
+ return node_to in self.edges[node_from]
46
+
47
+ def remove_edge(self, node_from: str, node_to: str):
48
+ self.edges[node_from].discard(node_to)
49
+
50
+ def check_loop(self):
51
+ for node in self.edges:
52
+ if node in self.flags:
53
+ continue
54
+ route = [node]
55
+ if self.depth_first_search(node, route):
56
+ return route
57
+ return []
58
+
59
+ def depth_first_search(self, node: str, route: List[str]):
60
+ if node not in self.edges:
61
+ self.flags[node] = self.VISITED
62
+ return False
63
+ self.flags[node] = self.VISITING
64
+ for child in self.edges[node]:
65
+ route.append(child)
66
+ if child not in self.flags:
67
+ if self.depth_first_search(child, route):
68
+ return True
69
+ elif self.flags[child] == self.VISITING:
70
+ return True
71
+ route.pop()
72
+ self.flags[node] = self.VISITED
73
+ return False
74
+
75
+
76
+ class SrParser:
77
+ def __init__(self, sr_dir: str):
78
+ self.issues_report = defaultdict(set)
79
+ self.sr_dir = sr_dir
80
+
81
+ @staticmethod
82
+ def get_obj_name(prop_val: str):
83
+ obj_prop = prop_val.split('/', 1)[1]
84
+ obj_name = obj_prop.split('.', 1)[0]
85
+ if SrParser.is_sync(prop_val) and obj_name.startswith('::'):
86
+ return obj_name[2:]
87
+ return obj_name
88
+
89
+ @staticmethod
90
+ def get_class_name(obj_name: str):
91
+ return obj_name.split('_', 1)[0]
92
+
93
+ @staticmethod
94
+ def is_ref(prop_val: str):
95
+ return prop_val.startswith("#/")
96
+
97
+ @staticmethod
98
+ def is_sync(prop_val: str):
99
+ return prop_val.startswith("<=/")
100
+
101
+ @staticmethod
102
+ def get_prop_name(prop_val: str):
103
+ if '.' not in prop_val:
104
+ return ""
105
+ ret = prop_val.split('.', 2)[1]
106
+ if "|>" in ret:
107
+ ret = ret.split("|>", 1)[0].strip()
108
+ return ret
109
+
110
+ @staticmethod
111
+ def get_logger(level: str):
112
+ if level == 'error':
113
+ return log.error
114
+ if level == 'warning':
115
+ return log.warning
116
+ return log.info
117
+
118
+ @staticmethod
119
+ def get_log_color(level: str):
120
+ if level == 'error':
121
+ return Fore.RED
122
+ if level == 'warning':
123
+ return Fore.YELLOW
124
+ return Fore.WHITE
125
+
126
+ @staticmethod
127
+ def log_issue(sr_path: str, level: str, msg: str):
128
+ logger = SrParser.get_logger(level)
129
+ if 'CLOUD_BUILD_RECORD_ID' in os.environ:
130
+ logger("%s: %s: %s", sr_path, level, msg)
131
+ else:
132
+ color = SrParser.get_log_color(level)
133
+ logger("%s: %s: %s%s%s", sr_path, level, color, msg, Style.RESET_ALL)
134
+
135
+ def log_issues(self, issues_log_path=None):
136
+ file_count = 0
137
+ problems_total = 0
138
+ issues_count = defaultdict(int)
139
+ issues_content = ''
140
+ for sr_path, issues in self.issues_report.items():
141
+ if not issues:
142
+ continue
143
+ file_count += 1
144
+ for level, msg in issues:
145
+ problems_total += (level == LEVEL_ERROR or level == LEVEL_WARNING)
146
+ issues_count[level] += 1
147
+ issues_content += f'{sr_path}: {level}: {msg}\n'
148
+ if issues_log_path is None or level == LEVEL_ERROR:
149
+ self.log_issue(sr_path, level, msg)
150
+ if issues_log_path is not None:
151
+ msg = f"Finished data dependency analysis: found {problems_total} issues in {file_count} files"
152
+ if issues_count[LEVEL_ERROR]:
153
+ msg += f', errors: {issues_count[LEVEL_ERROR]}'
154
+ if issues_count[LEVEL_WARNING]:
155
+ msg += f', warnings: {issues_count[LEVEL_WARNING]}'
156
+ issues_content += msg
157
+ with os.fdopen(os.open(issues_log_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
158
+ stat.S_IWUSR | stat.S_IRUSR), 'w') as fp:
159
+ fp.write(issues_content)
160
+ return file_count, problems_total, issues_count
161
+
162
+ def walk_sr_dir(self):
163
+ for root, _, files in os.walk(self.sr_dir):
164
+ for file in files:
165
+ if not file.endswith(".sr"):
166
+ continue
167
+ self.load_sr(os.path.join(root, file))
168
+
169
+ def load_sr(self, sr_path: str):
170
+ relpath = os.path.relpath(sr_path, self.sr_dir)
171
+ with open(sr_path, 'r') as file_descriptor:
172
+ try:
173
+ sr_content = json.load(file_descriptor)
174
+ except json.decoder.JSONDecodeError as error:
175
+ self.issues_report[relpath].add(("error", f"格式错误: {error.msg}"))
176
+ except Exception as error:
177
+ self.issues_report[relpath].add(("error", f"解析失败: {error}"))
178
+ else:
179
+ self.parse_sr(relpath, sr_content)
180
+
181
+ def parse_sr(self, relpath: str, sr_content: Dict):
182
+ # 由子类实现
183
+ pass
184
+
185
+
186
+ class SrValidate(SrParser):
187
+ def __init__(self, sr_dir: str):
188
+ super().__init__(sr_dir)
189
+ self.sr_objs: Dict[str, Dict[str, Dict]] = dict()
190
+ self.objects_used = defaultdict(set)
191
+ self.soft_sr_objects = defaultdict(dict)
192
+ self.soft_sr_files = dict()
193
+ self.is_sr_repo = False
194
+ self.is_product_sr_repo = False
195
+ self.check_repo_type()
196
+ self.smc_dfx_whitelist: Dict[str, List[Dict[str, int]]] = defaultdict(list)
197
+ self.load_smc_dfx_whitelist()
198
+
199
+ @staticmethod
200
+ def merge_sr_objects(hardware_sr_objects: Dict[str, Dict], software_sr_objects: Dict[str, Dict]):
201
+ for obj_name, obj_data in software_sr_objects.items():
202
+ if obj_name not in hardware_sr_objects:
203
+ hardware_sr_objects[obj_name] = obj_data
204
+ continue
205
+ for prop_name, prop_data in obj_data.items():
206
+ if prop_name in hardware_sr_objects[obj_name]:
207
+ continue
208
+ hardware_sr_objects[obj_name][prop_name] = prop_data
209
+
210
+ @staticmethod
211
+ def get_uid(sr_objects: Dict[str, Dict]):
212
+ tianchi_uid = ""
213
+ for obj_name, obj_data in sr_objects.items():
214
+ class_name = SrParser.get_class_name(obj_name)
215
+ uid = obj_data.get("UID")
216
+ if class_name == 'SRUpgrade' and uid:
217
+ # 优先返回SRUpgrade对象下配置的UID
218
+ return uid
219
+ tianchi_data = obj_data.get("bmc.dev.Board.TianChi")
220
+ if isinstance(tianchi_data, dict) and not tianchi_uid:
221
+ inner_uid = tianchi_data.get("UID")
222
+ if inner_uid:
223
+ tianchi_uid = inner_uid
224
+ elif uid:
225
+ tianchi_uid = uid
226
+ # 找不到SRUpgrade对象下配置的UID后,再返回按设备树方案查找的UID
227
+ return tianchi_uid
228
+
229
+ @staticmethod
230
+ def get_chip_ref(obj_data: Dict):
231
+ value = obj_data.get(CHIP_KEY)
232
+ if not isinstance(value, str) or not SrParser.is_ref(value):
233
+ return ""
234
+ return value[2:]
235
+
236
+ def check_repo_type(self):
237
+ service_path = os.path.join(self.sr_dir, 'mds/service.json')
238
+ try:
239
+ with open(service_path, 'r') as file_descriptor:
240
+ content = json.load(file_descriptor)
241
+ project_name = content.get('name')
242
+ if project_name in ['vpd', 'TaiShanServer2.9.0_CSR', 'TS900-K2_5.0.0_CSR']:
243
+ self.is_sr_repo = True
244
+ self.is_product_sr_repo = (project_name != 'vpd')
245
+ except Exception as e:
246
+ log.error('mds/service.json 文件解析失败: %s', e)
247
+
248
+ def load_smc_dfx_whitelist(self):
249
+ whitelist_file = Path(__file__).parent.joinpath("smc_dfx_whitelist.json")
250
+ if not os.path.exists(whitelist_file):
251
+ return
252
+ try:
253
+ with open(whitelist_file, 'r') as file_descriptor:
254
+ content = json.load(file_descriptor)
255
+ for item in content:
256
+ self.smc_dfx_whitelist[item.get("UID")] = item.get("Scanners")
257
+ except Exception as e:
258
+ log.error('smc_dfx_whitelist.json 文件解析失败: %s', e)
259
+
260
+ def run(self):
261
+ if not self.is_sr_repo:
262
+ return True
263
+ self.find_soft_sr_files()
264
+ self.walk_sr_dir()
265
+ file_count, problems_total, issues_count = self.log_issues()
266
+ msg = f"Finished SR analysis: found {problems_total} issues in {file_count} files"
267
+ if issues_count["error"]:
268
+ msg += f', errors: {issues_count["error"]}'
269
+ if issues_count["warning"]:
270
+ msg += f', warnings: {issues_count["warning"]}'
271
+ log.info(msg)
272
+ if problems_total == 0:
273
+ log.info("sr 校验通过")
274
+ else:
275
+ log.error("sr 校验失败")
276
+ return problems_total == 0
277
+
278
+ def find_soft_sr_files(self):
279
+ for root, _, files in os.walk(self.sr_dir):
280
+ for file in files:
281
+ if not file.endswith(SOFT_SR_SUFFIX):
282
+ continue
283
+ hard_sr_name = f"{file[:-len(SOFT_SR_SUFFIX)]}.sr"
284
+ soft_sr_path = os.path.join(root, file)
285
+ hard_sr_path = os.path.join(root, hard_sr_name)
286
+ if not os.path.exists(hard_sr_path) and root.endswith(SOFTWARE_SUFFIX):
287
+ hard_sr_path = os.path.join(root[:-len(SOFTWARE_SUFFIX)], "src", hard_sr_name)
288
+ self.soft_sr_files[hard_sr_path] = soft_sr_path
289
+
290
+
291
+ def get_soft_sr_objects(self, relpath):
292
+ sr_path = os.path.join(self.sr_dir, relpath)
293
+ if sr_path not in self.soft_sr_files:
294
+ return {}
295
+
296
+ soft_sr_path = self.soft_sr_files[sr_path]
297
+ if not os.path.exists(soft_sr_path):
298
+ return {}
299
+ try:
300
+ with open(soft_sr_path, 'r') as file_descriptor:
301
+ content = json.load(file_descriptor)
302
+ return content.get("Objects", {})
303
+ except Exception as e:
304
+ log.error('sr 文件 %s 解析失败: %s', soft_sr_path, e)
305
+ return {}
306
+
307
+ def parse_sr(self, relpath: str, sr_content: Dict):
308
+ if relpath.endswith(SOFT_SR_SUFFIX):
309
+ return
310
+ objs = sr_content.get("Objects", {})
311
+ self.merge_sr_objects(objs, self.get_soft_sr_objects(relpath))
312
+ self.sr_objs[relpath] = objs
313
+ self.check_smc_dfx_info(relpath)
314
+ if self.is_product_sr_repo:
315
+ return
316
+
317
+ for obj_name, obj_data in objs.items():
318
+ for key, value in obj_data.items():
319
+ if isinstance(value, str):
320
+ self.parse_prop_val(obj_name, key, value, relpath)
321
+
322
+ if "ManagementTopology" in sr_content:
323
+ self.check_topology(sr_content["ManagementTopology"], relpath)
324
+
325
+ def parse_prop_val(self, obj_name: str, prop_key: str, prop_val: str, relpath: str):
326
+ for global_sign, target_obj in re.findall(re.compile("(?:<=|#)\/(:*)(\w+)"), prop_val):
327
+ self.objects_used[relpath].add(target_obj)
328
+ if not global_sign and target_obj not in self.sr_objs[relpath]:
329
+ self.issues_report[relpath].add(("error",
330
+ f"'{obj_name}.{prop_key}'同步或引用的对象'{target_obj}'没有在Objects中定义"))
331
+ if not self.is_ref(prop_val) and not self.is_sync(prop_val):
332
+ return
333
+
334
+ for val in prop_val.split(';'):
335
+ val = val.strip()
336
+ if not (val.startswith('#/') or val.startswith("<=/")):
337
+ self.issues_report[relpath].add(("error", f"对象'{obj_name}'的属性'{prop_key}'值不规范:{val}"))
338
+
339
+ def check_topology(self, management_topology: dict, relpath: str):
340
+ chips = set()
341
+ for node_data in management_topology.values():
342
+ for key, objects in node_data.items():
343
+ for obj in objects:
344
+ self.objects_used[relpath].add(obj)
345
+ self.validate_topology_object(key, obj, chips, relpath)
346
+
347
+ def validate_topology_object(self, key: str, obj: str, chips: set, relpath: str):
348
+ if key not in ["Connectors", "Chips"]:
349
+ return
350
+ if obj not in self.sr_objs[relpath]:
351
+ self.issues_report[relpath].add(("error", f"器件'{obj}'没有在Objects中列出"))
352
+ if key == "Chips":
353
+ if obj in chips:
354
+ self.issues_report[relpath].add(("error", f"器件'{obj}'有多条上行总线"))
355
+ chips.add(obj)
356
+
357
+ def match_smc_dfx_whitelist(self, file_objs: Dict[str, Dict], uid: str, chip: str, scanner_data: Dict):
358
+ if chip not in file_objs or uid not in self.smc_dfx_whitelist:
359
+ return False
360
+ chip_data = file_objs.get(chip)
361
+ smc_address = chip_data.get("Address")
362
+ scanner_offset = scanner_data.get("Offset")
363
+ if not smc_address or not scanner_offset:
364
+ return False
365
+ for item in self.smc_dfx_whitelist.get(uid):
366
+ if item.get("SmcAddress") == smc_address and item.get("ScannerOffset") == scanner_offset:
367
+ return True
368
+ return False
369
+
370
+ def check_smc_dfx_info(self, relpath: str):
371
+ smc_dfx_info_objs = {}
372
+ for obj_name, obj_data in self.sr_objs[relpath].items():
373
+ chip = self.get_chip_ref(obj_data)
374
+ if chip and self.get_class_name(obj_name) == "SmcDfxInfo":
375
+ smc_dfx_info_objs[chip] = (obj_name, obj_data)
376
+ if not smc_dfx_info_objs:
377
+ return
378
+
379
+ uid = self.get_uid(self.sr_objs[relpath])
380
+ for obj_name, obj_data in self.sr_objs[relpath].items():
381
+ chip = self.get_chip_ref(obj_data)
382
+ condition = self.get_class_name(obj_name) == "Scanner" and obj_name != "Scanner_PowerGood" \
383
+ and chip and chip in smc_dfx_info_objs
384
+ condition = condition and not self.match_smc_dfx_whitelist(self.sr_objs[relpath], uid, chip, obj_data)
385
+ if not condition:
386
+ continue
387
+ smc_dfx_info_obj_name, smc_dfx_info_obj_data = smc_dfx_info_objs.get(chip)
388
+ if obj_name not in smc_dfx_info_obj_data.get("Mapping", {}):
389
+ error_msg = f"对象'{obj_name}'没有在对象'{smc_dfx_info_obj_name}'的Mapping中配置"\
390
+ "(特殊配套原因不能配置的场景,输出子系统DE讨论纪要后增加到白名单bmcgo/component/analysis/smc_dfx_whitelist.json)"
391
+ self.issues_report[relpath].add(("error", error_msg))