1616
1717from django .utils .translation import ugettext_lazy as _
1818
19- from apps .node_man import constants
19+ from apps .node_man import constants , models
2020
2121from . 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"\x7f ELF" :
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
0 commit comments