Skip to content

Commit b5a62fd

Browse files
committed
feat: 构建proxy包时支持arm架构以及支持使用包中的gse_agent二进制文件(closed #2699)
1 parent 863ceb5 commit b5a62fd

2 files changed

Lines changed: 125 additions & 28 deletions

File tree

apps/backend/agent/artifact_builder/proxy.py

Lines changed: 123 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from django.utils.translation import ugettext_lazy as _
1818

19-
from apps.node_man import constants
19+
from apps.node_man import constants, models
2020

2121
from . import base
2222

@@ -34,6 +34,7 @@ class ProxyArtifactBuilder(base.BaseArtifactBuilder):
3434
SERVER_BIN_DIR: str = "server/bin"
3535
# 所需的二进制文件
3636
PROXY_SVR_EXES: typing.List[str] = ["gse_data", "gse_file"]
37+
AGENT_BINARY_NAME: str = "gse_agent"
3738

3839
def extract_initial_artifact(self, initial_artifact_local_path: str, extract_dir: str):
3940
with tarfile.open(name=initial_artifact_local_path) as tf:
@@ -43,37 +44,46 @@ def extract_initial_artifact(self, initial_artifact_local_path: str, extract_dir
4344
if not os.path.exists(extract_dir):
4445
raise FileExistsError(_("Proxy 包解压后不存在 {base_pkg_dir} 目录").format(base_pkg_dir=self.BASE_PKG_DIR))
4546

46-
# 把基础 Agent 包拉过来
4747
os_str: str = constants.PluginOsType.linux
48-
cpu_arch: str = constants.CpuType.x86_64
49-
pkg_name: str = f"{constants.GsePackageCode.AGENT.value}-{self._get_version(extract_dir)}.tgz"
50-
base_agent_pkg_path: str = os.path.join(self.download_path, self.BASE_STORAGE_DIR, os_str, cpu_arch, pkg_name)
51-
if not self.storage.exists(base_agent_pkg_path):
52-
raise FileExistsError(
53-
_("构建 Proxy 所需 Agent 包不存在:file_path -> {file_path}").format(file_path=base_agent_pkg_path)
48+
cpu_arch: str = self._get_elf_arch(os.path.join(extract_dir, self.SERVER_BIN_DIR, self.PROXY_SVR_EXES[0]))
49+
50+
# 按正则规范构建 Proxy 安装包的目录
51+
proxy_dir: str = os.path.join(extract_dir, self.PKG_PATH_DIR_TEMPL.format(os=os_str, cpu_arch=cpu_arch))
52+
proxy_bin_dir: str = os.path.join(proxy_dir, "bin")
53+
54+
if os.path.exists(os.path.join(extract_dir, self.SERVER_BIN_DIR, self.AGENT_BINARY_NAME)):
55+
os.makedirs(proxy_bin_dir, exist_ok=True)
56+
logger.info(f"make proxy_bin_dir -> {proxy_bin_dir} success.")
57+
self.PROXY_SVR_EXES.append(self.AGENT_BINARY_NAME)
58+
else:
59+
# 把基础 Agent 包拉过来
60+
pkg_name: str = f"{constants.GsePackageCode.AGENT.value}-{self._get_version(extract_dir)}.tgz"
61+
base_agent_pkg_path: str = os.path.join(
62+
self.download_path, self.BASE_STORAGE_DIR, os_str, cpu_arch, pkg_name
5463
)
64+
if not self.storage.exists(base_agent_pkg_path):
65+
raise FileExistsError(
66+
_("构建 Proxy 所需 Agent 包不存在:file_path -> {file_path}").format(file_path=base_agent_pkg_path)
67+
)
5568

56-
base_agent_src: str = os.path.join(extract_dir, str(constants.GsePackageDir.AGENT.value))
57-
# src 存在即移除,确保基础 Agent 解压目录是干净的
58-
if os.path.exists(base_agent_src):
59-
shutil.rmtree(base_agent_src)
60-
logger.warning(f"base_agent_src -> {base_agent_src} not clean, removed it.")
69+
base_agent_src: str = os.path.join(extract_dir, str(constants.GsePackageDir.AGENT.value))
70+
# src 存在即移除,确保基础 Agent 解压目录是干净的
71+
if os.path.exists(base_agent_src):
72+
shutil.rmtree(base_agent_src)
73+
logger.warning(f"base_agent_src -> {base_agent_src} not clean, removed it.")
6174

62-
# 执行解压
63-
with self.storage.open(name=base_agent_pkg_path, mode="rb") as tf_from_storage:
64-
with tarfile.open(fileobj=tf_from_storage) as tf:
65-
tf.extractall(extract_dir)
66-
logger.info(f"file -> {base_agent_pkg_path} extract to dir -> {extract_dir} success.")
75+
# 执行解压
76+
with self.storage.open(name=base_agent_pkg_path, mode="rb") as tf_from_storage:
77+
with tarfile.open(fileobj=tf_from_storage) as tf:
78+
tf.extractall(extract_dir)
79+
logger.info(f"file -> {base_agent_pkg_path} extract to dir -> {extract_dir} success.")
6780

68-
# 按正则规范构建 Proxy 安装包的目录
69-
proxy_dir: str = os.path.join(extract_dir, self.PKG_PATH_DIR_TEMPL.format(os=os_str, cpu_arch=cpu_arch))
70-
os.rename(base_agent_src, proxy_dir)
71-
logger.info(f"rename base_agent_src -> {base_agent_src} to proxy_dir -> {proxy_dir}")
81+
os.rename(base_agent_src, proxy_dir)
82+
logger.info(f"rename base_agent_src -> {base_agent_src} to proxy_dir -> {proxy_dir}")
7283

73-
# bin 目录检查
74-
proxy_bin_dir: str = os.path.join(proxy_dir, "bin")
75-
if not os.path.exists(proxy_bin_dir):
76-
raise FileExistsError(_("构建 Proxy 所需 Agent 不存在 bin 路径"))
84+
# bin 目录检查
85+
if not os.path.exists(proxy_bin_dir):
86+
raise FileExistsError(_("构建 Proxy 所需 Agent 不存在 bin 路径"))
7787

7888
# 将所需的二进制放到安装包目录
7989
for svr_exe in self.PROXY_SVR_EXES:
@@ -92,5 +102,92 @@ def extract_initial_artifact(self, initial_artifact_local_path: str, extract_dir
92102
self._inject_dependencies(extract_dir)
93103
return extract_dir
94104

105+
def update_or_create_support_files(self, package_infos: typing.List[typing.Dict]):
106+
"""
107+
创建或更新support_files记录
108+
:param package_infos:
109+
:return:
110+
"""
111+
for package_info in package_infos:
112+
support_files = package_info["artifact_meta_info"]["support_files_info"]
113+
version = package_info["artifact_meta_info"]["version"]
114+
package = package_info["package_dir_info"]
115+
116+
for env_file in support_files["env"]:
117+
with open(env_file["file_absolute_path"], "r") as f:
118+
env_str = f.read()
119+
120+
logger.info(
121+
f"update_or_create_support_files: env_file->{env_file} version->{version} raw_env->{env_str}"
122+
)
123+
env_value: typing.Dict[str, typing.Any] = self.parse_env(env_str)
124+
logger.info(
125+
f"update_or_create_support_files: env_file->{env_file} version->{version} env_value->{env_value}"
126+
)
127+
128+
models.GseConfigEnv.objects.update_or_create(
129+
defaults={"env_value": env_value},
130+
version=version,
131+
os=package["os"],
132+
cpu_arch=package["cpu_arch"],
133+
agent_name=(
134+
constants.GsePackageCode.AGENT.value
135+
if env_file["file_name"] in constants.GsePackageEnv.AGENT.value
136+
else self.NAME
137+
),
138+
)
139+
140+
for template in support_files["templates"]:
141+
with open(template["file_absolute_path"], "r") as f:
142+
content = f.read()
143+
logger.info(
144+
f"update_or_create_support_files: template->{template} version->{version} content->{content}"
145+
)
146+
147+
models.GseConfigTemplate.objects.update_or_create(
148+
defaults={"content": content},
149+
name=template["file_name"],
150+
version=version,
151+
os=package["os"],
152+
cpu_arch=package["cpu_arch"],
153+
agent_name=(
154+
constants.GsePackageCode.AGENT.value
155+
if constants.GsePackageTemplatePattern.AGENT.value.search(template["file_name"])
156+
else self.NAME
157+
),
158+
)
159+
95160
def _get_support_files_info(self, extract_dir: str) -> typing.Dict[str, typing.Any]:
96161
return super()._get_support_files_info(extract_dir=extract_dir)
162+
163+
def _get_elf_arch(self, binary_path: str) -> str:
164+
if not os.path.exists(binary_path):
165+
return constants.CpuType.x86_64
166+
167+
import struct
168+
169+
# ELF e_machine: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
170+
EM_AARCH64 = 0xB7 # AARCH64 架构
171+
with open(binary_path, "rb") as f:
172+
magic = f.read(4)
173+
if magic != b"\x7fELF":
174+
raise ValueError(_("文件 {binary_path} 不是合法的 ELF 文件").format(binary_path=binary_path))
175+
176+
# ELF 头偏移 5 字节是 EI_DATA
177+
f.seek(5)
178+
ei_data = f.read(1)[0]
179+
180+
if ei_data == 1: # ELFDATA2LSB (小端序)
181+
fmt = "<H"
182+
elif ei_data == 2: # ELFDATA2MSB (大端序)
183+
fmt = ">H"
184+
else:
185+
fmt = "@H" # 使用系统字节序
186+
187+
f.seek(18)
188+
e_machine = struct.unpack(fmt, f.read(2))[0]
189+
if e_machine == EM_AARCH64:
190+
return constants.CpuType.aarch64
191+
else:
192+
# 目前仅支持 x86_64 和 aarch64 两种架构
193+
return constants.CpuType.x86_64

apps/node_man/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -990,14 +990,14 @@ def _get_member__alias_map(cls) -> Dict[Enum, str]:
990990
class GsePackageEnv(EnhanceEnum):
991991
"""安装包Env文件名称"""
992992

993-
PROXY = ["gse_proxy.env"]
993+
PROXY = ["gse_proxy.env", "gse_agent.env"]
994994
AGENT = ["gse_agent.env"]
995995

996996

997997
class GsePackageTemplate(EnhanceEnum):
998998
"""安装包Template文件名称"""
999999

1000-
PROXY = ["gse_data_proxy.conf", "gse_file_proxy.conf"]
1000+
PROXY = ["gse_data_proxy.conf", "gse_file_proxy.conf", "gse_agent.conf"]
10011001
AGENT = ["gse_agent.conf"]
10021002

10031003

0 commit comments

Comments
 (0)