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,46 @@
1
+ #!/usr/bin/env python3
2
+ # encoding=utf-8
3
+ # 描述:pip安装工具
4
+ # Copyright (c) 2025 Huawei Technologies Co., Ltd.
5
+ # openUBMC is licensed under Mulan PSL v2.
6
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
7
+ # You may obtain a copy of Mulan PSL v2 at:
8
+ # http://license.coscl.org.cn/MulanPSL2
9
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12
+ # See the Mulan PSL v2 for more details.
13
+ import sys
14
+ import shutil
15
+ from typing import Dict, List
16
+ from bmcgo.utils.tools import Tools
17
+ from bmcgo.utils.installations import install_consts
18
+ from bmcgo.utils.installations.base_installer import BaseInstaller
19
+
20
+
21
+ tool = Tools("pip_install")
22
+
23
+
24
+ class PipInstaller(BaseInstaller, installer_type="pip"):
25
+ def install(self, plan: Dict[str, List[str]], operator: str, version: str):
26
+ if operator == "=":
27
+ operator = "=="
28
+
29
+ pkg_name = plan.get(install_consts.PLAN_PACKAGE_NAME)
30
+ app_name = plan.get(install_consts.PLAN_MODULE_NAME)
31
+
32
+ if version == install_consts.INSTALL_LATEST or not operator:
33
+ pkg_info = pkg_name
34
+ else:
35
+ pkg_info = "".join([pkg_name, operator, version])
36
+ cmds = [sys.executable, "-m", "pip", "install", "--upgrade", pkg_info]
37
+
38
+ with open("/etc/issue", "r") as fp:
39
+ issue = fp.readline()
40
+ if issue.startswith("Ubuntu 24.04"):
41
+ cmds.append("--break-system-packages")
42
+
43
+ self.logger and self.logger.info(f"pip 开始安装{pkg_info}")
44
+ need_sudo = shutil.which(app_name).startswith("/home")
45
+ tool.run_command(cmds, sudo=need_sudo, show_log=True)
46
+ self.logger and self.logger.info(f"pip 安装{pkg_info}完成!")
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env python3
2
+ # encoding=utf-8
3
+ # 描述:版本比较器
4
+ # Copyright (c) 2025 Huawei Technologies Co., Ltd.
5
+ # openUBMC is licensed under Mulan PSL v2.
6
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
7
+ # You may obtain a copy of Mulan PSL v2 at:
8
+ # http://license.coscl.org.cn/MulanPSL2
9
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12
+ # See the Mulan PSL v2 for more details.
13
+
14
+ import re
15
+
16
+
17
+ class PkgVersion:
18
+ _version_re = re.compile(
19
+ r"^((?P<epoch>\d+):)?"
20
+ r"(?P<upstream>[0-9a-zA-Z.+~-]+?)"
21
+ r"(-(?P<debian>[0-9a-zA-Z.+~]+))?$"
22
+ )
23
+
24
+ _digit = re.compile(r"^\d+")
25
+ _non_digit = re.compile(r"^\D+")
26
+
27
+ def __init__(self, version: str):
28
+ self.origin = version
29
+ match = self._version_re.match(version)
30
+ if not match:
31
+ raise ValueError(f"版本号非法: {version}")
32
+
33
+ groups = match.groupdict()
34
+ self.epoch = int(groups["epoch"] or 0)
35
+ self.upstream = groups["upstream"]
36
+ self.debian = groups["debian"] or "0"
37
+
38
+ def __lt__(self, other):
39
+ return self.__compare(other) < 0
40
+
41
+ def __eq__(self, other):
42
+ return self.__compare(other) == 0
43
+
44
+ def __le__(self, other):
45
+ return self.__compare(other) <= 0
46
+
47
+ def __ge__(self, other):
48
+ return self.__compare(other) >= 0
49
+
50
+ def __gt__(self, other):
51
+ return self.__compare(other) > 0
52
+
53
+ def __ne__(self, other):
54
+ return self.__compare(other) != 0
55
+
56
+ def __compare_chars(self, a: str, b: str) -> int:
57
+ while a or b:
58
+ a_part = self.__get_part(a)
59
+ b_part = self.__get_part(b)
60
+
61
+ if a_part.startswith("~") or b_part.startswith("~"):
62
+ if a_part != b_part:
63
+ return -1 if a_part.startswith("~") else 1
64
+
65
+ a_isnum = a_part and a_part[0].isdigit()
66
+ b_isnum = b_part and b_part[0].isdigit()
67
+
68
+ if a_isnum != b_isnum:
69
+ return -1 if a_isnum else 1
70
+
71
+ if a_isnum and b_isnum:
72
+ a_num = int(a_part.lstrip("0") or "0")
73
+ b_num = int(b_part.lstrip("0") or "0")
74
+
75
+ if a_num != b_num:
76
+ return -1 if a_num < b_num else 1
77
+ else:
78
+ if a_part != b_part:
79
+ return -1 if a_part < b_part else 1
80
+
81
+ a = a[len(a_part):]
82
+ b = b[len(b_part):]
83
+ return 0
84
+
85
+ def __get_part(self, s: str) -> str:
86
+ if not s:
87
+ return ""
88
+ if s[0].isdigit():
89
+ return self._digit.match(s).group()
90
+ return self._non_digit.match(s).group()
91
+
92
+ def __compare(self, other: type["PkgVersion"]):
93
+ if self.epoch != other.epoch:
94
+ return -1 if self.epoch < other.epoch else 1
95
+
96
+ upstream_cmp = self.__compare_chars(self.upstream, other.upstream)
97
+ if upstream_cmp != 0:
98
+ return upstream_cmp
99
+
100
+ return self.__compare_chars(self.debian, other.debian)
@@ -0,0 +1,443 @@
1
+ #!/usr/bin/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 os
14
+ import shutil
15
+ import json
16
+ import copy
17
+ import stat
18
+ import re
19
+
20
+ from bmcgo.tasks.task import Task
21
+ from bmcgo.logger import Logger
22
+ from bmcgo import misc
23
+
24
+ log = Logger("mapping_config_patch")
25
+
26
+ permission_dict = {
27
+ "redfish": {"rd": 550, "r": 440, "user": [104, 104]},
28
+ "web_backend": {"rd": 550, "r": 440, "user": [104, 104]},
29
+ "snmp": {"rd": 550, "r": 440, "user": [95, 95]},
30
+ misc.CLI: {"rd": 555, "r": 444, "user": [0, 0]}
31
+ }
32
+
33
+
34
+ def is_valid_path(path, prefix, check_is_exist):
35
+ real_path = os.path.realpath(path)
36
+ if not real_path.startswith(prefix):
37
+ log.error(f"无效的路径:{path}")
38
+ return False
39
+
40
+ if check_is_exist and not os.path.exists(path):
41
+ log.error(f"无效的路径,指定的文件/目录不存在:{path}")
42
+ return False
43
+ return True
44
+
45
+
46
+ def load_json_file(json_file):
47
+ with open(json_file, "r") as f:
48
+ return json.load(f)
49
+
50
+
51
+ def save_json_file(json_file, json_dict):
52
+ log.info(f"保存 json 文件到: {json_file}")
53
+ with os.fdopen(os.open(json_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
54
+ stat.S_IWUSR | stat.S_IRUSR), 'w') as fp:
55
+ json.dump(json_dict, fp, separators=(',', ':'))
56
+
57
+
58
+ def split_prop_name(prop):
59
+ array = prop.split("/")
60
+ for i, x in enumerate(array):
61
+ try:
62
+ num = int(x)
63
+ array[i] = num - 1
64
+ except ValueError:
65
+ pass
66
+
67
+ return array
68
+
69
+
70
+ # 删除json节点
71
+ def remove_json_prop(obj, array, depth):
72
+ if not isinstance(obj, (dict, list)):
73
+ return
74
+
75
+ size = len(array) - 1
76
+ if depth > size:
77
+ return
78
+ elif depth == size:
79
+ if isinstance(obj, dict) and array[depth] in obj:
80
+ del obj[array[depth]]
81
+ elif isinstance(obj, list) and array[depth] < len(obj):
82
+ del obj[array[depth]]
83
+ else:
84
+ node = None
85
+ if isinstance(obj, dict) and obj.get(array[depth]) is not None:
86
+ node = obj.get(array[depth])
87
+ elif isinstance(obj, list) and array[depth] < len(obj):
88
+ node = obj[array[depth]]
89
+ if node is not None:
90
+ remove_json_prop(node, array, depth + 1)
91
+
92
+
93
+ # 深度合并两个json,list和dict采用合并,其他采用覆盖
94
+ def merge_json(obj1, obj2):
95
+ if not isinstance(obj1, type(obj2)) or not isinstance(obj1, (dict, list)):
96
+ return
97
+
98
+ if isinstance(obj1, dict):
99
+ for key, value in obj2.items():
100
+ if not obj1.get(key) or not isinstance(obj1[key], type(value)) or not isinstance(value, (dict, list)):
101
+ obj1[key] = copy.deepcopy(value)
102
+ else:
103
+ merge_json(obj1[key], obj2[key])
104
+
105
+ if isinstance(obj1, list):
106
+ for item in obj2:
107
+ obj1.append(copy.deepcopy(item))
108
+
109
+
110
+ # 重命名json节点
111
+ def rename_json_prop(obj, array, depth, new_key):
112
+ if not isinstance(obj, (dict, list)):
113
+ return
114
+
115
+ size = len(array) - 1
116
+ if depth > size:
117
+ return
118
+ elif depth == size:
119
+ if isinstance(obj, dict) and obj.get(array[depth]) is not None:
120
+ obj[new_key] = obj.pop(array[depth])
121
+ elif isinstance(obj, list) and array[depth] < len(obj):
122
+ # 数组没有key值,无法重命名
123
+ return
124
+ else:
125
+ node = None
126
+ if isinstance(obj, dict) and obj.get(array[depth]) is not None:
127
+ node = obj.get(array[depth])
128
+ elif isinstance(obj, list) and array[depth] < len(obj):
129
+ node = obj[array[depth]]
130
+ if node is not None:
131
+ remove_json_prop(node, array, depth + 1, new_key)
132
+
133
+
134
+ class MappingConfigPatch(Task):
135
+ def __init__(self, config, work_name="", config_path=""):
136
+ super(MappingConfigPatch, self).__init__(config, work_name=work_name)
137
+ self.config_path = config_path
138
+ self.config_patch_path = os.path.join(self.config_path, 'config_patch')
139
+
140
+ def uri_remove_in_file(self, target_path, target_uri, target_method):
141
+ target_object = load_json_file(target_path)
142
+ resources = target_object.get("Resources")
143
+ if resources is None:
144
+ log.info(f"Uri移除场景,{target_path}无Resources配置")
145
+ return
146
+
147
+ flag = False
148
+ # 倒序遍历
149
+ for i in range(len(resources) - 1, -1, -1):
150
+ uri = resources[i].get("Uri")
151
+ if uri != target_uri:
152
+ continue
153
+ # 有Uri无Method,删除文件中指定Uri
154
+ if target_method is None:
155
+ flag = True
156
+ del resources[i]
157
+ continue
158
+
159
+ # 有Uri、Method配置,删除指定配置
160
+ interfaces = resources[i].get("Interfaces", [])
161
+ # 倒序遍历
162
+ for j in range(len(interfaces) - 1, -1, -1):
163
+ method = interfaces[j].get("Type", "").lower()
164
+ if method in target_method:
165
+ flag = True
166
+ del interfaces[j]
167
+ if len(interfaces) == 0 and flag:
168
+ del resources[i]
169
+
170
+ if flag:
171
+ save_json_file(target_path, target_object)
172
+ else:
173
+ log.error(f"Uri移除场景,没有找到Uri({target_uri})或Method({target_method})指定的配置")
174
+
175
+ # Uri移除
176
+ def uri_remove(self, actions):
177
+ for action in actions:
178
+ target = action.get("Target")
179
+ target_uri = action.get("Uri")
180
+ target_method = action.get("Method")
181
+ if target is None:
182
+ log.error(f"Uri移除场景,Target参数必须存在")
183
+ continue
184
+ target_path = os.path.join(self.config_path, target)
185
+ if target_method is not None:
186
+ # 将目标Method转为全小写,方便比较
187
+ target_method = [method.lower() for method in target_method]
188
+
189
+ if not is_valid_path(target_path, self.config_path, True):
190
+ continue
191
+
192
+ if os.path.isdir(target_path):
193
+ # 删除整个路径
194
+ if target_uri is not None or target_method is not None:
195
+ log.error(f"Uri移除场景,删除整个路径时,无需Uri和Method配置,路径为{target_path}")
196
+ self.run_command(f"rm -rf {target_path}", sudo=True)
197
+ continue
198
+
199
+ if os.path.isfile(target_path):
200
+ # 无Uri配置,删除整个文件
201
+ if target_uri is None:
202
+ self.run_command(f"rm -rf {target_path}", sudo=True)
203
+ continue
204
+ self.uri_remove_in_file(target_path, target_uri, target_method)
205
+ continue
206
+
207
+ log.error(f"Uri移除场景,没有Target{target}对应的文件或目录")
208
+
209
+ # Uri增加
210
+ def uri_copy(self, actions):
211
+ for action in actions:
212
+ source = action.get("Source")
213
+ target = action.get("Target")
214
+ if source is None or target is None:
215
+ log.error(f"Uri增加场景,Source和Target参数必须存在")
216
+ continue
217
+ source_path = os.path.join(self.config_patch_path, source)
218
+ target_path = os.path.join(self.config_path, target)
219
+
220
+ if not is_valid_path(source_path, self.config_patch_path, True) or\
221
+ not is_valid_path(target_path, self.config_path, False):
222
+ continue
223
+
224
+ if os.path.exists(target_path):
225
+ log.info(f"Uri增加场景,Target({target})指定的文件或目录已存在,删除原有的")
226
+ self.run_command(f"rm -rf {target_path}", sudo=True, command_echo=False)
227
+
228
+ if os.path.isfile(source_path):
229
+ dir_name = os.path.dirname(target_path)
230
+ if not os.path.exists(dir_name):
231
+ # 目标路径不存在时,需要递归创建
232
+ os.makedirs(dir_name)
233
+ shutil.copyfile(source_path, target_path)
234
+ elif os.path.isdir(source_path):
235
+ shutil.copytree(source_path, target_path)
236
+ log.info(f"复制 {source_path} 到 {target_path}")
237
+
238
+ # Uri重命名
239
+ def uri_rename(self, actions):
240
+ for action in actions:
241
+ target = action.get("Target")
242
+ origin_uri = action.get("OriginUri")
243
+ new_uri = action.get("NewUri")
244
+ if target is None or origin_uri is None or new_uri is None:
245
+ log.error(f"Uri重命名场景,Target、OriginUri、NewUri参数必须存在")
246
+ continue
247
+ target_path = os.path.join(self.config_path, target)
248
+ if not is_valid_path(target_path, self.config_path, True):
249
+ continue
250
+
251
+ target_object = load_json_file(target_path)
252
+ resources = target_object.get("Resources")
253
+ if resources is None:
254
+ log.info(f"Uri重命名场景,文件{target_path}无Resources配置")
255
+ continue
256
+
257
+ flag = False
258
+ for resource in resources:
259
+ uri = resource.get("Uri")
260
+ if uri == origin_uri:
261
+ flag = True
262
+ resource["Uri"] = new_uri
263
+
264
+ if flag:
265
+ save_json_file(target_path, target_object)
266
+ else:
267
+ log.error(f"Uri重命名场景,没有找到Uri({origin_uri})指定的配置")
268
+
269
+
270
+ def uri_actions(self, actions):
271
+ self.uri_remove(actions.get("Remove", []))
272
+ self.uri_copy(actions.get("Copy", []))
273
+ self.uri_rename(actions.get("Rename", []))
274
+
275
+
276
+ def adjust_processingflow_sequence(self, base, actions):
277
+ if base is None or len(base) == 0:
278
+ return
279
+ base = len(base)
280
+
281
+ def replace_processing_flow(s):
282
+ pattern = r"ProcessingFlow\[(\d+)\]"
283
+
284
+ def replace(match):
285
+ n = int(match.group(1))
286
+ return f"ProcessingFlow[{n + base}]"
287
+ t = re.sub(pattern, replace, s)
288
+ return s == t, t
289
+
290
+ def traversal(obj):
291
+ if isinstance(obj, dict):
292
+ for key, value in obj.items():
293
+ is_equal, new = replace_processing_flow(key)
294
+ if not is_equal:
295
+ obj[new] = obj[key].pop()
296
+ if isinstance(value, (dict, list)):
297
+ traversal(value)
298
+ continue
299
+ if not isinstance(value, str):
300
+ continue
301
+ is_equal, new = replace_processing_flow(value)
302
+ if not is_equal:
303
+ obj[key] = new
304
+ elif isinstance(obj, list):
305
+ for i, _ in enumerate(obj):
306
+ if isinstance(obj[i], (dict, list)):
307
+ traversal(obj[i])
308
+ continue
309
+ if not isinstance(obj[i], str):
310
+ continue
311
+ is_equal, new = replace_processing_flow(obj[i])
312
+ if not is_equal:
313
+ obj[i] = new
314
+ traversal(actions)
315
+
316
+ # 属性移除
317
+ def property_remove(self, interface, actions):
318
+ for prop in actions:
319
+ remove_json_prop(interface, split_prop_name(prop), 0)
320
+
321
+ # 属性变更
322
+ def property_modify(self, interface, actions):
323
+ self.adjust_processingflow_sequence(interface.get("ProcessingFlow"), actions)
324
+ merge_json(interface, actions)
325
+
326
+ # 属性重命名
327
+ def property_rename(self, interface, actions):
328
+ for key, value in actions.items():
329
+ rename_json_prop(interface, split_prop_name(key), 0, value)
330
+
331
+ def property_action(self, resources, target_method, target_uri, action):
332
+ flag = False
333
+ for resource in resources:
334
+ uri = resource.get("Uri")
335
+ if uri != target_uri:
336
+ continue
337
+ interfaces = resource.get("Interfaces", [])
338
+ for interface in interfaces:
339
+ method = interface.get("Type", "")
340
+ if method.lower() != target_method.lower():
341
+ continue
342
+ flag = True
343
+ self.property_remove(interface, action.get("Remove", []))
344
+ self.property_modify(interface, action.get("Modify", {}))
345
+ self.property_rename(interface, action.get("Rename", {}))
346
+ return flag
347
+
348
+ def property_actions(self, actions):
349
+ for action in actions:
350
+ target = action.get("Target")
351
+ target_uri = action.get("Uri")
352
+ target_method = action.get("Method")
353
+ if target is None or target_uri is None or target_method is None:
354
+ log.error(f"属性变更场景,Target、Uri、Method参数必须存在")
355
+ continue
356
+ target_path = os.path.join(self.config_path, target)
357
+ if not is_valid_path(target_path, self.config_path, True):
358
+ continue
359
+
360
+ target_object = load_json_file(target_path)
361
+ resources = target_object.get("Resources")
362
+ if resources is None:
363
+ log.info(f"属性变更场景,文件{target_path}无Resources配置")
364
+ continue
365
+ flag = self.property_action(resources, target_method, target_uri, action)
366
+
367
+ if flag:
368
+ save_json_file(target_path, target_object)
369
+ else:
370
+ log.error(f"属性变更场景,没有找到Uri({target_uri})指定的配置")
371
+
372
+
373
+ def global_variables(self, global_variable):
374
+ if global_variable is None:
375
+ return
376
+ target_path = os.path.join(self.config_path, "config.json")
377
+ if not os.path.exists(target_path):
378
+ return
379
+ target_object = load_json_file(target_path)
380
+ target_global_variable = target_object.get("GlobalVariable")
381
+ if target_global_variable is None:
382
+ log.info(f"平台层文件{target_path}无GlobalVariable配置")
383
+ return
384
+ merge_json(target_global_variable, global_variable)
385
+ save_json_file(target_path, target_object)
386
+
387
+
388
+ def restore_permission(self):
389
+ p = {"rd": 550, "r": 440, "user": [0, 0]}
390
+ for key, value in permission_dict.items():
391
+ app = "opt/bmc/apps/" + key
392
+ if app in self.config_path:
393
+ p = value
394
+
395
+ self.pipe_command([f"sudo find {self.config_path} -type d", f"sudo xargs -P 0 -i. chmod {p['rd']} ."])
396
+ self.pipe_command([f"sudo find {self.config_path} -type f", f"sudo xargs -P 0 -i. chmod {p['r']} ."])
397
+ self.pipe_command([f"sudo find {self.config_path} -type d",
398
+ f"sudo xargs -P 0 -i. chown {p['user'][0]}:{p['user'][1]} ."])
399
+ self.pipe_command([f"sudo find {self.config_path} -type f",
400
+ f"sudo xargs -P 0 -i. chown {p['user'][0]}:{p['user'][1]} ."])
401
+
402
+ def config_patch(self):
403
+ patch_file = os.path.join(self.config_patch_path, 'config.json')
404
+ if not os.path.isfile(patch_file):
405
+ return
406
+
407
+ patch_object = load_json_file(patch_file)
408
+ self.uri_actions(patch_object.get("Uri.Actions", {}))
409
+ self.property_actions(patch_object.get("Property.Actions", []))
410
+ self.global_variables(patch_object.get("GlobalVariable", {}))
411
+
412
+
413
+ def run(self):
414
+ if not os.path.isdir(self.config_patch_path):
415
+ return
416
+
417
+ # 给予权限方便对文件做变更
418
+ self.run_command(f"chmod -R 777 {self.config_path}", sudo=True)
419
+
420
+ self.config_patch()
421
+
422
+ # 变更完成恢复权限
423
+ self.restore_permission()
424
+ self.run_command(f"rm -rf {self.config_patch_path}", sudo=True)
425
+
426
+
427
+ class MappingConfigGenerate(MappingConfigPatch):
428
+ def __init__(self, config, work_name="", config_path="", custom="default"):
429
+ super(MappingConfigPatch, self).__init__(config, work_name=work_name)
430
+ self.config_path = config_path
431
+ self.config_patch_path = os.path.join(self.config_path, 'customer', custom)
432
+
433
+ def run(self):
434
+ if not os.path.isdir(self.config_patch_path):
435
+ return
436
+
437
+ # 给予权限方便对文件做变更
438
+ self.run_command(f"chmod -R 777 {self.config_path}", sudo=True)
439
+
440
+ self.config_patch()
441
+
442
+ # 变更完成恢复权限
443
+ self.restore_permission()