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,333 @@
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 stat
16
+ from collections import defaultdict
17
+ from typing import Dict, List, Set
18
+ from pyecharts import options as opts
19
+ from pyecharts.charts import Graph
20
+ from pyecharts.options import GraphLink, GraphNode, LineStyleOpts
21
+
22
+ from bmcgo.component.analysis.dep_node import DepNode
23
+ from bmcgo.component.analysis.rule import Rules
24
+ from bmcgo.component.analysis.sr_validation import SrParser, DirectedGraph
25
+ from bmcgo.logger import Logger
26
+ from bmcgo import misc
27
+
28
+ global log
29
+ log = Logger()
30
+ CONAN_DATA = ".conan/data"
31
+ DATA_DEPENDENCIES = "dataDependencies"
32
+
33
+
34
+ class ClassPropMap:
35
+ def __init__(self, nodes: List[DepNode], mdb_interface_dir: str) -> None:
36
+ self.class_map: Dict[str, DepUnit] = dict()
37
+ self.prop_map: Dict[tuple[str, str], DepUnit] = dict()
38
+ self.intf_props: Dict[str, set[str]] = defaultdict(set)
39
+ self.class_intf_props: Dict[str, set[str]] = defaultdict(set)
40
+ self.map_mdb_interface(mdb_interface_dir)
41
+ for node in nodes:
42
+ if not os.path.exists(node.model_path):
43
+ continue
44
+ with open(node.model_path, "r") as file_descriptor:
45
+ model_dict = json.load(file_descriptor)
46
+ for class_name, class_data in model_dict.items():
47
+ self.add_from_model(node.package_name, class_name, class_data)
48
+
49
+ def add_class(self, app_name: str, class_name: str, usage_csr: bool):
50
+ if class_name in self.class_map and self.class_map[class_name].usage_csr:
51
+ return
52
+ self.class_map[class_name] = DepUnit(app_name, class_name, usage_csr=usage_csr)
53
+
54
+ def map_mdb_interface(self, mdb_interface_dir):
55
+ if not mdb_interface_dir:
56
+ return
57
+
58
+ for root, _, files in os.walk(mdb_interface_dir):
59
+ for file in files:
60
+ if not file.endswith(".json"):
61
+ continue
62
+ intf_json = os.path.join(root, file)
63
+ with open(intf_json, 'r') as fp:
64
+ content = json.load(fp)
65
+ for intf, intf_data in content.items():
66
+ self.intf_props[intf] = set(intf_data.get('properties', {}).keys())
67
+
68
+ def add_from_model(self, app_name: str, class_name: str, class_data: Dict):
69
+ has_usage_csr = False
70
+ for intf, intf_data in class_data.get("interfaces", {}).items():
71
+ self.class_intf_props[class_name].update(self.intf_props[intf])
72
+ has_usage_csr |= self.parse_prop_data(app_name, class_name,
73
+ intf_data.get("properties", {}), intf=intf)
74
+
75
+ has_usage_csr |= self.parse_prop_data(app_name, class_name,
76
+ class_data.get("properties", {}))
77
+ self.add_class(app_name, class_name, has_usage_csr)
78
+
79
+ def check_class_exists(self, class_name: str):
80
+ return class_name in self.class_map
81
+
82
+ def check_prop_exists(self, class_name: str, prop: str):
83
+ if not prop:
84
+ return True
85
+ return (class_name, prop) in self.prop_map and prop in self.class_intf_props[class_name]
86
+
87
+ def get_app(self, class_name: str):
88
+ if class_name in self.class_map:
89
+ return self.class_map[class_name].app
90
+ return 'hwproxy'
91
+
92
+ def get_intf(self, class_name: str, prop: str):
93
+ if not prop or (class_name, prop) not in self.prop_map:
94
+ return ""
95
+ return self.prop_map.get((class_name, prop)).intf
96
+
97
+ def get_ref_intf(self, class_name: str, prop: str):
98
+ if not prop or (class_name, prop) not in self.prop_map:
99
+ return ""
100
+ return self.prop_map.get((class_name, prop)).ref_intf
101
+
102
+ def parse_prop_data(self, app_name: str, class_name: str, properties_dict: Dict, intf: str = ""):
103
+ no_csr = True
104
+ for prop, prop_data in properties_dict.items():
105
+ usage_csr = "CSR" in prop_data.get("usage", [])
106
+ ref_intf = prop_data.get("refInterface", "")
107
+ self.prop_map[(class_name, prop)] = DepUnit(app_name, class_name,
108
+ usage_csr=usage_csr, prop=prop, intf=intf, ref_intf=ref_intf)
109
+ no_csr = no_csr and not usage_csr
110
+ return not no_csr
111
+
112
+
113
+ class DepUnit:
114
+ def __init__(self, app_name: str, class_name: str, **kwargs) -> None:
115
+ self.app = app_name
116
+ self.class_name = class_name
117
+ self.usage_csr = kwargs.get("usage_csr", False)
118
+ self.prop = kwargs.get("prop", "")
119
+ self.obj_name = kwargs.get("obj_name", "")
120
+ self.ref_intf = kwargs.get("ref_intf", "")
121
+ self.intf = kwargs.get("intf", None)
122
+ self.obj_prop = f"{self.obj_name}.{self.prop}" if self.prop else self.obj_name
123
+
124
+
125
+ class DataDependenciesAnalysis(SrParser):
126
+ def __init__(self, nodes: List[DepNode], rules: List[Rules], custom_sr_dir: str):
127
+ mdb_interface_dir = ""
128
+ for node in nodes:
129
+ if node.package_name == 'vpd':
130
+ pkg_dir = node.ref.split("#")[0].replace("@", "/")
131
+ sr_dir = os.path.join(os.environ["HOME"], CONAN_DATA, pkg_dir, "source")
132
+ if node.package_name == 'mdb_interface':
133
+ pkg_dir = node.ref.split("#")[0].replace("@", "/")
134
+ mdb_interface_dir = os.path.join(os.environ["HOME"], CONAN_DATA, pkg_dir,
135
+ "package", node.package_id, "opt/bmc/apps/mdb_interface/intf/mdb/bmc")
136
+ if custom_sr_dir:
137
+ sr_dir = custom_sr_dir
138
+ super().__init__(sr_dir)
139
+ self._nodes = nodes
140
+ self._rules = rules
141
+ self.cp_map = ClassPropMap(nodes, mdb_interface_dir)
142
+ self.dependencies: Dict[tuple[str, str], tuple[bool, str]] = dict()
143
+ self.correct_sr_deps_graph: Dict[str, Dict[str, List[Dict[str, str]]]] = defaultdict(dict)
144
+ self.wrong_sr_deps_graph: Dict[str, Dict[str, List[Dict[str, str]]]] = defaultdict(dict)
145
+ self.app_deps: Dict[str, Dict[tuple[str, str], tuple[str, str]]] = defaultdict(dict)
146
+ self.links: List[GraphLink] = []
147
+ self.involved_apps: set[str] = set()
148
+ self.nodes_by_app: Dict[str, DepNode] = dict()
149
+ for node in self._nodes:
150
+ self.nodes_by_app[node.package_name] = node
151
+
152
+ @staticmethod
153
+ def get_loop_error_msg(loop: List[str], dep_data: Dict):
154
+ route = []
155
+ for i in range(len(loop) - 1):
156
+ obj_prop_from, obj_prop_to = dep_data[(loop[i], loop[i + 1])]
157
+ route.append(f"{obj_prop_from}({loop[i]}) -> {obj_prop_to}({loop[i + 1]})")
158
+ return ", ".join(route)
159
+
160
+ @staticmethod
161
+ def is_in_whitelist(dep_unit: DepUnit):
162
+ return dep_unit.app == 'event' or dep_unit.class_name == 'Event'
163
+
164
+ def run(self, html_output_path: str, json_output_path: str, issues_log_path: str):
165
+ self.walk_sr_dir()
166
+ for sr_path, dep_data in self.app_deps.items():
167
+ graph = DirectedGraph()
168
+ for app_pair in dep_data:
169
+ graph.add_edge(*app_pair)
170
+ loop = graph.check_loop()
171
+ if loop:
172
+ self.issues_report[sr_path].add(("error",
173
+ f"引用关系构成了组件间环形依赖: {self.get_loop_error_msg(loop, dep_data)}"))
174
+ _, _, issues_count = self.log_issues(issues_log_path)
175
+ self.set_links()
176
+ self.visualize_graph(html_output_path)
177
+ self.assemble_deps_json_desc(json_output_path)
178
+ return issues_count["error"] == 0 and not bool(self.wrong_sr_deps_graph)
179
+
180
+ def parse_sr(self, relpath: str, sr_content: Dict):
181
+ for obj_name, obj_data in sr_content.get("Objects", {}).items():
182
+ class_name = self.get_class_name(obj_name)
183
+ if not self.cp_map.check_class_exists(class_name):
184
+ continue
185
+ app_name = self.cp_map.get_app(class_name)
186
+
187
+ for key, value in obj_data.items():
188
+ intf = self.cp_map.get_intf(class_name, key)
189
+ dep_from = DepUnit(app_name, class_name, prop=key, obj_name=obj_name, intf=intf)
190
+ if isinstance(value, str) and (self.is_ref(value) or self.is_sync(value)):
191
+ self.parse_prop_val(dep_from, value, relpath)
192
+
193
+ def parse_prop_val(self, dep_from: DepUnit, prop_val: str, relpath: str):
194
+ for val in prop_val.split(';'):
195
+ val = val.strip()
196
+ if not (self.is_ref(val) or self.is_sync(val)):
197
+ continue
198
+ target_obj = self.get_obj_name(val)
199
+ target_class = self.get_class_name(target_obj)
200
+ target_prop = self.get_prop_name(val)
201
+ target_class_exists = self.cp_map.check_class_exists(target_class)
202
+ target_prop_exists = self.cp_map.check_prop_exists(target_class, target_prop)
203
+ if not target_class_exists or not target_prop_exists or self.is_sync(val):
204
+ continue
205
+
206
+ target_app = self.cp_map.get_app(target_class)
207
+ intf = self.cp_map.get_intf(target_class, target_prop)
208
+ dep_to = DepUnit(target_app, target_class, prop=target_prop, intf=intf, obj_name=target_obj)
209
+ self.add_dep(dep_from, dep_to, relpath)
210
+
211
+ def add_dep(self, dep_from: DepUnit, dep_to: DepUnit, relpath: str):
212
+ self.involved_apps.add(dep_from.app)
213
+ self.involved_apps.add(dep_to.app)
214
+ dependency_allowed = True
215
+
216
+ if dep_from.app != dep_to.app:
217
+ self.app_deps[relpath][(dep_from.app, dep_to.app)] = (dep_from.obj_prop, dep_to.obj_prop)
218
+ dependency_allowed = self.check_sr_dependency(dep_from, dep_to, relpath)
219
+
220
+ if dependency_allowed and dep_to.intf and dep_to.intf != dep_from.ref_intf:
221
+ level = "notice" if self.is_in_whitelist(dep_from) else "warning"
222
+ self.issues_report[relpath].add((level, f"'{dep_from.obj_prop}'对'{dep_to.obj_prop}'的引用\
223
+ 没有在组件'{dep_from.app}'的MDS中用refInterface声明对接口'{dep_to.intf}'的依赖"))
224
+
225
+ def set_links(self):
226
+ for (app_from, app_to), (allowed, violation) in self.dependencies.items():
227
+ if allowed:
228
+ link_opts = GraphLink(source=app_from, target=app_to,
229
+ linestyle_opts=LineStyleOpts(color="GREEN", curve=0.2))
230
+ else:
231
+ link_opts = GraphLink(source=app_from, target=app_to,
232
+ linestyle_opts=LineStyleOpts(color=misc.COLOR_RED, curve=0.2), value=violation)
233
+ self.links.append(link_opts)
234
+
235
+ def check_sr_dependency(self, dep_from: DepUnit, dep_to: DepUnit, relpath: str):
236
+ if dep_from.app == dep_to.app or dep_from.app not in self.nodes_by_app \
237
+ or dep_to.app not in self.nodes_by_app:
238
+ return True
239
+ node_from = self.nodes_by_app.get(dep_from.app)
240
+ node_to = self.nodes_by_app.get(dep_to.app)
241
+ allowed = False
242
+ for rules in self._rules:
243
+ if rules.intf_dep_check(node_from, node_to, dep_to.intf):
244
+ allowed = True
245
+ break
246
+ dep_detail = {
247
+ "sr_path": relpath,
248
+ "source": dep_from.obj_prop,
249
+ "target": dep_to.obj_prop
250
+ }
251
+ if allowed:
252
+ self.dependencies[(dep_from.app, dep_to.app)] = self.dependencies.get((dep_from.app, dep_to.app),
253
+ (True, ""))
254
+ self.correct_sr_deps_graph[dep_from.app][dep_to.app] = \
255
+ self.correct_sr_deps_graph[dep_from.app].get(dep_to.app, list())
256
+ self.correct_sr_deps_graph[dep_from.app][dep_to.app].append(dep_detail)
257
+ return True
258
+
259
+ whitelisted = self.is_in_whitelist(dep_from)
260
+ level = "notice" if whitelisted else "error"
261
+ same_sub = node_from.subsys_name == node_to.subsys_name
262
+ violation = "违反子系统内依赖约束" if same_sub else "违反子系统间依赖约束"
263
+ detail = f"'{dep_from.obj_prop}'对'{dep_to.obj_prop}'的引用属于组件'{dep_from.app}'对组件'{dep_to.app}'的依赖"
264
+ self.issues_report[relpath].add((level, f"数据依赖违反依赖约束: {detail}"))
265
+ if whitelisted:
266
+ return True
267
+ self.dependencies[(dep_from.app, dep_to.app)] = (False, violation)
268
+ self.wrong_sr_deps_graph[dep_from.app][dep_to.app] = \
269
+ self.wrong_sr_deps_graph[dep_from.app].get(dep_to.app, list())
270
+ self.wrong_sr_deps_graph[dep_from.app][dep_to.app].append(dep_detail)
271
+ return False
272
+
273
+ def visualize_graph(self, output_path: str):
274
+ subsystems = set()
275
+ for pkg in self._nodes:
276
+ subsystems.add(pkg.subsys_name)
277
+ categories = []
278
+ for subsys in subsystems:
279
+ categories.append({misc.NAME: subsys, "symbolSize": 100})
280
+ categories.append({misc.NAME: "unknown", "symbolSize": 100})
281
+ category_id_map: Dict[str, int] = dict()
282
+ for index, category in enumerate(categories):
283
+ category_id_map[category[misc.NAME]] = index
284
+
285
+ graph_nodes: List[GraphNode] = []
286
+ for pkg in self._nodes:
287
+ if pkg.package_name in self.involved_apps:
288
+ graph_nodes.append(GraphNode(name=pkg.package_name, symbol_size=10, \
289
+ category=category_id_map.get(pkg.subsys_name, len(categories))))
290
+
291
+ log.info("保存 BMC 依赖信息图到 %s", output_path)
292
+ output_graph = Graph(init_opts=opts.InitOpts(width="100%", height="1200px",
293
+ page_title="BMC-Data-Dependency-Graph"))
294
+ output_graph.add("", graph_nodes, self.links, categories,
295
+ repulsion=100,
296
+ is_rotate_label=True,
297
+ edge_symbol=["", "arrow"],
298
+ label_opts=opts.LabelOpts(position="right", formatter="{b}"))
299
+ output_graph.set_global_opts(
300
+ title_opts=opts.TitleOpts(title="Graph-BMC-Data-Dependency-Graph"),
301
+ legend_opts=opts.LegendOpts(orient="vertical", pos_left="2%", pos_top="20%"))
302
+ output_graph.options.get("series")[0]["zoom"] = 4
303
+ output_graph.render(output_path)
304
+
305
+ def assemble_deps_json_desc(self, output_path: str):
306
+ node_name_map = dict()
307
+
308
+ for node in self._nodes:
309
+ node_name_map[node.package_name] = {
310
+ misc.NAME: node.package_name,
311
+ "version": node.package_version,
312
+ "subsystem": node.subsys_name,
313
+ "type": node.package_type
314
+ }
315
+
316
+ json_dict = {"DataDependencyGraph": [], "IllegalDataDependencyGraph": []}
317
+ for (app_from, dep_data) in self.correct_sr_deps_graph.items():
318
+ entry = {"sourceComponent": node_name_map.get(app_from), DATA_DEPENDENCIES: []}
319
+ for app_to, detail in dep_data.items():
320
+ entry[DATA_DEPENDENCIES].append({"targetComponent": node_name_map.get(app_to), "detail": detail})
321
+ json_dict["DataDependencyGraph"].append(entry)
322
+
323
+ for (app_from, dep_data) in self.wrong_sr_deps_graph.items():
324
+ entry = {"sourceComponent": node_name_map.get(app_from), DATA_DEPENDENCIES: []}
325
+ for app_to, detail in dep_data.items():
326
+ entry[DATA_DEPENDENCIES].append({"targetComponent": node_name_map.get(app_to), "detail": detail})
327
+ json_dict["IllegalDataDependencyGraph"].append(entry)
328
+
329
+ log.info("保存 BMC 依赖信息到 %s", output_path)
330
+ flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
331
+ modes = stat.S_IWUSR | stat.S_IRUSR
332
+ with os.fdopen(os.open(output_path, flags, modes), 'w') as file_descriptor:
333
+ file_descriptor.write(json.dumps(json_dict, indent=4))