diff --git a/component/CompatibilityTesting/install.sh b/component/CompatibilityTesting/install.sh index f0cb4b87e7b7bbb1e2fff6e04f4364ccda15b44a..4bfa698639238723c071bc37114a5e28080e39a9 100644 --- a/component/CompatibilityTesting/install.sh +++ b/component/CompatibilityTesting/install.sh @@ -4,7 +4,7 @@ set -e function main (){ - compatibility_test_tar=$1 + compatibility_test_tar=/tmp/devkitdependencies/compatibility_testing.tar.gz echo "Decompress compatibility_testing.tar.gz to ${HOME}/.local" tar --no-same-owner -zxf ${compatibility_test_tar} -C ${HOME}/.local/ echo "Decompress compatibility_testing.tar.gz to ${HOME}/.local finished." diff --git a/component/DevKitWeb/check_install_result.sh b/component/DevKitWeb/check_install_result.sh new file mode 100644 index 0000000000000000000000000000000000000000..c854e0b8883b64c58176ef8c4187798c0ce298d8 --- /dev/null +++ b/component/DevKitWeb/check_install_result.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "true" \ No newline at end of file diff --git a/component/DevKitWeb/install.sh b/component/DevKitWeb/install.sh new file mode 100644 index 0000000000000000000000000000000000000000..c854e0b8883b64c58176ef8c4187798c0ce298d8 --- /dev/null +++ b/component/DevKitWeb/install.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "true" \ No newline at end of file diff --git "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" index 8c02a0402f3fa698817da4412cb80e486b8c01aa..3e133b8f7228f2567bbe34ea129cfb1fcde6678c 100644 --- "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" +++ "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" @@ -4,9 +4,21 @@ ------ -测试平台使用的是lkp test 工具,以下均已lkp test描述测试平台 +测试平台使用的是lkp test 工具,以下均已lkp test描述测试平台] -## 一. 安装指导 +## 一. 云测工具介绍 + +lkp test是运行云测工具描述验证应用在鲲鹏服务器上的运行情况的必要依赖 + +云测工具是用来运行兼容性测试和可靠性测试的应用 + +| 兼容性测试 | 通过待测试应用软件在鲲鹏环境启动前后资源波动异常检测、验证应用软件启动和停止,自动检测应用软件在鲲鹏平台上的可运行性、兼容性问题。 | +| ----- | ---------------------------------------------------------------------- | +| 可靠性测试 | 通过待测试应用软件在稳定运行期间的系统资源内存的波动异常检测、在异常终止测试场景检测应用运行,自动评估应用软件在鲲鹏平台上的稳定性和可靠性。 | + + + +## 二. 安装指导 可以使用一键部署工具去部署,如果只想单独部署测试平台可以按照以下操作(请用有root权限的用户去安装) @@ -60,7 +72,7 @@ lkp install 直接解压缩compatibility_testing.tar.gz到${HOME}/.local就行 -## 二. 添加项目至lkp tests测试平台 +## 三. 添加项目至lkp tests测试平台(云测工具已完成添加,无需再次添加,以下仅用来介绍如何再lkp tests里面添加项目) ### (1) 极简版项目添加,示例-云测工具(compatibility-test) @@ -218,7 +230,7 @@ lkp split programs/compatibility-test/jobs/compatibility-test.yaml ln -s xxx/lkp-tests/programs/compatibility-test/run xxx/lkp-tests/tests/compatibility-test ``` -## 三、 云测工具 +## 四、 云测工具 要运行云测平台需要配置参数,在安装目录${HOME}/.local/compatibility_testing/Chinese/compatibility_testing.conf @@ -273,7 +285,7 @@ hpc_certificate= binary_file= ``` -## 四、gitlab Pipeline 中集成lkp test (以云测工具(compatibility-test)为示例) +## 五、gitlab Pipeline 中集成lkp test (以云测工具(compatibility-test)为示例) 请确保运行的用户有root权限 @@ -313,7 +325,7 @@ build-job: # This job runs in the build stage, which runs first. ![创建Pipeline任务03](./images/gitlab创建项目3.png)![创建Pipeline任务04](./images/gitlab创建项目4.png) ![创建Pipeline任务05](./images/gitlab创建项目5.png) -## 五、lkp test 添加测试用例全部功能介绍 +## 六、lkp test 添加测试用例全部功能介绍 ### 样例 @@ -645,7 +657,7 @@ lkp split programs/compatibility-test/jobs/compatibility-test.yaml ln -s xxx/lkp-tests/programs/compatibility-test/run xxx/lkp-tests/tests/compatibility-test ``` -## 六、FAQ +## 七、FAQ ### lkp install 遇到的问题 diff --git "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" index 25de563e274af139605cef87ffa63fb6ae5b522e..dacd8febfcbc82e359d3daa7ffbc5d194a447dbd 100644 Binary files "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" and "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216gitlab\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" differ diff --git "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" index 029f17d046cc92a62738cf1895a1c751725e4d0d..385ec7c7746413f94ca6a6936d13bbf72085ecb5 100644 --- "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" +++ "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.md" @@ -4,9 +4,19 @@ ------ -测试平台使用的是lkp test 工具,以下均已lkp test描述测试平台 +测试平台使用的是lkp test 工具,以下均已lkp test描述测试平台 -## 一. 安装指导 +## 一. 云测工具介绍 + +lkp test是运行云测工具描述验证应用在鲲鹏服务器上的运行情况的必要依赖 + +云测工具是用来运行兼容性测试和可靠性测试的应用 + +| 兼容性测试 | 通过待测试应用软件在鲲鹏环境启动前后资源波动异常检测、验证应用软件启动和停止,自动检测应用软件在鲲鹏平台上的可运行性、兼容性问题。 | +| ----- | ---------------------------------------------------------------------- | +| 可靠性测试 | 通过待测试应用软件在稳定运行期间的系统资源内存的波动异常检测、在异常终止测试场景检测应用运行,自动评估应用软件在鲲鹏平台上的稳定性和可靠性。 | + +## 二. 安装指导 可以使用一键部署工具去部署,如果只想单独部署测试平台可以按照以下操作(请用有root权限的用户去安装) @@ -60,9 +70,11 @@ lkp install 直接解压缩compatibility_testing.tar.gz到${HOME}/.local就行 -## 二. 添加项目至lkp tests测试平台 +## 三. 添加项目至lkp tests测试平台(云测工具已完成添加,无需再次添加,以下仅用来介绍如何再lkp tests里面添加项目) + +如果想要添加别的项目请按照下方指导,无需重安云测工具 -### (1) 极简版项目添加,示例-云测工具(compatibility-test) +### (1) 极简版项目添加,示例-云测工具(compatibility-test已完成添加) 以下所有文件夹在安装完lkp-tests 文件夹下面,如果使用一键部署工具则在${HOME}/.local下面 @@ -137,7 +149,7 @@ lkp split programs/compatibility-test/jobs/compatibility-test.yaml ln -s xxx/lkp-tests/programs/compatibility-test/run xxx/lkp-tests/tests/compatibility-test ``` -### (2) 带参数版项目添加,示例-云测工具(compatibility-test) +### (2) 带参数版项目添加,示例-云测工具(compatibility-test已完成添加) 1. 在programs 文件夹下创建compatibility-test文件夹,里面要包含以下几个文件,其余文件可以根据需求自行决定是否添加 @@ -218,7 +230,7 @@ lkp split programs/compatibility-test/jobs/compatibility-test.yaml ln -s xxx/lkp-tests/programs/compatibility-test/run xxx/lkp-tests/tests/compatibility-test ``` -## 三、 云测工具 +## 四、 如何配置以及使用兼容性测试工具-云测工具 要运行云测平台需要配置参数,在安装目录${HOME}/.local/compatibility_testing/Chinese/compatibility_testing.conf @@ -273,7 +285,9 @@ hpc_certificate= binary_file= ``` -## 四、Jenkins Pipeline 中集成lkp test (以云测工具(compatibility-test)为示例) +之后如何运行请看pipeline实例代码 + +## 五、Jenkins Pipeline 中集成lkp test (以云测工具(compatibility-test)为示例) 请确保运行的用户有root权限 @@ -335,7 +349,7 @@ stage('lkp test') { ---- -## 五、lkp test 添加测试用例全部功能介绍 +## 六、lkp test 添加测试用例全部功能介绍 ### 样例 @@ -589,7 +603,7 @@ programs/$program/PKGBUILD # when $package=$program makedepends_debian_11=(lam4-dev libopenmpi-dev libmpich-dev pvm-dev) ``` -## 六、FAQ +## 七、FAQ ### lkp install 遇到的问题 diff --git "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" index 569a483dbe77dc80c62964fd7db1a12e4a7e94bb..64b88cba6fd6e66fefd1b4091d734773349d261f 100644 Binary files "a/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" and "b/document/\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262/devkit\346\265\213\350\257\225\345\271\263\345\217\260\345\256\211\350\243\205\351\203\250\347\275\262\344\270\216jenkins\351\233\206\346\210\220\351\203\250\347\275\262\346\214\207\345\257\274\346\211\213\345\206\214.pdf" differ diff --git a/tools/install_dependency/src/constant.py b/tools/install_dependency/src/constant.py index 96023520141e181a8175b5d43ad9f1573c973abd..4e2dc663f37b9ca6c0b0555a37c12403bd7c288b 100644 --- a/tools/install_dependency/src/constant.py +++ b/tools/install_dependency/src/constant.py @@ -16,7 +16,7 @@ ROLE_COMPONENT = { SCANNER: ["BiShengJDK17", "DevKitCLI"], C_BUIDLER: ["GCCforOpenEuler", "BiShengCompiler", "BiShengJDK17", "A-FOT", "NonInvasiveSwitching"], JAVA_BUILDER: ["BiShengJDK17", "BiShengJDK8"], - EXECUTOR: ["BiShengJDK17", "DevkitDistribute", "LkpTests"], + EXECUTOR: ["BiShengJDK17", "LkpTests", "CompatibilityTesting", "DevkitDistribute"], DEVKIT: ["DevKitWeb"] } diff --git a/tools/install_dependency/src/deploy/a_fot_deploy.py b/tools/install_dependency/src/deploy/a_fot_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..08324236d8cf666b0b7d70b43f26089f18d9f63f --- /dev/null +++ b/tools/install_dependency/src/deploy/a_fot_deploy.py @@ -0,0 +1,23 @@ +import constant +import os +from deploy.deploy_base import DeployBase +from utils import (CHECK_PERF_AVAILABLE_CMD, remote_exec_command, MKDIR_TMP_DEVKITDEPENDENCIES_CMD) + + +class AFotDeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(AFotDeploy, self).__init__(component, + ip, user, pkey, password, hook_before_upload_fn=self.hook_before_upload_fn, hook_after_install_fn=None) + self.upload_func = False + + def hook_before_upload_fn(self): + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + remote_exec_command(CHECK_PERF_AVAILABLE_CMD, self.ssh_client, self.LOGGER, self.ip) + saved_path = os.path.join(constant.DEFAULT_PATH, "a-fot.tar.gz") + remote_file = os.path.abspath(os.path.join('/tmp', saved_path)) + self.LOGGER.debug(f"Transport local_file: {saved_path} to remote machine {self.ip} " + f"remote_file: {remote_file}") + self.sftp_client.put(localpath=f"{saved_path}", remotepath=f"{remote_file}") + + diff --git a/tools/install_dependency/src/deploy/bisheng_compiler_deploy.py b/tools/install_dependency/src/deploy/bisheng_compiler_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..865a4b9dceea2543fe74468b5b756f256892b03c --- /dev/null +++ b/tools/install_dependency/src/deploy/bisheng_compiler_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class BiShengCompilerDeploy(DeployBase): + pass diff --git a/tools/install_dependency/src/deploy/bisheng_jdk17_deploy.py b/tools/install_dependency/src/deploy/bisheng_jdk17_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..6bbf791a0a19135a3615915bed1b113ef196810b --- /dev/null +++ b/tools/install_dependency/src/deploy/bisheng_jdk17_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class BiShengJDK17Deploy(DeployBase): + pass diff --git a/tools/install_dependency/src/deploy/bisheng_jdk8_deploy.py b/tools/install_dependency/src/deploy/bisheng_jdk8_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..a6acb2e4a4a139d3e93f42af423d51ca82563584 --- /dev/null +++ b/tools/install_dependency/src/deploy/bisheng_jdk8_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class BiShengJDK8Deploy(DeployBase): + pass diff --git a/tools/install_dependency/src/deploy/compatibility_test_deploy.py b/tools/install_dependency/src/deploy/compatibility_test_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..7d0847993f5881bc4cdb0d5eb3bb20e64f9213ab --- /dev/null +++ b/tools/install_dependency/src/deploy/compatibility_test_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class CompatibilityDeploy(DeployBase): + pass \ No newline at end of file diff --git a/tools/install_dependency/src/deploy/deploy_base.py b/tools/install_dependency/src/deploy/deploy_base.py new file mode 100644 index 0000000000000000000000000000000000000000..248d13ee6b65ea4e5c041bc44ab36634552c0463 --- /dev/null +++ b/tools/install_dependency/src/deploy/deploy_base.py @@ -0,0 +1,129 @@ +import logging +import os + +import timeout_decorator + +import constant +from deploy.deploy_help import DeployHelp +from download.download_utils import component_collection_map +from utils import (base_path, MKDIR_TMP_DEVKITDEPENDENCIES_CMD, + CHECK_TAR_AVAILABLE_CMD, CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE, + CHECK_MIRROR_INSTALL_STATUS, remote_exec_command, SHELL_FILE_LIST, global_value) + + +class DeployBase: + def __init__(self, component, + ip, user, pkey, password, hook_before_upload_fn=None, hook_after_install_fn=None): + self.component = component + self.before_upload_fn = hook_before_upload_fn + self.after_install_fn = hook_after_install_fn + self.LOGGER = logging.getLogger("install_dependency") + self.ip = ip + self.user = user + self.pkey = pkey + self.upload_func = True + self.install_func = True + self.install_param = False + self.password = password + self.deploy_helper = DeployHelp(ip, user, pkey, password, self.LOGGER) + # todo 把这个用的时候在创建 + self.sftp_client = None + self.ssh_client = None + self.remote_file_list = [] + # 去掉这个,每个component直接以compoent去调用 + + def clear_tmp_file_at_remote_machine(self, remote_file_list): + self.LOGGER.debug(f"Clear tmp file at remote machine {self.ip}") + for remote_file in remote_file_list: + try: + remote_file = os.path.realpath(remote_file) + if not remote_file.startswith(os.path.join("/tmp", constant.DEPENDENCY_DIR)): + continue + self.LOGGER.debug(f"Delete tmp file at remote machine {self.ip}: {remote_file}") + self.ssh_client.exec_command(f"rm -fr {remote_file}") + except Exception as e: + self.LOGGER.debug(str(e)) + + def upload(self): + remote_exec_command(CHECK_TAR_AVAILABLE_CMD, self.ssh_client, self.LOGGER, self.ip) + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + remote_exec_command(CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE, self.ssh_client, self.LOGGER, self.ip) + # 上传 lkp-tests.tar.gz文件 + self.LOGGER.info(f"Install component in remote machine {self.ip}: {self.component}") + + shell_dict = component_collection_map.get(self.component) + for shell_cmd in shell_dict: + url_and_save_path = shell_dict.get(shell_cmd) + local_file = url_and_save_path.get("save_path") + remote_file = os.path.abspath(os.path.join('/tmp', constant.DEPENDENCY_DIR, local_file.split('/')[-1])) + self.LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " + f"remote_file: {remote_file}") + + self.remote_file_list.append(remote_file) + self.sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") + + def transport_shell_file_and_execute(self, sh_file_local_path, sh_file_remote_path, + sh_cmd): + if not os.path.exists(sh_file_local_path): + self.LOGGER.error(f"{sh_file_local_path} not exists.") + raise FileNotFoundError(f"local file {sh_file_local_path} not exists.") + + self.LOGGER.debug(f"Transport local_file: {sh_file_local_path} to remote machine {self.ip} " + f"remote_file: {sh_file_remote_path}") + self.sftp_client.put(localpath=sh_file_local_path, remotepath=sh_file_remote_path) + + stdin, stdout, stderr = self.ssh_client.exec_command(sh_cmd) + output = stdout.read().decode().strip() + self.LOGGER.info(f"Remote machine {self.ip} '{sh_cmd}' output: {output}") + return output + + def install(self): + # 上传并执行 安装脚本, 校验安装结果脚本 + install_result = "" + for shell_file in SHELL_FILE_LIST: + sh_file_local_path = os.path.join(base_path("component"), self.component, shell_file) + sh_file_remote_path = os.path.join("/tmp/", constant.DEPENDENCY_DIR, self.component + shell_file) + if self.install_param: + sh_cmd = f"bash {sh_file_remote_path} {sh_file_remote_path}" + else: + sh_cmd = f"bash {sh_file_remote_path}" + execute_output = ( + self.transport_shell_file_and_execute( + sh_file_local_path=sh_file_local_path, + sh_file_remote_path=sh_file_remote_path, + sh_cmd=sh_cmd + )) + self.remote_file_list.append(sh_file_remote_path) + if shell_file == SHELL_FILE_LIST[1]: + install_result = execute_output + + if install_result == "true": + self.LOGGER.info(f"Remote machine {self.ip} install {self.component} success.") + else: + self.LOGGER.error(f"Remote machine {self.ip} install {self.component} failed.") + + def clean(self): + # 清理tmp临时文件 + self.clear_tmp_file_at_remote_machine(self.remote_file_list) + + def install_component_handler(self): + try: + self.sftp_client = self.deploy_helper.sftp_client() + self.ssh_client = self.deploy_helper.ssh_client() + if self.before_upload_fn: + self.before_upload_fn() + if self.upload_func: + self.upload() + if self.install_func: + self.install() + if self.after_install_fn: + self.after_install_fn() + self.clean() + except timeout_decorator.TimeoutError as e: + self.LOGGER.error(f"Remote machine {self.ip} occur Error: Exec cmd {str(e)}") + except (FileNotFoundError, PermissionError, NotADirectoryError, OSError, IOError) as e: + self.LOGGER.error(f"Remote machine {self.ip} occur Error: {str(e)}") + finally: + self.clear_tmp_file_at_remote_machine([os.path.join("/tmp/", constant.DEPENDENCY_DIR)]) + self.ssh_client.close() + self.sftp_client.close() diff --git a/tools/install_dependency/src/deploy/deploy_help.py b/tools/install_dependency/src/deploy/deploy_help.py new file mode 100644 index 0000000000000000000000000000000000000000..69953a6a1330c0951ccbddd1487a495eeb57df66 --- /dev/null +++ b/tools/install_dependency/src/deploy/deploy_help.py @@ -0,0 +1,85 @@ +import logging +import os +import socket + +import paramiko +import timeout_decorator + +from exception.connect_exception import (CreatePkeyFailedException, ConnectRemoteException, + NotMatchedMachineTypeException) +from utils import validate_path + + +class DeployHelp: + def __init__(self, ip, user, pkey, password, logger): + self.ip = ip + self.user = user + self.pkey = pkey + self.password = password + self.LOGGER = logger + + pass + + def check_is_aarch64(self): + machine_type = self.get_machine_type() + self.LOGGER.info(f"{self.ip} machine type: {machine_type}") + if machine_type != "aarch64": + self.LOGGER.error(f"Machine type of {self.ip} is {machine_type}, not aarch64. Please replace this machine.") + raise NotMatchedMachineTypeException() + + def get_machine_type(self): + try: + ssh_client = self.ssh_client() + stdin, stdout, stderr = ssh_client.exec_command("uname -m", timeout=10) + except (paramiko.ssh_exception.SSHException, socket.timeout) as e: + self.LOGGER.error(f"Connect remote {self.ip} failed. {str(e)}") + raise ConnectRemoteException() + stdout_output = stdout.read().decode().strip() + ssh_client.close() + return stdout_output + + def ssh_client(self): + ssh = paramiko.SSHClient() + ssh._transport = self.transport_connect() + return ssh + + def sftp_client(self): + sftp = paramiko.SFTPClient.from_transport(self.transport_connect()) + return sftp + + def transport_connect(self): + if not validate_path(self.pkey) or not os.path.isfile(self.pkey): + self.LOGGER.error("Yaml file content not correct. Given pkey not exists.") + raise ConnectRemoteException() + try: + # 指定本地的RSA私钥文件。如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 + pkey = paramiko.RSAKey.from_private_key_file(self.pkey, password=self.password) + except (IOError,) as e: + self.LOGGER.error(f"Pkey file not exists. {str(e)}") + raise CreatePkeyFailedException() + except (paramiko.ssh_exception.PasswordRequiredException, paramiko.ssh_exception.AuthenticationException) as e: + self.LOGGER.warning(f"Pkey password is required. {str(e)}") + password = input(f"Press Enter to input password of {self.pkey}: ") + self.password = password + return self.transport_connect() + except (paramiko.ssh_exception.SSHException,) as e: + self.LOGGER.error(f"Connect remote {self.ip} failed because of wrong pkey. {str(e)}") + raise CreatePkeyFailedException() + + try: + transport = self.transport_connect_with_timeout(pkey) + except (paramiko.ssh_exception.AuthenticationException, + paramiko.ssh_exception.SSHException, + timeout_decorator.TimeoutError, + socket.gaierror, + socket.timeout, + socket.error) as e: + self.LOGGER.error(f"Connect remote {self.ip} failed. {str(e)}") + raise ConnectRemoteException() + return transport + + @timeout_decorator.timeout(10) + def transport_connect_with_timeout(self, pkey): + transport = paramiko.Transport((self.ip, 22)) + transport.connect(username=self.user, pkey=pkey) + return transport diff --git a/tools/install_dependency/src/deploy/devkit_distribute_deploy.py b/tools/install_dependency/src/deploy/devkit_distribute_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..f9636003357d6941debe638d57744e0a90a4d8e7 --- /dev/null +++ b/tools/install_dependency/src/deploy/devkit_distribute_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class DevkitDistributeDeploy(DeployBase): + pass \ No newline at end of file diff --git a/tools/install_dependency/src/deploy/devkitcli_deploy.py b/tools/install_dependency/src/deploy/devkitcli_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..8703abe43bb09ae5aa39aca5366d5b9198e5e75d --- /dev/null +++ b/tools/install_dependency/src/deploy/devkitcli_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class DevkitCLIDeploy(DeployBase): + pass \ No newline at end of file diff --git a/tools/install_dependency/src/deploy/devkitweb_deploy.py b/tools/install_dependency/src/deploy/devkitweb_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..46296b517acd9ed54b79033cf4c15f814504f034 --- /dev/null +++ b/tools/install_dependency/src/deploy/devkitweb_deploy.py @@ -0,0 +1,44 @@ +# todo 这个原来的逻辑写的跟咱们通用的有点不一样要改 + +import os +import subprocess +from download.download_utils import component_collection_map +from deploy.deploy_base import DeployBase +from utils import base_path, MKDIR_TMP_DEVKITDEPENDENCIES_CMD, remote_exec_command + + +class DevkitWebDeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(DevkitWebDeploy, self).__init__(component, + ip, user, pkey, password, hook_before_upload_fn=self.hook_before_upload_fn, hook_after_install_fn=self.hook_after_install_fn) + self.install_func = False + self.upload_func = False + + def hook_before_upload_fn(self): + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + + self.LOGGER.info(f"Install component in remote machine {self.ip}: {self.component}") + shell_dict = component_collection_map.get(self.component) + + url_and_save_path = shell_dict.get("download file") + local_file = url_and_save_path.get("save_path") + remote_file = os.path.abspath(os.path.join('/opt', local_file.split('/')[-1])) + self.LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " + f"remote_file: {remote_file}") + self.remote_file_list.append(remote_file) + self.sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") + + cmd = f"{os.path.join(base_path('component'), self.component, 'devkit_installer')} " \ + f"-i {self.ip} -u {self.user} -p {self.pkey} -paname {local_file.split('/')[-1]}" + self.LOGGER.debug(f"Executing command: {cmd}") + subprocess.run(cmd.split(' '), + capture_output=False, shell=False, stderr=subprocess.STDOUT) + + def hook_after_install_fn(self): + local_file = component_collection_map.get(self.component).get("download file").get("save_path") + cmd = f"{os.path.join(base_path('component'), self.component, 'devkit_installer')} " \ + f"-i {self.ip} -u {self.user} -p {self.pkey} -paname {local_file.split('/')[-1]}" + self.LOGGER.debug(f"Executing command: {cmd}") + subprocess.run(cmd.split(' '), + capture_output=False, shell=False, stderr=subprocess.STDOUT) diff --git a/tools/install_dependency/src/deploy/gcc_deploy.py b/tools/install_dependency/src/deploy/gcc_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..06caba845442ef84a4fffe0d0922aaf603456594 --- /dev/null +++ b/tools/install_dependency/src/deploy/gcc_deploy.py @@ -0,0 +1,6 @@ + +from deploy.deploy_base import DeployBase + + +class GccDeploy(DeployBase): + pass diff --git a/tools/install_dependency/src/deploy/lkptest_deploy.py b/tools/install_dependency/src/deploy/lkptest_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..9cc9716f538b9d38a6a56029a3f7e2f71068caa2 --- /dev/null +++ b/tools/install_dependency/src/deploy/lkptest_deploy.py @@ -0,0 +1,13 @@ + +from deploy.deploy_base import DeployBase +from utils import YUM_INSTALL_LKP_DEPENDENCIES_CMD, remote_exec_command + + +class LkpTestDeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(LkpTestDeploy, self).__init__(component, + ip, user, pkey, password, hook_before_upload_fn=self.hook_before_upload_fn, hook_after_install_fn=None) + + def hook_before_upload_fn(self): + remote_exec_command(YUM_INSTALL_LKP_DEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) diff --git a/tools/install_dependency/src/deploy/mount_mirror_deploy.py b/tools/install_dependency/src/deploy/mount_mirror_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..fbb29480e3b391df6c3a2b4e45d5943ba5a840a7 --- /dev/null +++ b/tools/install_dependency/src/deploy/mount_mirror_deploy.py @@ -0,0 +1,24 @@ +import os +from deploy.deploy_base import DeployBase +from utils import CHECK_HOME_SPACE_SUFFICIENT_FOR_MIRROR, remote_exec_command, MKDIR_TMP_DEVKITDEPENDENCIES_CMD +from deploy.deploy_command_line import CommandLine + + +class MountISODeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(MountISODeploy, self).__init__(component, + ip, user, pkey, password, hook_before_upload_fn=self.hook_before_upload_fn, + hook_after_install_fn=None) + self.upload_func = False + self.install_param = True + + def hook_before_upload_fn(self): + remote_exec_command(CHECK_HOME_SPACE_SUFFICIENT_FOR_MIRROR, self.ssh_client, self.LOGGER, self.ip) + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + self.LOGGER.info(f"Deploy component in remote machine {self.ip}: {self.component}") + local_path = os.path.abspath(CommandLine.iso_path) + remote_path = os.path.join("/home", local_path.split('/')[-1]) + self.LOGGER.debug(f"Transport local_file: {local_path} to remote machine {self.ip} " + f"remote_file: {remote_path}") + self.sftp_client.put(localpath=local_path, remotepath=remote_path) diff --git a/tools/install_dependency/src/deploy/switch_deploy.py b/tools/install_dependency/src/deploy/switch_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..0d119f2b4df9be332b52bf1458a9a3701c9af03a --- /dev/null +++ b/tools/install_dependency/src/deploy/switch_deploy.py @@ -0,0 +1,15 @@ +from deploy.deploy_base import DeployBase +from utils import remote_exec_command, MKDIR_TMP_DEVKITDEPENDENCIES_CMD + + +class SwitchDeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(SwitchDeploy, self).__init__(component, + ip, user, pkey, password, hook_before_upload_fn=self.hook_before_upload_fn, + hook_after_install_fn=None) + self.upload_func = False + + def hook_before_upload_fn(self): + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + diff --git a/tools/install_dependency/src/deploy/unmount_mirror_deploy.py b/tools/install_dependency/src/deploy/unmount_mirror_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..b1fd90911b13596efaf3d04e7d532132d19ff4c1 --- /dev/null +++ b/tools/install_dependency/src/deploy/unmount_mirror_deploy.py @@ -0,0 +1,37 @@ +import os + +from deploy.deploy_base import DeployBase +from utils import CHECK_MIRROR_INSTALL_STATUS, base_path, remote_exec_command, MKDIR_TMP_DEVKITDEPENDENCIES_CMD +from deploy.deploy_command_line import CommandLine + + +class UnMountISODeploy(DeployBase): + def __init__(self, component, + ip, user, pkey, password): + super(UnMountISODeploy, self).__init__(component, + ip, user, pkey, password, + hook_before_upload_fn=self.hook_before_upload_fn, + hook_after_install_fn=self.hook_after_install_fn) + self.install_func = False + self.upload_func = False + + def hook_before_upload_fn(self): + remote_exec_command(CHECK_MIRROR_INSTALL_STATUS, self.ssh_client, self.LOGGER, self.ip) + self.component = self.component.replace("Un", "") + + def hook_after_install_fn(self): + remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, self.ssh_client, self.LOGGER, self.ip) + local_path = os.path.abspath(CommandLine.iso_path) + remote_path = os.path.join("/home", local_path.split('/')[-1]) + for shell_file in ["uninstall.sh"]: + sh_file_local_path = os.path.join(base_path("component"), self.component, shell_file) + sh_file_remote_path = os.path.join("/tmp/", self.component + shell_file) + sh_cmd = f"bash {sh_file_remote_path}" + execute_output = ( + self.transport_shell_file_and_execute( + sh_file_local_path=sh_file_local_path, + sh_file_remote_path=sh_file_remote_path, + sh_cmd=sh_cmd + )) + self.remote_file_list.append(sh_file_remote_path) + self.remote_file_list.append(remote_path) diff --git a/tools/install_dependency/src/download/download_utils.py b/tools/install_dependency/src/download/download_utils.py index 595180d83f069a154d7dc014a8504ec5c1051b74..766e7393806693f666f07369a768015b18d94a4b 100644 --- a/tools/install_dependency/src/download/download_utils.py +++ b/tools/install_dependency/src/download/download_utils.py @@ -74,12 +74,14 @@ component_collection_map = { SAVE_PATH: f"{os.path.join(DEFAULT_PATH, download_config.LkpTests.get('GemDependency').split('/')[-1])}", FILE_SIZE: "4206309", }, - "CompatibilityTesting": { + }, + + "CompatibilityTesting": { + "download file":{ URL: f"{download_config.LkpTests.get('CompatibilityTesting')}", SAVE_PATH: f"{os.path.join(DEFAULT_PATH, download_config.LkpTests.get('CompatibilityTesting').split('/')[-1])}", FILE_SIZE: "76645477", - }, - + } }, "DevkitDistribute": { diff --git a/tools/install_dependency/src/handler/connect_check.py b/tools/install_dependency/src/handler/connect_check.py index cf142e7c2046f5c0f58df5079153bf61cc2b5cad..d77fa6c7f151b872c980174e82f93334e9c1c82a 100644 --- a/tools/install_dependency/src/handler/connect_check.py +++ b/tools/install_dependency/src/handler/connect_check.py @@ -3,11 +3,39 @@ import socket import constant from handler.handler_and_node import Handler -from machine.machine import Machine from exception.connect_exception import ConnectException from constant import ROLE_COMPONENT, ROLE_LIST +from utils import global_value +from deploy.bisheng_jdk17_deploy import BiShengJDK17Deploy +from deploy.bisheng_jdk8_deploy import BiShengJDK8Deploy +from deploy.devkitcli_deploy import DevkitCLIDeploy +from deploy.gcc_deploy import GccDeploy +from deploy.bisheng_compiler_deploy import BiShengCompilerDeploy +from deploy.switch_deploy import SwitchDeploy +from deploy.lkptest_deploy import LkpTestDeploy +from deploy.compatibility_test_deploy import CompatibilityDeploy +from deploy.devkit_distribute_deploy import DevkitDistributeDeploy +from deploy.devkitweb_deploy import DevkitWebDeploy +from deploy.mount_mirror_deploy import MountISODeploy +from deploy.unmount_mirror_deploy import UnMountISODeploy +from deploy.a_fot_deploy import AFotDeploy LOGGER = logging.getLogger("install_dependency") +ROLE_MAP = { + "BiShengJDK17": BiShengJDK17Deploy, + "BiShengJDK8": BiShengJDK8Deploy, + "DevKitCLI": DevkitCLIDeploy, + "GCCforOpenEuler": GccDeploy, + "BiShengCompiler": BiShengCompilerDeploy, + "A-FOT": AFotDeploy, + "NonInvasiveSwitching": SwitchDeploy, + "LkpTests": LkpTestDeploy, + "CompatibilityTesting": CompatibilityDeploy, + "DevkitDistribute": DevkitDistributeDeploy, + "DevKitWeb": DevkitWebDeploy, + "OpenEulerMirrorISO": MountISODeploy, + "UnOpenEulerMirrorISO": UnMountISODeploy +} class ConnectCheck(Handler): @@ -16,18 +44,32 @@ class ConnectCheck(Handler): data[constant.MACHINE] = dict() ret = True for role in (ROLE_LIST & data.keys()): - ret = ret and ConnectCheck.machine_role_check(data, role) + ret = ret and ConnectCheck.deploy_role_check(data, role) return ret @staticmethod - def machine_role_check(data, role): + def deploy_role_check(data, role): builder_list = data.get(role) + if data.get(constant.INSTRUCTION) == "deploy_iso": + global_value["DEPLOY_ISO"] = True for ip in builder_list: try: - machine_instance = data[constant.MACHINE].get(ip, Machine(ip, data[constant.USER], data[constant.PKEY], - data.get(constant.PASSWORD, None))) - machine_instance.add_component(ROLE_COMPONENT[role]) - data[constant.MACHINE][ip] = machine_instance + for each in ROLE_COMPONENT[role]: + if ip in global_value["ip"].keys(): + global_value["ip"][ip]["component_set"].add(each) + else: + global_value["ip"][ip] = dict() + global_value["ip"][ip]["component_set"] = set() + global_value["ip"][ip]["component_set"].add(each) + global_value["ip"][ip]["component_list"] = list(global_value["ip"][ip]["component_set"]) + if global_value["DEPLOY_ISO"]: + global_value["ip"][ip]["component_list"].insert(0, "OpenEulerMirrorISO") + global_value["ip"][ip]["component_list"].append("UnOpenEulerMirrorISO") + global_value["ip"][ip]["deploy_component"] = [] + for each in global_value["ip"][ip]["component_list"]: + global_value["ip"][ip]["deploy_component"].append(ROLE_MAP.get(each)(each, ip, data[constant.USER], + data[constant.PKEY], + data.get(constant.PASSWORD))) except ConnectException: LOGGER.error(f"-- [error] Connect {ip} failed. Please check.") del data[constant.MACHINE] @@ -36,8 +78,6 @@ class ConnectCheck(Handler): LOGGER.error(f"-- [error] Connect {ip} failed. Because of {str(e)}") del data[constant.MACHINE] return False - if data.get(constant.INSTRUCTION) == "deploy_iso": - machine_instance.set_mirror() return True @staticmethod diff --git a/tools/install_dependency/src/handler/install_package.py b/tools/install_dependency/src/handler/install_package.py index ab81daa10a043a219b85ff65c8e11d7514aa167a..c11a496643fbf06bd23c6d15fb5e3b8b3bf26d15 100644 --- a/tools/install_dependency/src/handler/install_package.py +++ b/tools/install_dependency/src/handler/install_package.py @@ -2,6 +2,7 @@ import logging import multiprocessing import constant +from utils import global_value from handler.handler_and_node import Handler LOGGER = logging.getLogger("install_dependency") @@ -12,17 +13,28 @@ class InstallPackage(Handler): def handle(self, data): LOGGER.debug("Install Package start!") jobs = [] - for _, machine in data[constant.MACHINE].items(): - process = multiprocessing.Process(target=process_work, args=(machine,)) + undeploy_iso = None + for each in global_value["ip"].keys(): + process = multiprocessing.Process(target=process_deploy_component, args=(each,)) jobs.append(process) process.start() - for job in jobs: - job.join() + for job in jobs: + job.join() return True -def process_work(machine): +def process_deploy_component(ip): try: - machine.install_components() + undeploy_iso = None + if global_value["DEPLOY_ISO"]: + global_value["ip"][ip]["deploy_component"][0].install_component_handler() + undeploy_iso = global_value["ip"][ip]["deploy_component"][-1] + del global_value["ip"][ip]["deploy_component"][0] + del global_value["ip"][ip]["deploy_component"][-1] + for every in global_value["ip"][ip]["deploy_component"]: + every.install_component_handler() + if global_value["DEPLOY_ISO"]: + undeploy_iso.install_component_handler() except (OSError, IOError) as e: - LOGGER.error(f"Remote machine {machine.ip} occur Error: {str(e)}") + LOGGER.error(f"Remote machine {ip} occur Error: {str(e)}") + diff --git a/tools/install_dependency/src/machine/__init__.py b/tools/install_dependency/src/machine/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/tools/install_dependency/src/machine/machine.py b/tools/install_dependency/src/machine/machine.py deleted file mode 100644 index 6bf8b7858c144624c7edc5cf27e790ad104f800c..0000000000000000000000000000000000000000 --- a/tools/install_dependency/src/machine/machine.py +++ /dev/null @@ -1,436 +0,0 @@ -import logging -import os -import socket -import subprocess -import typing - -import paramiko -import timeout_decorator - -import constant -from deploy.deploy_command_line import CommandLine -from exception.connect_exception import (CreatePkeyFailedException, ConnectRemoteException, - NotMatchedMachineTypeException) -from download.download_utils import component_collection_map -from utils import (base_path, validate_path, MKDIR_TMP_DEVKITDEPENDENCIES_CMD, - CHECK_TAR_AVAILABLE_CMD, CHECK_PERF_AVAILABLE_CMD, YUM_INSTALL_LKP_DEPENDENCIES_CMD, - CHECK_HOME_SPACE_SUFFICIENT_FOR_MIRROR, CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE, - CHECK_MIRROR_INSTALL_STATUS, PROMPT_MAP) - -LOGGER = logging.getLogger("install_dependency") -SHELL_FILE_LIST = ["install.sh", "check_install_result.sh"] - - -class Machine: - def __init__(self, ip, user, pkey, password=None): - self.ip = ip - self.user = user - self.pkey = pkey - self.password = password - self.check_is_aarch64() - self.component_list = [] - self.mirrors = False - - def add_component(self, component): - self.component_list.extend(component) - self.component_list = list(set(self.component_list)) - - def get_components(self): - return self.component_list.copy() - - def set_mirror(self): - self.mirrors = True - - def check_is_aarch64(self): - machine_type = self.get_machine_type() - LOGGER.info(f"{self.ip} machine type: {machine_type}") - if machine_type != "aarch64": - LOGGER.error(f"Machine type of {self.ip} is {machine_type}, not aarch64. Please replace this machine.") - raise NotMatchedMachineTypeException() - - def get_machine_type(self): - try: - ssh_client = self.ssh_client() - stdin, stdout, stderr = ssh_client.exec_command("uname -m", timeout=10) - except (paramiko.ssh_exception.SSHException, socket.timeout) as e: - LOGGER.error(f"Connect remote {self.ip} failed. {str(e)}") - raise ConnectRemoteException() - stdout_output = stdout.read().decode().strip() - ssh_client.close() - return stdout_output - - def ssh_client(self): - ssh = paramiko.SSHClient() - ssh._transport = self.transport_connect(self.user, self.pkey, self.password) - return ssh - - def sftp_client(self): - sftp = paramiko.SFTPClient.from_transport(self.transport_connect(self.user, self.pkey, self.password)) - return sftp - - def transport_connect(self, user, pkey_path, password=None): - if not validate_path(pkey_path) or not os.path.isfile(pkey_path): - LOGGER.error("Yaml file content not correct. Given pkey not exists.") - raise ConnectRemoteException() - try: - # 指定本地的RSA私钥文件。如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 - pkey = paramiko.RSAKey.from_private_key_file(pkey_path, password=password) - except (IOError,) as e: - LOGGER.error(f"Pkey file not exists. {str(e)}") - raise CreatePkeyFailedException() - except (paramiko.ssh_exception.PasswordRequiredException, paramiko.ssh_exception.AuthenticationException) as e: - LOGGER.warning(f"Pkey password is required. {str(e)}") - password = input(f"Press Enter to input password of {pkey_path}: ") - self.password = password - return self.transport_connect(user, pkey_path, password) - except (paramiko.ssh_exception.SSHException,) as e: - LOGGER.error(f"Connect remote {self.ip} failed because of wrong pkey. {str(e)}") - raise CreatePkeyFailedException() - - try: - transport = self.transport_connect_with_timeout(user, pkey) - except (paramiko.ssh_exception.AuthenticationException, - paramiko.ssh_exception.SSHException, - timeout_decorator.TimeoutError, - socket.gaierror, - socket.timeout, - socket.error) as e: - LOGGER.error(f"Connect remote {self.ip} failed. {str(e)}") - raise ConnectRemoteException() - return transport - - @timeout_decorator.timeout(10) - def transport_connect_with_timeout(self, user, pkey): - transport = paramiko.Transport((self.ip, 22)) - transport.connect(username=user, pkey=pkey) - return transport - - def install_components(self): - if self.mirrors: - self.install_component("OpenEulerMirrorISO") - for component in self.component_list: - self.install_component(component) - if self.mirrors: - self.install_component("UnOpenEulerMirrorISO") - - self.clear_tmp_file_at_remote_machine( - self.ssh_client(), [os.path.join("/tmp/", constant.DEPENDENCY_DIR)]) - - def install_component(self, component_name): - ssh_client = self.ssh_client() - sftp_client = self.sftp_client() - try: - self.install_component_handler(component_name, sftp_client, ssh_client) - except timeout_decorator.TimeoutError as e: - LOGGER.error(f"Remote machine {self.ip} occur Error: Exec cmd {str(e)}") - except (FileNotFoundError, PermissionError, NotADirectoryError, OSError, IOError) as e: - LOGGER.error(f"Remote machine {self.ip} occur Error: {str(e)}") - finally: - ssh_client.close() - sftp_client.close() - - def install_component_handler(self, component_name, sftp_client, ssh_client): - component_name_to_func_dict: typing.Dict[ - str, typing.Callable[[str, paramiko.SFTPClient, paramiko.SSHClient], typing.Any]] = { - "GCCforOpenEuler": self.default_install_component_handle, - "BiShengCompiler": self.default_install_component_handle, - "BiShengJDK17": self.default_install_component_handle, - "BiShengJDK8": self.default_install_component_handle, - "DevkitDistribute": self.default_install_component_handle, - "LkpTests": self.lkptest_install_component_handle, - "NonInvasiveSwitching": self.nis_install_component_handle, - "DevKitWeb": self.devkitweb_install_component_handle, - "DevKitCLI": self.default_install_component_handle, - "OpenEulerMirrorISO": self.deploy_iso_handle, - "UnOpenEulerMirrorISO": self.undeploy_iso_handle, - "A-FOT": self.install_a_fot, - } - self._remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, ssh_client) - self._remote_exec_command(CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE, ssh_client) - return component_name_to_func_dict.get(component_name)(component_name, sftp_client, ssh_client) - - def devkitweb_install_component_handle(self, component_name, sftp_client, ssh_client): - # 上传 tar.gz 文件 - LOGGER.info(f"Install component in remote machine {self.ip}: {component_name}") - remote_file_list = [] - shell_dict = component_collection_map.get(component_name) - - url_and_save_path = shell_dict.get("download file") - local_file = url_and_save_path.get("save_path") - remote_file = os.path.abspath(os.path.join('/opt', local_file.split('/')[-1])) - LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " - f"remote_file: {remote_file}") - remote_file_list.append(remote_file) - sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") - - cmd = f"{os.path.join(base_path('component'), component_name, 'devkit_installer')} " \ - f"-i {self.ip} -u {self.user} -p {self.pkey} -paname {local_file.split('/')[-1]}" - LOGGER.debug(f"Executing command: {cmd}") - subprocess.run(cmd.split(' '), - capture_output=False, shell=False, stderr=subprocess.STDOUT) - - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - - def install_a_fot(self, component_name, sftp_client, ssh_client): - self._remote_exec_command(CHECK_PERF_AVAILABLE_CMD, ssh_client) - saved_path = os.path.join(constant.DEFAULT_PATH, "a-fot.tar.gz") - remote_file = os.path.abspath(os.path.join('/tmp', saved_path)) - LOGGER.debug(f"Transport local_file: {saved_path} to remote machine {self.ip} " - f"remote_file: {remote_file}") - sftp_client.put(localpath=f"{saved_path}", remotepath=f"{remote_file}") - self.nis_install_component_handle(component_name, sftp_client, ssh_client) - self.clear_tmp_file_at_remote_machine(ssh_client, [remote_file]) - - def nis_install_component_handle(self, component_name, sftp_client, ssh_client): - remote_file_list = [] - # 上传并执行 安装脚本, 校验安装结果脚本 - install_result = "" - for shell_file in SHELL_FILE_LIST: - sh_file_local_path = os.path.join(base_path("component"), component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", constant.DEPENDENCY_DIR, component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - if shell_file == SHELL_FILE_LIST[1]: - install_result = execute_output - - if install_result == "true": - LOGGER.info(f"Remote machine {self.ip} install {component_name} success.") - else: - LOGGER.error(f"Remote machine {self.ip} install {component_name} failed.") - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - - def lkptest_install_component_handle(self, component_name, sftp_client, ssh_client): - self._remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, ssh_client) - self._remote_exec_command(YUM_INSTALL_LKP_DEPENDENCIES_CMD, ssh_client) - - # 上传 lkp-tests.tar.gz文件 - LOGGER.info(f"Install component in remote machine {self.ip}: {component_name}") - remote_file_list = [] - shell_dict = component_collection_map.get(component_name) - for shell_cmd in shell_dict: - url_and_save_path = shell_dict.get(shell_cmd) - local_file = url_and_save_path.get("save_path") - remote_file = os.path.abspath(os.path.join('/tmp', constant.DEPENDENCY_DIR, local_file.split('/')[-1])) - LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " - f"remote_file: {remote_file}") - - remote_file_list.append(remote_file) - sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") - # 上传并执行 安装脚本, 校验安装结果脚本 - install_result = "" - for shell_file in SHELL_FILE_LIST: - sh_file_local_path = os.path.join(base_path("component"), component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", constant.DEPENDENCY_DIR, component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - if shell_file == SHELL_FILE_LIST[1]: - install_result = execute_output - - if install_result == "true": - LOGGER.info(f"Remote machine {self.ip} install {component_name} success.") - else: - LOGGER.error(f"Remote machine {self.ip} install {component_name} failed.") - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - self.__install_component_on_lkptest("CompatibilityTesting", sftp_client, ssh_client) - - def __install_component_on_lkptest(self, sub_component_name, sftp_client, ssh_client): - # 上传 tar.gz 文件 - LOGGER.info(f"Install component in remote machine {self.ip}: {sub_component_name}") - remote_file_list = [] - url_and_save_path = component_collection_map.get("LkpTests").get(sub_component_name) - - local_file = url_and_save_path.get("save_path") - remote_file = os.path.abspath(os.path.join('/tmp', constant.DEPENDENCY_DIR, local_file.split('/')[-1])) - LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " - f"remote_file: {remote_file}") - remote_file_list.append(remote_file) - sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") - # 上传并执行 安装脚本, 校验安装结果脚本 - install_result = "" - for shell_file in SHELL_FILE_LIST: - sh_file_local_path = os.path.join(base_path("component"), sub_component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", constant.DEPENDENCY_DIR, sub_component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path} {remote_file_list[0]}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - if shell_file == SHELL_FILE_LIST[1]: - install_result = execute_output - - if install_result == "true": - LOGGER.info(f"Remote machine {self.ip} install {sub_component_name} success.") - else: - LOGGER.error(f"Remote machine {self.ip} install {sub_component_name} failed.") - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - - def deploy_iso_handle(self, component_name, sftp_client, ssh_client): - self._remote_exec_command(CHECK_HOME_SPACE_SUFFICIENT_FOR_MIRROR, ssh_client) - - # 上传 镜像文件 - LOGGER.info(f"Deploy component in remote machine {self.ip}: {component_name}") - local_path = os.path.abspath(CommandLine.iso_path) - remote_path = os.path.join("/home", local_path.split('/')[-1]) - LOGGER.debug(f"Transport local_file: {local_path} to remote machine {self.ip} " - f"remote_file: {remote_path}") - sftp_client.put(localpath=local_path, remotepath=remote_path) - - # 上传并执行 安装脚本, 校验安装结果脚本 - install_result = "" - remote_file_list = [] - for shell_file in SHELL_FILE_LIST: - sh_file_local_path = os.path.join(base_path("component"), component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path} {remote_path}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - if shell_file == SHELL_FILE_LIST[1]: - install_result = execute_output - - if install_result == "true": - LOGGER.info(f"Remote machine {self.ip} deploy {component_name} success.") - else: - LOGGER.info(f"Remote machine {self.ip} deploy {component_name} failed.") - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - - def default_install_component_handle(self, component_name, sftp_client, ssh_client): - self._remote_exec_command(CHECK_TAR_AVAILABLE_CMD, ssh_client) - self._remote_exec_command(MKDIR_TMP_DEVKITDEPENDENCIES_CMD, ssh_client) - self._remote_exec_command(CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE, ssh_client) - - # 上传 组件压缩包和校验文件 - LOGGER.info(f"Install component in remote machine {self.ip}: {component_name}") - remote_file_list = [] - shell_dict = component_collection_map.get(component_name) - for shell_cmd in shell_dict: - url_and_save_path = shell_dict.get(shell_cmd) - local_file = url_and_save_path.get("save_path") - remote_file = os.path.abspath(os.path.join('/tmp', local_file)) - LOGGER.debug(f"Transport local_file: {local_file} to remote machine {self.ip} " - f"remote_file: {remote_file}") - remote_file_list.append(remote_file) - sftp_client.put(localpath=f"{local_file}", remotepath=f"{remote_file}") - - # 上传并执行 安装脚本, 校验安装结果脚本 - install_result = "" - for shell_file in SHELL_FILE_LIST: - sh_file_local_path = os.path.join(base_path("component"), component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", constant.DEPENDENCY_DIR, component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - if shell_file == SHELL_FILE_LIST[1]: - install_result = execute_output - - if install_result == "true": - LOGGER.info(f"Remote machine {self.ip} install {component_name} success.") - else: - LOGGER.info(f"Remote machine {self.ip} install {component_name} failed.") - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) - - @timeout_decorator.timeout(100) - def _remote_exec_command(self, cmd, ssh_client): - try: - stdin, stdout, stderr = ssh_client.exec_command(cmd, timeout=90) - except (paramiko.ssh_exception.SSHException, socket.timeout) as e: - LOGGER.error(f"Remote machine {self.ip} exec '{cmd}' failed Please run this command in this machine.") - raise OSError(PROMPT_MAP.get(cmd, f"Remote machine {self.ip} exec '{cmd}' failed.")) - exit_status = stdout.channel.recv_exit_status() - if exit_status == 0: - LOGGER.debug(f"Remote machine {self.ip} exec '{cmd}' success.") - else: - LOGGER.error(f"Remote machine {self.ip} exec '{cmd}' failed. Please run this command in this machine.") - raise OSError(PROMPT_MAP.get(cmd, f"Remote machine {self.ip} exec '{cmd}' failed.")) - - def transport_shell_file_and_execute(self, ssh_client, sftp_client, sh_file_local_path, sh_file_remote_path, - sh_cmd): - if not os.path.exists(sh_file_local_path): - LOGGER.error(f"{sh_file_local_path} not exists.") - raise FileNotFoundError(f"local file {sh_file_local_path} not exists.") - - LOGGER.debug(f"Transport local_file: {sh_file_local_path} to remote machine {self.ip} " - f"remote_file: {sh_file_remote_path}") - sftp_client.put(localpath=sh_file_local_path, remotepath=sh_file_remote_path) - - stdin, stdout, stderr = ssh_client.exec_command(sh_cmd) - output = stdout.read().decode().strip() - LOGGER.info(f"Remote machine {self.ip} '{sh_cmd}' output: {output}") - return output - - def clear_tmp_file_at_remote_machine(self, ssh_client, remote_file_list): - LOGGER.debug(f"Clear tmp file at remote machine {self.ip}") - for remote_file in remote_file_list: - try: - remote_file = os.path.realpath(remote_file) - if not remote_file.startswith(os.path.join("/tmp", constant.DEPENDENCY_DIR)): - continue - LOGGER.debug(f"Delete tmp file at remote machine {self.ip}: {remote_file}") - ssh_client.exec_command(f"rm -fr {remote_file}") - except Exception as e: - LOGGER.debug(str(e)) - - def do_nothing(self, component_name, sftp_client, ssh_client): - return - - def undeploy_iso_handle(self, component_name, sftp_client, ssh_client): - # 需要检查本地镜像是否安装成功 - self._remote_exec_command(CHECK_MIRROR_INSTALL_STATUS, ssh_client) - - component_name = component_name.replace("Un", "") - LOGGER.info(f"Umount component in remote machine {self.ip}: {component_name}") - local_path = os.path.abspath(CommandLine.iso_path) - remote_path = os.path.join("/home", local_path.split('/')[-1]) - - # 上传并执行 卸载脚本 - remote_file_list = [] - for shell_file in ["uninstall.sh"]: - sh_file_local_path = os.path.join(base_path("component"), component_name, shell_file) - sh_file_remote_path = os.path.join("/tmp/", component_name + shell_file) - sh_cmd = f"bash {sh_file_remote_path}" - execute_output = ( - self.transport_shell_file_and_execute( - ssh_client, sftp_client, - sh_file_local_path=sh_file_local_path, - sh_file_remote_path=sh_file_remote_path, - sh_cmd=sh_cmd - )) - remote_file_list.append(sh_file_remote_path) - remote_file_list.append(remote_path) - # 清理tmp临时文件 - self.clear_tmp_file_at_remote_machine(ssh_client, remote_file_list) diff --git a/tools/install_dependency/src/utils.py b/tools/install_dependency/src/utils.py index 5bb6f404f9620fe5affe5dc4b8e54b397677a199..285484042639eac8087c51da6491ee41eb49a4cc 100644 --- a/tools/install_dependency/src/utils.py +++ b/tools/install_dependency/src/utils.py @@ -1,6 +1,10 @@ import os import sys import yaml +import paramiko +import socket +import timeout_decorator + from constant import ROLE_LIST, ROLE_COMPONENT CHECK_TAR_AVAILABLE_CMD = "which tar" @@ -10,6 +14,14 @@ YUM_INSTALL_LKP_DEPENDENCIES_CMD = "sudo yum install -y make git wget rubygems" CHECK_HOME_SPACE_SUFFICIENT_FOR_MIRROR = "[[ $(df -m /home | awk 'NR==2' | awk '{print $4}') -gt 17*1024 ]]" CHECK_TMP_SPACE_SUFFICIENT_FOR_PACKAGE = "[[ $(df -m /tmp | awk 'NR==2' | awk '{print $4}') -gt 1024 ]]" CHECK_MIRROR_INSTALL_STATUS = "test -d /etc/yum.repos.d/yum.repos.backup" +SHELL_FILE_LIST = ["install.sh", "check_install_result.sh"] +global_value = { + "DEPLOY_ISO": False, + "component_list": [], + "deploy_component": [], + "ip": {} + +} PROMPT_MAP = { CHECK_TAR_AVAILABLE_CMD: "'tar' command not available.", @@ -57,3 +69,18 @@ def generate_component_list(yaml_dict): continue component_list.extend(ROLE_COMPONENT[role]) return list(set(component_list)) + + +@timeout_decorator.timeout(100) +def remote_exec_command(cmd, ssh_client, LOGGER, ip): + try: + stdin, stdout, stderr = ssh_client.exec_command(cmd, timeout=90) + except (paramiko.ssh_exception.SSHException, socket.timeout) as e: + LOGGER.error(f"Remote machine {ip} exec '{cmd}' failed Please run this command in this machine.") + raise OSError(PROMPT_MAP.get(cmd, f"Remote machine {ip} exec '{cmd}' failed.")) + exit_status = stdout.channel.recv_exit_status() + if exit_status == 0: + LOGGER.debug(f"Remote machine {ip} exec '{cmd}' success.") + else: + LOGGER.error(f"Remote machine {ip} exec '{cmd}' failed. Please run this command in this machine.") + raise OSError(PROMPT_MAP.get(cmd, f"Remote machine {ip} exec '{cmd}' failed."))