• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4#
5# Copyright (c) 2020-2023 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20import shutil
21import subprocess
22import json
23import sys
24import time
25import xml.etree.ElementTree as ET
26from public_method import get_server_dict, get_config_ip, get_sn_list
27
28
29def _init_sys_config():
30    sys.localcoverage_path = os.path.join(current_path, "..")
31    sys.path.insert(0, sys.localcoverage_path)
32
33
34def modify_init_file(developer_path, hdc_str):
35    """
36    /etc/init.cfg文件添加cmds
37    """
38    recv_path = os.path.join(developer_path, "localCoverage/resident_service/resources")
39    print("%s file recv /etc/init.cfg %s" % (hdc_str, recv_path))
40    coverage_command("%s file recv /etc/init.cfg %s" % (hdc_str, recv_path))
41    recv_restores_path = os.path.join(recv_path, "restores_environment")
42    if not os.path.exists(recv_restores_path):
43        os.mkdir(recv_restores_path)
44    recv_restores_name = os.path.join(recv_restores_path, "init.cfg")
45    if not os.path.exists(recv_restores_name):
46        coverage_command("%s file recv /etc/init.cfg %s" % (hdc_str, recv_restores_path))
47    else:
48        print("INFO: file exit", recv_restores_name)
49
50    cfg_file_path = os.path.join(recv_path, "init.cfg")
51    if os.path.exists(cfg_file_path):
52        with open(cfg_file_path, "r") as fp:
53            json_data = json.load(fp)
54
55        for jobs_list in json_data["jobs"]:
56            if jobs_list["name"] == "init":
57                if jobs_list["cmds"][-1] != "export GCOV_FETCH_METHOD FM_SIGNA":
58                    jobs_list["cmds"].append("mkdir /data/gcov 0777 system system")
59                    jobs_list["cmds"].append("export GCOV_PREFIX /data/gcov")
60                    jobs_list["cmds"].append("export GCOV_FETCH_METHOD FM_SIGNA")
61                else:
62                    return
63        json_str = json.dumps(json_data, indent=2)
64        with open(cfg_file_path, "w") as json_file:
65            json_file.write(json_str)
66    else:
67        print("init.cfg file not exists")
68        return
69    print("%s shell mount -o rw,remount / > /dev/null 2>&1" % hdc_str)
70    coverage_command("%s shell mount -o rw,remount / > /dev/null 2>&1" % hdc_str)
71    print("%s file send %s %s" % (hdc_str, cfg_file_path, "/etc/"))
72    coverage_command("%s file send %s %s" % (hdc_str, cfg_file_path, "/etc/"))
73    coverage_command("%s shell param set persist.appspawn.client.timeout 120 > /dev/null 2>&1" % hdc_str)
74    return
75
76
77def modify_faultloggerd_file(developer_path, hdc_str):
78    _, enforce = subprocess.getstatusoutput("%s shell getenforce" % hdc_str)
79    coverage_command("%s shell mount -o rw,remount /" % hdc_str)
80    print("%s shell mount -o rw,remount /" % hdc_str)
81    if enforce != "Permissive":
82        coverage_command("%s shell sed -i 's/enforcing/permissive/g' /system/etc/selinux/config" % hdc_str)
83
84    recv_path = os.path.join(developer_path, "localCoverage/resident_service/resources")
85    print("%s file recv /system/etc/init/faultloggerd.cfg %s" % (hdc_str, recv_path))
86    coverage_command("%s file recv /system/etc/init/faultloggerd.cfg %s" % (hdc_str, recv_path))
87
88    cfg_file_path = os.path.join(recv_path, "faultloggerd.cfg")
89    if os.path.exists(cfg_file_path):
90        with open(cfg_file_path, "r") as fp:
91            json_data = json.load(fp)
92        if len(json_data["jobs"]) == 1 and json_data["jobs"][0]["name"] != "pre-init":
93            json_data["jobs"].insert(0, {
94                "name": "pre-init",
95                "cmds": [
96                    "export LD_PRELOAD libcoverage_signal_handler.z.so"
97                ]
98            })
99            json_str = json.dumps(json_data, indent=4)
100            with open(cfg_file_path, "w") as json_file:
101                json_file.write(json_str)
102            print("%s file send %s %s" % (hdc_str, cfg_file_path, "/system/etc/init/"))
103            coverage_command("%s file send %s %s" % (hdc_str, cfg_file_path, "/system/etc/init/"))
104    else:
105        print("faultloggerd.cfg file not exists.")
106
107    return
108
109
110def modify_foundation_xml(serv, config_path, origin_xml) -> str:
111    """
112    修改foundation.xml文件,删去拆分的进程相关
113    :param serv: 拆分进程
114    :param config_path: 配置文件路径
115    :param origin_xml: 原foundation.xml
116    :return: 修改后foundation.xml路径
117    """
118    lib_list = FoundationServer.lib_dict.get(serv)
119
120    tree = ET.parse(origin_xml)
121    root = tree.getroot()
122    loadlibs = root.find("loadlibs")
123
124    for lib in lib_list:
125        for sa in root.findall('systemability'):
126            if lib in sa.find('libpath').text:
127                root.remove(sa)
128        for ll in loadlibs.findall('libpath'):
129            if lib in ll.text:
130                loadlibs.remove(ll)
131
132    tree.write(os.path.join(config_path, 'foundation.xml'), encoding='utf-8', xml_declaration=True)
133    return os.path.join(config_path, 'foundation.xml')
134
135
136def modify_foundation_json(serv, config_path, origin_json) -> str:
137    """
138    修改foundation.json文件,删去拆分的进程相关
139    :param serv: 拆分进程
140    :param config_path: 配置文件路径
141    :param origin_json: 原foundation.json
142    :return: 修改后foundation.json路径
143    """
144    lib_list = FoundationServer.lib_dict.get(serv)
145
146    with open(origin_json, "r", encoding="UTF-8") as f:
147        f_dict = json.load(f)
148
149    tmp_list = list()
150    for i in range(len(f_dict["systemability"])):
151        if f_dict["systemability"][i]["libpath"] not in lib_list:
152            tmp_list.append(f_dict["systemability"][i])
153    f_dict["systemability"] = tmp_list
154
155    new_json = os.path.join(config_path, 'foundation.json')
156    with open(new_json, "w", encoding="utf-8") as f:
157        json.dump(f_dict, f, indent=4)
158
159    return new_json
160
161
162def create_service_json(serv, config_path, origin_json) -> str:
163    """
164    创建进程json
165    :param serv: 进程名
166    :param config_path:配置文件所在目录
167    :param origin_json: 原foundation.json
168    :return: json文件路径
169    """
170    lib_list = FoundationServer.lib_dict.get(serv)
171    with open(origin_json, "r", encoding="UTF-8") as f:
172        f_dict = json.load(f)
173
174    tmp_list = list()
175    for lib in lib_list:
176        for i in range(len(f_dict["systemability"])):
177            if f_dict["systemability"][i]["libpath"] == lib:
178                tmp_list.append(f_dict["systemability"][i])
179    f_dict["systemability"] = tmp_list
180    f_dict["process"] = "{}".format(serv)
181
182    new_json = os.path.join(config_path, '{}.json'.format(serv))
183    with open(new_json, "w", encoding="utf-8") as f:
184        json.dump(f_dict, f, indent=4)
185
186    return new_json
187
188
189def create_service_xml(serv, config_path, origin_xml) -> str:
190    """
191    创建进程xml
192    :param serv: 进程名
193    :param config_path:配置文件所在目录
194    :param origin_xml: 原foundation.xml
195    :return: xml文件路径
196    """
197    lib_list = FoundationServer.lib_dict.get(serv)
198
199    tree = ET.parse(origin_xml)
200    root = tree.getroot()
201    loadlibs = root.find("loadlibs")
202
203    for lib in lib_list:
204        for sa in root.findall('systemability'):
205            if lib not in sa.find('libpath').text:
206                root.remove(sa)
207        for lp in loadlibs.findall('libpath'):
208            if lib not in lp.text:
209                loadlibs.remove(lp)
210
211    tree.write(os.path.join(config_path, '{}.xml'.format(serv)), encoding='utf-8', xml_declaration=True)
212    return os.path.join(config_path, '{}.xml'.format(serv))
213
214
215def create_service_cfg(serv, config_path, origin_cfg) -> str:
216    """
217    创建进程cfg文件
218    :param serv: 进程名
219    :param config_path:配置文件所在目录
220    :param origin_cfg: 原foundation.cfg
221    :return: cfg文件路径
222    """
223    with open(origin_cfg, "r") as jf:
224        json_obj = json.load(jf)
225        json_obj["jobs"][0]["name"] = "services:{}".format(serv)
226
227        json_obj["services"][0]["name"] = "{}".format(serv)
228
229        path_list = json_obj["services"][0]["path"]
230        path_list.remove("/system/profile/foundation.json")
231        path_list.append("/system/profile/{}.json".format(serv))
232        json_obj["services"][0]["path"] = path_list
233
234        json_obj["services"][0]["jobs"]["on-start"] = "services:{}".format(serv)
235
236    cfg_path = os.path.join(config_path, "{}.cfg".format(serv))
237    with open(cfg_path, 'w') as r:
238        json.dump(json_obj, r, indent=4)
239    return cfg_path
240
241
242def remove_configs(config_path):
243    """
244    清理配置文件目录下的xml和cfg文件
245    :param config_path: 配置文件目录
246    :return:
247    """
248    logger("Clear config path...", "INFO")
249    shutil.rmtree(config_path)
250    os.mkdir(config_path)
251
252
253def split_foundation_services(developer_path, system_info_dict, home_path, hdc_dict):
254    """
255    foundation.xmlXXX.xml文件推送到 /system/profile
256    XXX.cfg文件推送到/etc/init/
257    reboot设备,可以将服务从foundation中拆分出来,成为一个独立服务进程
258    """
259    config_path = os.path.join(developer_path, "localCoverage", "resident_service", "config")
260    remove_configs(config_path)
261
262    device_ip = hdc_dict["device_ip"]
263    hdc_port = hdc_dict["device_port"]
264    device_sn = hdc_dict["device_sn_str"]
265
266    hdc_command(device_ip, hdc_port, device_sn, "file recv /system/profile/foundation.json {}".format(config_path))
267    hdc_command(device_ip, hdc_port, device_sn, "file recv /etc/init/foundation.cfg {}".format(config_path))
268
269    if os.path.exists(os.path.join(config_path, "foundation.json")):
270        origin_json = os.path.join(config_path, "foundation_origin.json")
271        os.rename(os.path.join(config_path, "foundation.json"), origin_json)
272    else:
273        logger("{} not exist, Cannot modify.".format(os.path.join(config_path, "foundation.json")), "ERROR")
274        return
275
276    if os.path.exists(os.path.join(config_path, "foundation.cfg")):
277        origin_cfg = os.path.join(config_path, "foundation_origin.cfg")
278        os.rename(os.path.join(config_path, "foundation.cfg"), origin_cfg)
279    else:
280        logger("{} not exist, Cannot modify.".format(os.path.join(config_path, "foundation.cfg")), "ERROR")
281        return
282
283    foundation_process_list = FoundationServer.lib_dict.keys()
284
285    # 推送配置文件
286    for _, value_list in system_info_dict.items():
287        for process_str in value_list:
288            if process_str in foundation_process_list:
289                foundation_json = modify_foundation_json(process_str, config_path, origin_json)
290                service_json = create_service_json(process_str, config_path, origin_json)
291                service_cfg = create_service_cfg(process_str, config_path, origin_cfg)
292
293                hdc_command(device_ip, hdc_port, device_sn, "shell rm -rf {}".format(home_path))
294                hdc_command(device_ip, hdc_port, device_sn, "file send {} /system/profile/".format(foundation_json))
295                hdc_command(device_ip, hdc_port, device_sn, "file send {} /system/profile/".format(service_json))
296                hdc_command(device_ip, hdc_port, device_sn, "file send {} /etc/init/".format(service_cfg))
297
298    return
299
300
301def modify_cfg_xml_file(developer_path, device_ip, device_sn_list,
302                        system_info_dict, home_path, device_port):
303    if device_ip and len(device_sn_list) >= 1:
304        for device_sn_str in device_sn_list:
305            hdc_str = "hdc -s %s:%s -t %s" % (device_ip, device_port, device_sn_str)
306            hdc_dict = {"device_ip": device_ip, "device_port": device_port, "device_sn_str": device_sn_str}
307            modify_init_file(developer_path, hdc_str)
308            modify_faultloggerd_file(
309                developer_path, hdc_str)
310            # 推送服务对应的配置文件
311            split_foundation_services(developer_path, system_info_dict, home_path, hdc_dict)
312            logger("{} shell reboot".format(hdc_str), "INFO")
313            coverage_command("%s shell reboot > /dev/null 2>&1" % hdc_str)
314            while True:
315                after_sn_list = get_sn_list("hdc -s %s:%s list targets" % (device_ip, device_port))
316                time.sleep(10)
317                if device_sn_str in after_sn_list:
318                    break
319            coverage_command("%s shell getenforce" % hdc_str)
320    else:
321        logger("user_config.xml device ip not config", "ERROR")
322
323
324if __name__ == '__main__':
325    command_args = sys.argv[1]
326    command_str = command_args.split("command_str=")[1].replace(",", " ")
327    current_path = os.getcwd()
328    _init_sys_config()
329    from localCoverage.utils import coverage_command, \
330        logger, hdc_command, FoundationServer
331
332    root_path = current_path.split("/test/testfwk/developer_test")[0]
333    developer_test_path = os.path.join(root_path, "test/testfwk/developer_test")
334    home_paths = '/'.join(root_path.split("/")[:3])
335
336    # 获取user_config中的device ip
337    ip, port, sn = get_config_ip(os.path.join(developer_test_path, "config/user_config.xml"))
338    if not port:
339        port = "8710"
340    sn_list = []
341    if sn:
342        sn_list.extend(sn.replace(" ", "").split(";"))
343    else:
344        sn_list = get_sn_list("hdc -s %s:%s list targets" % (ip, port))
345
346    # 获取子系统部件与服务的关系
347    system_dict, _, _ = get_server_dict(command_str)
348
349    # 修改设备init.cfg, faultloggerd.cfg等文件
350    modify_cfg_xml_file(developer_test_path, ip, sn_list,
351                        system_dict, home_paths, port)
352