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,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))
|