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.
- bmcgo/__init__.py +12 -0
- bmcgo/bmcgo.py +22 -0
- bmcgo/bmcgo_config.py +176 -0
- bmcgo/cli/__init__.py +10 -0
- bmcgo/cli/cli.py +584 -0
- bmcgo/codegen/__init__.py +14 -0
- bmcgo/codegen/c/__init__.py +9 -0
- bmcgo/codegen/c/annotation.py +52 -0
- bmcgo/codegen/c/argument.py +42 -0
- bmcgo/codegen/c/codegen.py +153 -0
- bmcgo/codegen/c/comment.py +22 -0
- bmcgo/codegen/c/ctype_defination.py +353 -0
- bmcgo/codegen/c/helper.py +87 -0
- bmcgo/codegen/c/interface.py +63 -0
- bmcgo/codegen/c/method.py +82 -0
- bmcgo/codegen/c/property.py +180 -0
- bmcgo/codegen/c/renderer.py +21 -0
- bmcgo/codegen/c/signal.py +64 -0
- bmcgo/codegen/c/template/client.c.mako +145 -0
- bmcgo/codegen/c/template/client.h.mako +36 -0
- bmcgo/codegen/c/template/interface.c.mako +0 -0
- bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
- bmcgo/codegen/c/template/micro_component.c.mako +32 -0
- bmcgo/codegen/c/template/public.c.mako +228 -0
- bmcgo/codegen/c/template/public.h.mako +128 -0
- bmcgo/codegen/c/template/server.c.mako +104 -0
- bmcgo/codegen/c/template/server.h.mako +36 -0
- bmcgo/codegen/lua/.lua-format +7 -0
- bmcgo/codegen/lua/Makefile +101 -0
- bmcgo/codegen/lua/__init__.py +9 -0
- bmcgo/codegen/lua/codegen.py +171 -0
- bmcgo/codegen/lua/proto/Makefile +87 -0
- bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
- bmcgo/codegen/lua/proto/types.proto +52 -0
- bmcgo/codegen/lua/script/check_intfs.py +161 -0
- bmcgo/codegen/lua/script/dto/__init__.py +11 -0
- bmcgo/codegen/lua/script/dto/exception.py +53 -0
- bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
- bmcgo/codegen/lua/script/dto/options.py +33 -0
- bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
- bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
- bmcgo/codegen/lua/script/dto/url_route.py +195 -0
- bmcgo/codegen/lua/script/gen_db_json.py +444 -0
- bmcgo/codegen/lua/script/gen_depends.py +89 -0
- bmcgo/codegen/lua/script/gen_entry.py +263 -0
- bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
- bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
- bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
- bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
- bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
- bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
- bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
- bmcgo/codegen/lua/script/gen_schema.py +302 -0
- bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
- bmcgo/codegen/lua/script/loader/__init__.py +11 -0
- bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
- bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
- bmcgo/codegen/lua/script/lua_format.py +62 -0
- bmcgo/codegen/lua/script/mds_util.py +385 -0
- bmcgo/codegen/lua/script/merge_model.py +330 -0
- bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
- bmcgo/codegen/lua/script/proto_loader.py +47 -0
- bmcgo/codegen/lua/script/proto_plugin.py +140 -0
- bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
- bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
- bmcgo/codegen/lua/script/render_utils/base.py +25 -0
- bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
- bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
- bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
- bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
- bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
- bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
- bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
- bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
- bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
- bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
- bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
- bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
- bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
- bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
- bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
- bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
- bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
- bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
- bmcgo/codegen/lua/script/template.py +166 -0
- bmcgo/codegen/lua/script/types_pb2.py +516 -0
- bmcgo/codegen/lua/script/utils.py +663 -0
- bmcgo/codegen/lua/script/validate.py +80 -0
- bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
- bmcgo/codegen/lua/templates/Makefile +114 -0
- bmcgo/codegen/lua/templates/apps/Makefile +261 -0
- bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
- bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
- bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
- bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
- bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
- bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
- bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
- bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
- bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
- bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
- bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
- bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
- bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
- bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
- bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
- bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
- bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
- bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
- bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
- bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
- bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
- bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
- bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
- bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
- bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
- bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
- bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
- bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
- bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
- bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
- bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
- bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
- bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
- bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
- bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
- bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
- bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
- bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
- bmcgo/component/__init__.py +10 -0
- bmcgo/component/analysis/analysis.py +183 -0
- bmcgo/component/analysis/build_deps.py +165 -0
- bmcgo/component/analysis/data_deps.py +333 -0
- bmcgo/component/analysis/dep-rules.json +912 -0
- bmcgo/component/analysis/dep_node.py +110 -0
- bmcgo/component/analysis/intf_deps.py +163 -0
- bmcgo/component/analysis/intf_validation.py +254 -0
- bmcgo/component/analysis/rule.py +211 -0
- bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
- bmcgo/component/analysis/sr_validation.py +391 -0
- bmcgo/component/build.py +222 -0
- bmcgo/component/component_dt_version_parse.py +348 -0
- bmcgo/component/component_helper.py +114 -0
- bmcgo/component/coverage/__init__.py +11 -0
- bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
- bmcgo/component/coverage/incremental_cov.py +464 -0
- bmcgo/component/deploy.py +110 -0
- bmcgo/component/gen.py +169 -0
- bmcgo/component/package_info.py +236 -0
- bmcgo/component/template/conanbase.py.mako +278 -0
- bmcgo/component/template/conanfile.deploy.py.mako +40 -0
- bmcgo/component/test.py +947 -0
- bmcgo/errors.py +119 -0
- bmcgo/frame.py +217 -0
- bmcgo/functional/__init__.py +10 -0
- bmcgo/functional/analysis.py +96 -0
- bmcgo/functional/bmc_studio_action.py +98 -0
- bmcgo/functional/check.py +185 -0
- bmcgo/functional/conan_index_build.py +251 -0
- bmcgo/functional/config.py +332 -0
- bmcgo/functional/csr_build.py +724 -0
- bmcgo/functional/deploy.py +263 -0
- bmcgo/functional/diff.py +235 -0
- bmcgo/functional/fetch.py +235 -0
- bmcgo/functional/full_component.py +391 -0
- bmcgo/functional/maintain.py +381 -0
- bmcgo/functional/new.py +166 -0
- bmcgo/functional/schema_valid.py +111 -0
- bmcgo/functional/simple_sign.py +104 -0
- bmcgo/functional/upgrade.py +78 -0
- bmcgo/ipmigen/__init__.py +13 -0
- bmcgo/ipmigen/ctype_defination.py +82 -0
- bmcgo/ipmigen/ipmigen.py +309 -0
- bmcgo/ipmigen/template/cmd.c.mako +366 -0
- bmcgo/ipmigen/template/ipmi.c.mako +25 -0
- bmcgo/ipmigen/template/ipmi.h.mako +51 -0
- bmcgo/logger.py +176 -0
- bmcgo/misc.py +117 -0
- bmcgo/target/app.yml +17 -0
- bmcgo/target/install_sdk.yml +15 -0
- bmcgo/target/personal.yml +53 -0
- bmcgo/target/publish.yml +45 -0
- bmcgo/tasks/__init__.py +11 -0
- bmcgo/tasks/download_buildtools_hm.py +124 -0
- bmcgo/tasks/misc.py +15 -0
- bmcgo/tasks/task.py +354 -0
- bmcgo/tasks/task_build_conan.py +714 -0
- bmcgo/tasks/task_build_rootfs_img.py +595 -0
- bmcgo/tasks/task_buildgppbin.py +88 -0
- bmcgo/tasks/task_buildhpm_ext4.py +82 -0
- bmcgo/tasks/task_create_interface_config.py +122 -0
- bmcgo/tasks/task_download_buildtools.py +99 -0
- bmcgo/tasks/task_download_dependency.py +72 -0
- bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
- bmcgo/tasks/task_packet_to_supporte.py +87 -0
- bmcgo/tasks/task_prepare.py +105 -0
- bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
- bmcgo/utils/__init__.py +10 -0
- bmcgo/utils/buffer.py +128 -0
- bmcgo/utils/combine_json_schemas.py +170 -0
- bmcgo/utils/component_post.py +54 -0
- bmcgo/utils/component_version_check.py +86 -0
- bmcgo/utils/config.py +1067 -0
- bmcgo/utils/fetch_component_code.py +232 -0
- bmcgo/utils/install_manager.py +61 -0
- bmcgo/utils/installations/__init__.py +10 -0
- bmcgo/utils/installations/base_installer.py +70 -0
- bmcgo/utils/installations/install_consts.py +30 -0
- bmcgo/utils/installations/install_plans/bingo.yml +11 -0
- bmcgo/utils/installations/install_workflow.py +50 -0
- bmcgo/utils/installations/installers/apt_installer.py +177 -0
- bmcgo/utils/installations/installers/pip_installer.py +46 -0
- bmcgo/utils/installations/version_util.py +100 -0
- bmcgo/utils/mapping_config_patch.py +443 -0
- bmcgo/utils/perf_analysis.py +114 -0
- bmcgo/utils/tools.py +704 -0
- bmcgo/worker.py +417 -0
- openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
- openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
- openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
- openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
- 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()
|