diff --git a/build.sh b/build.sh index bd114779fca5fd7648dcf4e9b8522808d2b0f119..edd02abf86b6f63fdce39ac21ae3b341069e4e74 100644 --- a/build.sh +++ b/build.sh @@ -3,21 +3,21 @@ # Copyright: Copyright (c) Huawei Technologies Co., Ltd. All rights reserved. set -e -current_dir=$(cd $(dirname $0); pwd) +current_dir=$(cd $(dirname "$0"); pwd) -cd ${current_dir} -cp ${current_dir}/tools/download_dependency/src/* ${current_dir}/tools/install_dependency/src/ +tag="v0.1" -cd ${current_dir}/tools/download_dependency -pyinstaller -F ./src/download.py -p ./ +sh "${current_dir}"/tools/distribute/build_devkit_distribute.sh -cd ${current_dir}/tools/install_dependency -pyinstaller -F ./src/devkitpipeline.py -p ./ --add-data "${current_dir}/component:component" +sh "${current_dir}"/tools/download_dependency/build_download.sh -cp ${current_dir}/tools/install_dependency/config/machine.yaml ${current_dir}/tools/install_dependency/dist/machine.yaml -cp ${current_dir}/tools/download_dependency/dist/download ${current_dir}/tools/install_dependency/dist/ +sh "${current_dir}"/tools/install_dependency/build_install.sh -mkdir -p ${current_dir}/tools/install_dependency/v1.0/tools/ -cp -rf ${current_dir}/tools/install_dependency/dist/ ${current_dir}/tools/install_dependency/v1.0/tools/linux -cd ${current_dir}/tools/install_dependency/v1.0/ -tar -zcvf v1.0.tar.gz tools +cd "${current_dir}"/build + +mkdir -p "${current_dir}"/build/dekvit-pipeline-${tag}/linux +cp -rf "${current_dir}"/build/install/dist/* "${current_dir}"/build/dekvit-pipeline-${tag}/linux +cp -rf "${current_dir}"/build/download/dist/* "${current_dir}"/build/dekvit-pipeline-${tag}/linux +cp -rf "${current_dir}"/build/distribute/devkit_distribute "${current_dir}"/build/dekvit-pipeline-${tag}/linux + +tar -zcvf dekvit-pipeline-${tag}.tar.gz dekvit-pipeline-${tag} diff --git "a/document/\344\276\235\350\265\226/requirement.md" "b/document/\344\276\235\350\265\226/requirement.md" index 7349684eb4fd81f797fce43c7b083a3fbb42f140..3ee266aa68e9ff3368011a4c3110bd05ca566e77 100644 --- "a/document/\344\276\235\350\265\226/requirement.md" +++ "b/document/\344\276\235\350\265\226/requirement.md" @@ -3,4 +3,6 @@ pyinstaller paramiko PyYAML wget -timeout_decorator \ No newline at end of file +timeout_decorator +urllib3 +requests \ No newline at end of file diff --git a/tools/common/devkit_utils/__init__.py b/tools/common/devkit_utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/common/devkit_utils/devkit_client.py b/tools/common/devkit_utils/devkit_client.py new file mode 100644 index 0000000000000000000000000000000000000000..ebcef7cfb1f976992f0d209c1fd8387e88fe83c5 --- /dev/null +++ b/tools/common/devkit_utils/devkit_client.py @@ -0,0 +1,91 @@ +import logging +import os.path + +import requests +from urllib3 import encode_multipart_formdata + + +class DevKitClient: + def __init__(self, ip, port, username, password): + self.ip = ip + self.port = port + self.username = username + self.password = password + self.user_id = "" + self.token = "" + self.header = dict() + self.login() + + def __del__(self): + self.logout() + + def __str__(self): + return f"{self.ip}, {self.port}, {self.username}, {self.password}, {self.user_id}, {self.token}, f{self.header}" + + def login(self): + url = f"https://{self.ip}:{self.port}/framework/api/v1.0/users/session/" + body = dict({"username": self.username, "password": self.password}) + try: + ret = requests.post(url=url, json=body, verify=False, timeout=10) + user_dict = ret.json() + self.token = ret.headers["token"] + self.user_id = user_dict["data"]["id"] + self.header = dict({ + "Authorization": self.token, + "Content-Type": "application/json", + "Accept-Language": "zh-cn" + }) + except requests.exceptions.ReadTimeout or requests.exceptions.ConnectionError as ex: + logging.exception(ex) + raise ex + + def logout(self): + url = f"https://{self.ip}:{self.port}/framework/api/v1.0/users/session/{self.user_id}/" + try: + requests.delete(url, headers=self.header, verify=False) + except Exception as ex: + logging.exception(ex) + pass + + def upload_report(self, file_path): + try: + data = dict({"file": (os.path.basename(file_path), open(file_path, "rb").read())}) + except OSError as e: + logging.exception(e) + raise + encoded_data = encode_multipart_formdata(data) + _header = self.header.copy() + _header.update({"Content-Type": encoded_data[1]}) + url = f"https://{self.ip}:{self.port}/plugin/api/v1.0/java_perf/api/records/actions/upload/" + return requests.post(url=url, headers=_header, data=encoded_data[0], verify=False) + + def get_record_list(self): + url = f"https://{self.ip}:{self.port}/plugin/api/v1.0/java_perf/api/records/user/" + data = {"userId": self.user_id} + return requests.post(url=url, json=data, headers=self.header, verify=False) + + def delete_report(self, task_id): + url = f"https://{self.ip}:{self.port}/plugin/api/v1.0/java_perf/api/records/{task_id}/" + requests.delete(url=url, headers=self.header, verify=False) + + def upload_report_by_force(self, file_path): + ret = self.upload_report(file_path) + if ret.status_code == requests.codes.ok: + return + if ret.json().get("code", "") == "JavaPerf.Upload.Recording.RecordingReachLimit": + records = self.get_record_list() + task_id, create_time = "", "999999999999999999999999999999" + for o in records.json().get("members", []): + if float(o["createTime"]) < float(create_time): + task_id, create_time = o["id"], o["createTime"] + self.delete_report(task_id) + self.upload_report(file_path) + + +if __name__ == "__main__": + try: + d = DevKitClient("172.39.173.2", "8086", "devadmin", "Huawei12#$") + d.upload_report_by_force("/home/panlonglong/Downloads/Main(136462)") + d.logout() + except Exception as e: + print(str(e)) diff --git a/tools/common/devkit_utils/error_coce.py b/tools/common/devkit_utils/error_coce.py new file mode 100644 index 0000000000000000000000000000000000000000..032cc9cc878a60d05223edcf6b9019d6155b7d97 --- /dev/null +++ b/tools/common/devkit_utils/error_coce.py @@ -0,0 +1,17 @@ +import enum +import typing + + +class ErrorCodeEnum(enum.Enum): + SUCCESS = 0 + FAILURE = -1 + FINISHED = 1 + NOT_FOUND_JCMD = 10001 + NOT_FOUND_APPS = 10002 + + +class ErrorCodeMsg: + LANGUAGE_EN: typing.Dict[ErrorCodeEnum, str] = { + ErrorCodeEnum.NOT_FOUND_JCMD: "the jcmd command was not found on server {}", + ErrorCodeEnum.NOT_FOUND_APPS: "the application called {} was not found on server {}", + } diff --git a/tools/common/devkit_utils/file_utils.py b/tools/common/devkit_utils/file_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..a70cde7d0a60e1c9553de601d8846be8220bf0bf --- /dev/null +++ b/tools/common/devkit_utils/file_utils.py @@ -0,0 +1,30 @@ +import os + + +def create_dir(target, mode=0o700): + if os.path.exists(target): + if os.path.isdir(target): + return True + else: + return False + old_mask = os.umask(0o000) + os.makedirs(target, mode=mode) + os.umask(old_mask) + return True + + +def clear_dir(target): + """ + 删除目录下,所有文件,保留目录 + """ + if not os.path.exists(target): + return + for file in os.listdir(target): + sub = os.path.join(target, file) + if os.path.isfile(sub): + os.remove(sub) + if os.path.islink(sub): + os.unlink(sub) + if os.path.isdir(sub): + clear_dir(sub) + os.rmdir(sub) diff --git a/tools/common/devkit_utils/log_config.py b/tools/common/devkit_utils/log_config.py new file mode 100644 index 0000000000000000000000000000000000000000..e2a23022441a372167920756f7e1342c02960c58 --- /dev/null +++ b/tools/common/devkit_utils/log_config.py @@ -0,0 +1,17 @@ +import logging.config +import os + +from devkit_utils import file_utils +from devkit_utils import shell_tools + + +def config_log_ini(root_path, log_name): + log_template = os.path.join(root_path, "config/log.ini.template") + log_config = os.path.join(root_path, "config/log.ini") + log_path = os.path.join(root_path, "log") + log_replace_path = log_path.replace("/", "\\/") + shell_tools.exec_shell("cp {} {}".format(log_template, log_config), is_shell=True) + shell_tools.exec_shell("sed -i \"s/LOG_PATH/{}/g\" {} ".format(log_replace_path, log_config), is_shell=True) + shell_tools.exec_shell("sed -i \'s/LOG_NAME/{}/g\' {} ".format(log_name, log_config), is_shell=True) + file_utils.create_dir(log_path) + logging.config.fileConfig(os.path.join(root_path, "config/log.ini")) diff --git a/tools/common/devkit_utils/pyinstaller_utils.py b/tools/common/devkit_utils/pyinstaller_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..604ee668fbe447ed25d55bfebe1f953a6dceabaf --- /dev/null +++ b/tools/common/devkit_utils/pyinstaller_utils.py @@ -0,0 +1,22 @@ +import os.path +import sys + + +def check_is_running_in_pyinstaller_bundle(): + """ + 判断是否在pyinstaller + """ + if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): + return True + else: + return False + + +def obtain_root_path(root_path): + """ + 获取rootpath,当在pyinstaller中时,为父母录,否认为参入的参数 + """ + if check_is_running_in_pyinstaller_bundle(): + return os.path.dirname(os.path.dirname(sys.executable)) + else: + return root_path diff --git a/tools/common/devkit_utils/shell_tools.py b/tools/common/devkit_utils/shell_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..a7f7d0e5cfa60c6e585709e179cb15fb5638c803 --- /dev/null +++ b/tools/common/devkit_utils/shell_tools.py @@ -0,0 +1,40 @@ +import logging +import shlex +import subprocess +import typing + + +class ExecutionOutcome: + def __init__(self, return_code=0, out=None, err=None): + self.return_code: int = return_code + self.out: typing.Optional[str] = out + self.err: typing.Optional[str] = err + + def __str__(self): + return "code:%s\n out:%s\n err:%s\n" % (self.return_code, self.out, self.err) + + +def exec_shell(command: str, is_shell=False, timeout=30) -> ExecutionOutcome: + """ + 执行命令,返回执行结果 + """ + try: + if is_shell: + child = subprocess.Popen(command, close_fds=True, stdout=subprocess.PIPE, stdin=None, + stderr=subprocess.PIPE, encoding="utf-8", universal_newlines=True, shell=is_shell) + + else: + child = subprocess.Popen(shlex.split(command), close_fds=True, stdout=subprocess.PIPE, stdin=None, + stderr=subprocess.PIPE, encoding="utf-8", universal_newlines=True) + + except Exception as ex: + logging.error(ex, exc_info=True) + raise ex + else: + try: + out, err = child.communicate(timeout=timeout) + except Exception as exception: + logging.error(exception, exc_info=True) + raise exception + else: + return ExecutionOutcome(child.returncode, out, err) diff --git a/tools/common/devkit_utils/transport_utils.py b/tools/common/devkit_utils/transport_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..c3918e76ed68ef61ce4cf9125cad1a8ffc7e948a --- /dev/null +++ b/tools/common/devkit_utils/transport_utils.py @@ -0,0 +1,130 @@ +import logging +import os +import pathlib +from io import StringIO + +import paramiko + + +class TransportException(Exception): + def __init__(self, *args, **kwargs): + super(TransportException, self).__init__(args, kwargs) + + +class SSHClientFactory: + + def __init__(self, ip, user, password=None, port=22, pkey_file=None, pkey_content=None, pkey_password=None): + self.pkey_file = pkey_file + self.pkey_content = pkey_content + self.pkey_password = pkey_password + self.password = password + self.ip = ip + self.port = port + self.user = user + + def create_ssh_client(self): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + if self.password: + # 使用密码进行链接 + ssh.connect(hostname=self.ip, port=22, username=self.user, password=self.password) + elif self.pkey_file or self.pkey_content: + # 使用指定的免密文件路径或者免密内容进行链接(内容支持加密) + pkey = self.__pkey() + ssh.connect(hostname=self.ip, port=22, username=self.user, pkey=pkey) + else: + # 使用.ssh 下的私钥尝试链接 + try_result = False + for pkey_path in self.__get_home_pkey_path(): + try: + pkey = self.__pkey(pkey_path) + ssh.connect(hostname=self.ip, port=22, username=self.user, pkey=pkey) + try_result = True + break + except Exception as err: + logging.exception(err) + if not try_result: + raise TransportException("The passwordless configuration is incorrect") + except Exception as ex: + logging.exception(ex) + raise TransportException() + return ssh + + @staticmethod + def __get_home_pkey_path(): + pkey_files = list() + base = str(pathlib.Path.home()) + "/.ssh" + for filename in os.listdir(base): + filepath = os.path.join(base, filename) + if os.path.isfile(filepath) and filepath.startswith("id_") and not filepath.endswith("pub"): + pkey_files.append(filepath) + return pkey_files + + def __choose_pkey(self, pkey_path=None): + if pkey_path: + return paramiko.RSAKey.from_private_key_file(pkey_path) + if self.pkey_file: + return paramiko.RSAKey.from_private_key_file(self.pkey_file, password=self.pkey_password) + if self.pkey_content: + return paramiko.RSAKey.from_private_key(StringIO(self.pkey_content), password=self.pkey_password) + raise TransportException() + + def __pkey(self, pkey_path=None): + try: + # 指定本地的RSA私钥文件。如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 + pkey = self.__choose_pkey(pkey_path) + except (IOError,) as e: + logging.error(f"Pkey file not exists. {str(e)}") + raise TransportException() + except (paramiko.ssh_exception.PasswordRequiredException, paramiko.ssh_exception.AuthenticationException) as e: + logging.warning(f"Pkey password is required. {str(e)}") + raise TransportException(str(e)) + except Exception as e: + logging.error(f"Connect remote {self.ip} failed because of wrong pkey. {str(e)}") + raise TransportException() + else: + return pkey + + +if __name__ == "__main__": + factory = SSHClientFactory("127.0.0.1", "root", pkey_content="""-----BEGIN OPENSSH PRIVATE KEY----- +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 +Q0ktTVQBAgMEBQYH +-----END OPENSSH PRIVATE KEY-----""") + factory.create_ssh_client() diff --git a/tools/distribute/build_devkit_distribute.sh b/tools/distribute/build_devkit_distribute.sh new file mode 100644 index 0000000000000000000000000000000000000000..6f7e05ec646ff6aec345189de233398046ccddf4 --- /dev/null +++ b/tools/distribute/build_devkit_distribute.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# SourceCode build script +# Copyright: Copyright (c) Huawei Technologies Co., Ltd. All rights reserved. + +set -e +current_dir=$(cd $(dirname "$0"); pwd) +project_dir=$(realpath "${current_dir}/../..") +umask 077 + +build_dir=${project_dir}/build/distribute +rm -rf "${build_dir}" +mkdir -p "${build_dir}" + +cd "${build_dir}" + +pyinstaller -F "${current_dir}"/devkit_pipeline_agent/bin/flight_records_sample.py --runtime-tmpdir . \ + -p "${project_dir}"/tools/common + +mkdir -p devkit_pipeline_agent/bin +mkdir -p devkit_pipeline_agent/data +mkdir -p devkit_pipeline_agent/log + +cp "${build_dir}"/dist/flight_records_sample devkit_pipeline_agent/bin +cp "${current_dir}"/devkit_pipeline_agent/script/devkit_agent_start.sh devkit_pipeline_agent/bin +cp -rf "${current_dir}"/devkit_pipeline_agent/config devkit_pipeline_agent + +tar -czf devkit_pipeline_agent.tar.gz devkit_pipeline_agent + + +pyinstaller -F "${current_dir}"/devkit_distribute/bin/entrance.py --runtime-tmpdir . \ + -p "${project_dir}"/tools/common + +mkdir -p devkit_distribute/bin +mkdir -p devkit_distribute/data +mkdir -p devkit_distribute/log + +cp "${build_dir}"/dist/entrance devkit_distribute/bin +cp "${current_dir}"/devkit_distribute/script/devkit_pipeline_start.sh devkit_distribute/bin +cp -rf "${current_dir}"/devkit_distribute/config devkit_distribute +cp devkit_pipeline_agent.tar.gz devkit_distribute/config diff --git a/tools/distribute/devkit_distribute/bin/entrance.py b/tools/distribute/devkit_distribute/bin/entrance.py new file mode 100644 index 0000000000000000000000000000000000000000..b29ab2d6274dc6854bcce20124da3682d7e7dc21 --- /dev/null +++ b/tools/distribute/devkit_distribute/bin/entrance.py @@ -0,0 +1,192 @@ +import argparse +import datetime +import logging +import os +import uuid + +from devkit_utils import file_utils +from devkit_utils.devkit_client import DevKitClient +from devkit_utils.error_coce import ErrorCodeEnum, ErrorCodeMsg +from devkit_utils.log_config import config_log_ini +from devkit_utils.pyinstaller_utils import obtain_root_path +from devkit_utils.transport_utils import SSHClientFactory + +ROOT_PATH = os.path.dirname(os.path.dirname(__file__)) + + +class Distributor: + def __init__(self, args): + self.ips_list = args.ips_list.split(",") + self.port = args.port + self.user = args.user + self.password = args.password + self.pkey_file = args.pkey_file + self.pkey_content = args.pkey_content + self.pkey_password = args.pkey_password + self.duration = args.duration + self.root_path = args.root_path + self.apps = args.applications + self.data_path = os.path.join(self.root_path, "data") + self.log_path = os.path.join(self.root_path, "log") + self.devkit_ip = args.devkit_ip + self.devkit_port = args.devkit_port + self.devkit_user = args.devkit_user + self.devkit_password = args.devkit_password + file_utils.create_dir(self.data_path) + + def distribute(self): + task_id = str(uuid.uuid4()) + # 分发采集任务 + self.distribute_to_sample_task(task_id) + # 获取jfr文件,删除任务文件 + local_jfrs = list() + self.obtain_jfrs(local_jfrs, task_id) + # 发送至 Devkit + client = DevKitClient(self.devkit_ip, self.devkit_port, self.devkit_user, self.devkit_password) + for jfr in local_jfrs: + client.upload_report(jfr) + client.logout() + # 清空本地jfr文件 + file_utils.clear_dir(self.data_path) + + def obtain_jfrs(self, local_jfrs, task_id): + # 顺序获取 + for ip in self.ips_list: + factory = SSHClientFactory(ip=ip, user=self.user, port=self.port, password=self.password, + pkey_file=self.pkey_file, pkey_content=self.pkey_content, + pkey_password=self.pkey_password) + ssh_client = factory.create_ssh_client() + try: + logging.info("Wait for the server[%s] to finish uploading the jfr file", ip) + self.__blocking_util_upload_success(ssh_client, + f"{task_id}/devkit_pipeline_agent/config/complete_the_upload.ini", + ip) + + logging.info("obtain the jfr file name from ip:%s", ip) + stdin, stdout, stderr = ssh_client.exec_command( + f"cat {task_id}/devkit_pipeline_agent/config/upload_sample.ini") + jfr_paths_all = stdout.read().decode("utf-8") + jfr_paths = jfr_paths_all.split(os.linesep) if jfr_paths_all else [] + logging.info("jfr path:%s", jfr_paths) + self.__close_pipeline(stdin, stdout, stderr) + sftp_client = ssh_client.open_sftp() + log_ip_name = ip.replace(".", "_") + sftp_client.get(f"{task_id}/devkit_pipeline_agent/log/devkit_pipeline_agent.log", + f"{self.log_path}/devkit_pipeline_agent_{log_ip_name}.log") + logging.info("download the jfr file from ip:%s", ip) + if not jfr_paths: + raise Exception(f"The jfr file {self.apps} cannot be generated") + for jfr_path in jfr_paths: + local_path = os.path.join(self.data_path, os.path.basename(jfr_path)) + sftp_client.get(jfr_path, local_path) + local_jfrs.append(local_path) + sftp_client.close() + logging.info("the server[%s] has finish uploading the jfr file or has timeout 6000", ip) + except Exception as ex: + logging.exception(ex) + finally: + self.__delete_agent(ssh_client, task_id) + ssh_client.close() + + def distribute_to_sample_task(self, task_id): + # 分发采集任务 + for ip in self.ips_list: + factory = SSHClientFactory(ip=ip, user=self.user, port=self.port, password=self.password, + pkey_file=self.pkey_file, pkey_content=self.pkey_content, + pkey_password=self.pkey_password) + ssh_client = factory.create_ssh_client() + try: + logging.info("ip:%s create %s directory ", ip, task_id) + stdin, stdout, stderr = ssh_client.exec_command(f"mkdir {task_id}") + self.__close_pipeline(stdin, stdout, stderr) + agent_package = os.path.join(self.root_path, "config/devkit_pipeline_agent.tar.gz") + logging.info("ip:%s upload devkit_pipeline_agent.tar.gz", ip) + sftp_client = ssh_client.open_sftp() + sftp_client.put(agent_package, f"{task_id}/devkit_pipeline_agent.tar.gz") + sftp_client.close() + logging.info("ip:%s unpack devkit_pipeline_agent.tar.gz", ip) + stdin, stdout, stderr = ssh_client.exec_command( + f"cd {task_id} && tar -xvzf devkit_pipeline_agent.tar.gz --no-same-owner") + logging.info("upack tar.gz %s", stderr.readlines()) + self.__close_pipeline(stdin, stdout, stderr) + logging.info("ip:%s start devkit pipeline agent", ip) + stdin, stdout, stderr = ssh_client.exec_command( + f"sh {task_id}/devkit_pipeline_agent/bin/devkit_agent_start.sh " + f"-a {self.apps} -d {self.duration} -t {task_id}") + logging.info("start the sampling process on server %s:%s", ip, stderr.readlines()) + self.__close_pipeline(stdin, stdout, stderr) + logging.info("ip:%s The devkit pipeline agent was successfully launched", ip) + except Exception as ex: + self.__delete_agent(ssh_client, task_id) + raise ex + finally: + ssh_client.close() + + @staticmethod + def __delete_agent(ssh_client, task_id): + ssh_client.exec_command(f"rm -rf {task_id}") + ssh_client.exec_command(f"rm -rf /tmp/{task_id}") + + def __blocking_util_upload_success(self, ssh_client, transport_file, ip): + before = datetime.datetime.now() + while (datetime.datetime.now() - before).seconds < 6000 + self.duration: + stdin, stdout, stderr = ssh_client.exec_command(f"cat {transport_file}") + file_content = stdout.read().decode("utf-8").strip() + if file_content == str(ErrorCodeEnum.FINISHED): + return True + elif file_content == str(ErrorCodeEnum.NOT_FOUND_JCMD): + raise Exception(ErrorCodeMsg.LANGUAGE_EN.get(ErrorCodeEnum.NOT_FOUND_JCMD).format(ip)) + elif file_content == str(ErrorCodeEnum.NOT_FOUND_APPS): + raise Exception(ErrorCodeMsg.LANGUAGE_EN.get(ErrorCodeEnum.NOT_FOUND_APPS).format(self.apps, ip)) + return False + + @staticmethod + def __close_pipeline(stdin, stdout, stderr): + stdin.close() + stdout.close() + stderr.close() + + +def main(): + parser = argparse.ArgumentParser(description="Capture the flight records of the target program") + parser.add_argument("-i", "--ips", required=True, dest="ips_list", + help="the machine ips on which the java application is running ") + parser.add_argument("-u", "--user", required=True, dest="user", default="root", + help="the user password of the ips") + parser.add_argument("-P", "--port", dest="port", type=int, default=22, + help="the ssh port of the ips") + parser.add_argument("-p", "--password", dest="password", + help="the user password of the ips") + parser.add_argument("-f", "--pkey-file", dest="pkey_file", + help="the file path of the private key") + parser.add_argument("-c", "--pkey-content", dest="pkey_content", + help="the content of the private key") + parser.add_argument("-w", "--pkey-password", dest="pkey_password", + help="the private key password") + parser.add_argument("--devkit-ip", dest="devkit_ip", required=True, + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("--devkit-port", dest="devkit_port", default="8086", + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("--devkit-user", dest="devkit_user", default="devadmin", + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("--devkit-password", dest="devkit_password", default="admin100", + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("-a", "--app", required=True, dest="applications", + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("-d", "--duration", required=True, dest="duration", type=int, + help="the time of the sample") + parser.set_defaults(root_path=obtain_root_path(ROOT_PATH)) + args = parser.parse_args() + config_log_ini(args.root_path, "devkit_distribute") + logging.info("devkit_distribute start") + logging.info(args) + distributor = Distributor(args) + distributor.distribute() + + +if __name__ == "__main__": + try: + main() + except Exception as err: + logging.exception(err) + raise err diff --git a/tools/distribute/devkit_distribute/bin/template.py b/tools/distribute/devkit_distribute/bin/template.py new file mode 100644 index 0000000000000000000000000000000000000000..23f1915f233edb889cdb34167b3e1e6a202bf6cc --- /dev/null +++ b/tools/distribute/devkit_distribute/bin/template.py @@ -0,0 +1,158 @@ +performance_report = """ + + + + + + Main Page + + + +
+ Icn +

Kunpeng DevKit

+ +
+ +
+

DevKit Performance Test Info

+ + + + +
+
+ + + + + + + +""" \ No newline at end of file diff --git a/tools/distribute/devkit_distribute/config/log.ini.template b/tools/distribute/devkit_distribute/config/log.ini.template new file mode 100644 index 0000000000000000000000000000000000000000..c559a311f7e0b66e84d3eeb965a34212ea8afd9d --- /dev/null +++ b/tools/distribute/devkit_distribute/config/log.ini.template @@ -0,0 +1,30 @@ +[loggers] # loggers 对象列表 +keys=root + + +[handlers] # handlers 对象列表 +keys=consoleHandler,fileHandler + +[formatters] # formatters 对象列表 +keys=fmt + +[logger_root]# 配置 logger_root :设置日志级别、输出位置(控制台和文件) +level=INFO +handlers=consoleHandler,fileHandler + + +[handler_consoleHandler] # consoleHandler 控制器输出方向、级别、输出格式、参数 +class = StreamHandler +level = INFO +formatter = fmt +args = (sys.stdout,) + +[handler_fileHandler]# fileHandler 控制器输出方向、级别、输出格式、参数 +class = FileHandler +level = INFO +formatter = fmt +args = ("LOG_PATH/LOG_NAME.log", "a") + +[formatter_fmt] +format=[%(asctime)s] [%(levelname)s] [processID:%(process)d][%(threadName)s] [%(module)s:%(funcName)s:%(lineno)d] %(message)s +datefmt=%Y-%m-%d %H:%M:%S \ No newline at end of file diff --git a/tools/distribute/devkit_distribute/script/devkit_pipeline_start.sh b/tools/distribute/devkit_distribute/script/devkit_pipeline_start.sh new file mode 100644 index 0000000000000000000000000000000000000000..880e0d83b6fb1632f5cd78f06ee7b5a0d44e3bf4 --- /dev/null +++ b/tools/distribute/devkit_distribute/script/devkit_pipeline_start.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# shellcheck disable=SC2164 +current_path=$(cd $(dirname "$0"); pwd) + +nohup "${current_path}"/entrance "$@" >/dev/null 2>&1 & + +echo "start devkit success" \ No newline at end of file diff --git a/tools/distribute/devkit_pipeline_agent/bin/flight_records_sample.py b/tools/distribute/devkit_pipeline_agent/bin/flight_records_sample.py new file mode 100644 index 0000000000000000000000000000000000000000..0d892b3e8a8145fc09fb4dca595c052c6c6590d8 --- /dev/null +++ b/tools/distribute/devkit_pipeline_agent/bin/flight_records_sample.py @@ -0,0 +1,163 @@ +import argparse +import datetime +import logging.config +import os.path +import shutil +import time + +from devkit_utils import shell_tools, file_utils +from devkit_utils.error_coce import ErrorCodeEnum +from devkit_utils.log_config import config_log_ini +from devkit_utils.pyinstaller_utils import obtain_root_path + +ROOT_PATH = os.path.dirname(os.path.dirname(__file__)) + + +class TargetProcess: + def __init__(self, pid, name): + self.pid = pid + self.name = name + self.jfr_name = None + + +class FlightRecordsFactory: + RECORD_NAME = "devkit_recorder_per_day" + STOP_SAMPLE = "1" + + def __init__(self, apps, duration, root_path, task_id): + self.apps = apps + self.duration = duration + self.root_path = root_path + self.pids: list[TargetProcess] = list() + self.pids_to_start_recording = list() + self.pids_to_stop_recording = list() + self.jfr_paths: list[str] = [] + self.return_code = ErrorCodeEnum.FINISHED + self.dir_to_storage_jfr = os.path.join(root_path, "data") + self.tmp_dir = os.path.join("/tmp", task_id) + self.tmp_data_dir = os.path.join(self.tmp_dir, "data") + self.tmp_config_dir = os.path.join(self.tmp_dir, "config") + self.temporary_settings_path = os.path.join(self.tmp_config_dir, "settings.jfc") + self.settings_path = os.path.join(root_path, "config/settings.jfc") + self.response_file = os.path.join(root_path, "config/complete_the_upload.ini") + self.now_date = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + file_utils.create_dir(self.dir_to_storage_jfr) + + def start_sample(self): + try: + logging.info("start_sample") + self.__create_tmp() + self.__init_pids() + if len(self.pids) == 0: + self.return_code = ErrorCodeEnum.NOT_FOUND_APPS + elif not self.__check_jcmd(): + self.return_code = ErrorCodeEnum.NOT_FOUND_JCMD + logging.info("start_recorder") + self.__start_recorder() + if self.jfr_paths: + time.sleep(self.duration) + before = datetime.datetime.now() + # 停止采集 + logging.info("stop recorder") + while not self.__stop_recorder() and (datetime.datetime.now() - before).seconds < 30: + time.sleep(1) + else: + logging.exception(f"The target application {self.apps} cannot be found or cannot be collected") + finally: + shell_tools.exec_shell(f"echo {self.return_code} >{self.response_file}", is_shell=True) + logging.info("the current agent has been executed") + + def __create_tmp(self): + file_utils.create_dir(self.tmp_data_dir, mode=0o777) + file_utils.create_dir(self.tmp_config_dir, mode=0o777) + shutil.copy(self.settings_path, self.temporary_settings_path, follow_symlinks=False) + os.chmod(self.temporary_settings_path, mode=0o644) + + def __init_pids(self): + for app in self.apps.split(","): + commander_to_view_pid = "ps -ef|grep java|grep -v grep|grep {}|awk '{{print $2}}'".format(app) + outcome = shell_tools.exec_shell(commander_to_view_pid, is_shell=True) + logging.info("app:%s to pid %s", app, outcome) + pids = outcome.out.split() + for pid in pids: + self.pids.append(TargetProcess(pid, app)) + + @staticmethod + def __check_jcmd(): + commander_to_check = "which jcmd" + outcome = shell_tools.exec_shell(commander_to_check, is_shell=True) + logging.info("check jcmd :%s", outcome) + if outcome.return_code == 0: + return True + else: + return False + + def __start_recorder(self): + for target in self.pids: + jfr_path = self.__jfr_name(target.name, target.pid) + command = (f"jcmd {target.pid} JFR.start settings={self.temporary_settings_path} duration={self.duration}s" + f" name={self.RECORD_NAME} filename={jfr_path}") + logging.info(command) + outcome = shell_tools.exec_shell(command, is_shell=True) + logging.info(outcome) + if outcome.return_code == 0: + self.jfr_paths.append(jfr_path) + self.pids_to_start_recording.append(target) + # 移动到data目录下 + with open(file=os.path.join(self.root_path, "config/upload_sample.ini"), mode="w", encoding="utf-8") as file: + file.write(os.linesep.join(self.jfr_paths)) + + def __stop_recorder(self): + for target in self.pids_to_start_recording: + outcome = shell_tools.exec_shell("jcmd {} JFR.check name={}".format(target.pid, self.RECORD_NAME), + is_shell=True) + logging.info(outcome) + if outcome.out.find("Could not find"): + self.pids_to_stop_recording.append(target) + if len(self.pids_to_stop_recording) == len(self.pids_to_start_recording): + return True + else: + self.pids_to_stop_recording.clear() + return False + + def __jfr_name(self, app, pid): + return os.path.join(self.tmp_data_dir, f"{app}_{pid}_{self.now_date}.jfr") + + def __del_dir(self, target): + if not os.path.exists(target): + return + if os.path.isfile(target): + return + for file in os.listdir(target): + sub = os.path.join(target, file) + if os.path.isfile(sub): + os.remove(sub) + if os.path.islink(sub): + os.unlink(sub) + if os.path.isdir(sub): + self.__del_dir(sub) + os.rmdir(sub) + + +def main(): + parser = argparse.ArgumentParser(description="Capture the flight records of the target program") + parser.add_argument("-a", "--app", required=True, dest="applications", + help="the process names that can be multiple, each separated by a comma") + parser.add_argument("-d", "--duration", required=True, dest="duration", type=int, + help="the time of the sample") + parser.add_argument("-t", "--task-id", dest="task_id", default="devkit-pipeline-tmp", + help="the time of the sample") + parser.set_defaults(root_path=obtain_root_path(ROOT_PATH)) + args = parser.parse_args() + config_log_ini(args.root_path, "devkit_pipeline_agent") + logging.info("start") + factory = FlightRecordsFactory(args.applications, args.duration, args.root_path, args.task_id) + factory.start_sample() + + +if __name__ == "__main__": + try: + main() + except Exception as err: + logging.exception(err) + raise err diff --git a/tools/distribute/devkit_pipeline_agent/config/complete_the_upload.ini b/tools/distribute/devkit_pipeline_agent/config/complete_the_upload.ini new file mode 100644 index 0000000000000000000000000000000000000000..c227083464fb9af8955c90d2924774ee50abb547 --- /dev/null +++ b/tools/distribute/devkit_pipeline_agent/config/complete_the_upload.ini @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tools/distribute/devkit_pipeline_agent/config/log.ini.template b/tools/distribute/devkit_pipeline_agent/config/log.ini.template new file mode 100644 index 0000000000000000000000000000000000000000..c559a311f7e0b66e84d3eeb965a34212ea8afd9d --- /dev/null +++ b/tools/distribute/devkit_pipeline_agent/config/log.ini.template @@ -0,0 +1,30 @@ +[loggers] # loggers 对象列表 +keys=root + + +[handlers] # handlers 对象列表 +keys=consoleHandler,fileHandler + +[formatters] # formatters 对象列表 +keys=fmt + +[logger_root]# 配置 logger_root :设置日志级别、输出位置(控制台和文件) +level=INFO +handlers=consoleHandler,fileHandler + + +[handler_consoleHandler] # consoleHandler 控制器输出方向、级别、输出格式、参数 +class = StreamHandler +level = INFO +formatter = fmt +args = (sys.stdout,) + +[handler_fileHandler]# fileHandler 控制器输出方向、级别、输出格式、参数 +class = FileHandler +level = INFO +formatter = fmt +args = ("LOG_PATH/LOG_NAME.log", "a") + +[formatter_fmt] +format=[%(asctime)s] [%(levelname)s] [processID:%(process)d][%(threadName)s] [%(module)s:%(funcName)s:%(lineno)d] %(message)s +datefmt=%Y-%m-%d %H:%M:%S \ No newline at end of file diff --git a/tools/distribute/devkit_pipeline_agent/config/settings.jfc b/tools/distribute/devkit_pipeline_agent/config/settings.jfc new file mode 100644 index 0000000000000000000000000000000000000000..486e80e973874917c2e8ab7e723e53d61cdf1837 --- /dev/null +++ b/tools/distribute/devkit_pipeline_agent/config/settings.jfc @@ -0,0 +1,1245 @@ + + + + + true + + everyChunk + + + + + + true + + 1000 ms + + + + + + true + + everyChunk + + + + + + true + + 1000 ms + + + + + + true + + + + + + true + + + + + + true + + true + + 10 ms + + + + + + true + + true + + 10 ms + + + + + + true + + true + + 10 ms + + + + + + true + + true + + 10 ms + + + + + + true + + true + + 10 ms + + + + + + true + + true + + 0 ms + + + + + + true + + true + + 0 ms + + + + + + true + + true + + 0 ms + + + + + + true + + true + + + + + + false + + true + + 0 ms + + + + + + false + + true + + + + + + false + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + 1 ms + + + + + + true + + 1 ms + + + + + + true + + 0 ms + + + + + + false + + 0 ms + + + + + + false + + 0 ms + + + + + + false + + 0 ms + + + + + + false + + 0 ms + + + + + + false + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + true + + + + + + true + + 1000 ms + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + everyChunk + + + + + + true + + everyChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + false + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + true + + + + + + true + + true + + + + + + true + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + 0 ms + + + + + + false + + 0 ms + + + + + + false + + 0 ms + + + + + + true + + 0 ms + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + false + + true + + + + + + true + + + + + + false + + everyChunk + + + + + + false + + + + + + true + + true + + 0 ns + + + + + + true + + beginChunk + + + + + + true + + 1000 ms + + + + + + true + + 100 ms + + + + + + true + + 10 s + + + + + + true + + + + + + false + + + + + + true + + beginChunk + + + + + + true + + everyChunk + + + + + + true + + 100 ms + + + + + + true + + beginChunk + + + + + + true + + everyChunk + + + + + + true + + + + + + true + + beginChunk + + + + + + true + + beginChunk + + + + + + true + + 10 s + + + + + + true + + 1000 ms + + + + + + true + + 10 s + + + + + + true + + beginChunk + + + + + + true + + endChunk + + + + + + true + + 5 s + + + + + + true + + beginChunk + + + + + + true + + everyChunk + + + + + + true + + true + + + + + + true + + true + + + + + + true + + everyChunk + + + + + + true + + endChunk + + + + + + true + + endChunk + + + + + + true + + true + + 500000 ns + + + + + + true + + true + + 500000 ns + + + + + + true + + true + + 500000 ns + + + + + + true + + true + + 1000000 ns + + + + + + true + + true + + 1000000 ns + + + + + + false + + true + + + + + + true + + true + + + + + + true + + 1000 ms + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + 10 ms + + + + + + true + + 0 ms + + + + + + 10 ms + + true + + + + + + true + + 10 ms + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10 ms + + 10 ms + + 10 ms + + false + + + + diff --git a/tools/distribute/devkit_pipeline_agent/config/upload_sample.ini b/tools/distribute/devkit_pipeline_agent/config/upload_sample.ini new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/distribute/devkit_pipeline_agent/script/devkit_agent_start.sh b/tools/distribute/devkit_pipeline_agent/script/devkit_agent_start.sh new file mode 100644 index 0000000000000000000000000000000000000000..a96d38fc07bc8ec7e2fbf534942377a7d01c6587 --- /dev/null +++ b/tools/distribute/devkit_pipeline_agent/script/devkit_agent_start.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# shellcheck disable=SC2164 +current_path=$(cd $(dirname "$0"); pwd) + +nohup "${current_path}"/flight_records_sample "$@" >/dev/null 2>&1 & +echo "start devkit agent success" \ No newline at end of file diff --git a/tools/download_dependency/build_download.sh b/tools/download_dependency/build_download.sh new file mode 100644 index 0000000000000000000000000000000000000000..6787ad26f5da47172eaf7445812d85da235dc873 --- /dev/null +++ b/tools/download_dependency/build_download.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# SourceCode build script +# Copyright: Copyright (c) Huawei Technologies Co., Ltd. All rights reserved. + +set -e +current_dir=$(cd $(dirname "$0"); pwd) +project_dir=$(dirname $(dirname "${current_dir}")) + +umask 077 + +build_dir=${project_dir}/build/download +rm -rf "${build_dir}" +mkdir -p "${build_dir}" + +cd "${build_dir}" + +pyinstaller -F "${current_dir}"/src/download.py -p "${current_dir}"/src \ No newline at end of file diff --git a/tools/install_dependency/build_install.sh b/tools/install_dependency/build_install.sh new file mode 100644 index 0000000000000000000000000000000000000000..6744cbf9009763508626b26e464114b05c2fa7db --- /dev/null +++ b/tools/install_dependency/build_install.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# SourceCode build script +# Copyright: Copyright (c) Huawei Technologies Co., Ltd. All rights reserved. + +set -e +current_dir=$(cd $(dirname "$0"); pwd) +project_dir=$(dirname $(dirname "${current_dir}")) +umask 077 + +build_dir=${project_dir}/build/install +rm -rf "${build_dir}" +mkdir -p "${build_dir}" + +cd "${build_dir}" + +pyinstaller -F "${current_dir}"/src/devkitpipeline.py -p "${current_dir}/src:${project_dir}/tools/download_dependency/src" \ +--add-data "${project_dir}/component:component" + +cp "${current_dir}"/config/machine.yaml "${build_dir}"/dist/machine.yaml