diff --git a/tools/update_os/check_pre_upgrade.py b/tools/update_os/check_pre_upgrade.py new file mode 100644 index 0000000000000000000000000000000000000000..070859fe8012ecc8e34284319ad0ce492d7f95e0 --- /dev/null +++ b/tools/update_os/check_pre_upgrade.py @@ -0,0 +1,115 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" +Copyright: Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved +Create: 2022/12/19 +Content: +""" +import os +import logging +from command import Commands +from ssh import SSHConnect, login + + +if __name__ == '__main__': + + logger = logging + CLIENT_PKG_PATH = '/etc/x2openEuler/x2openEuler-client-2.0.0-1.noarch.rpm' + + #创建ssh对象 + ssh_info = SSHConnect('192.168.137.xx', + '22', + 'root', + 'xxx') + #获取ssh连接 + ssh_client = login(ssh_info) + if ssh_client is None: + logger.error('ssh connect failed') + exit() + else: + logger.info('ssh connect successd') + + #获取ftp工具 + ftp_client = ssh_client.open_sftp() + if ftp_client is None: + logger.error('get ftp client failed') + exit() + else: + logger.info('get ftp client successd') + + #1.传输client包到client端 + + try: + put_info = ftp_client.put(CLIENT_PKG_PATH + , '/root', confirm=True) + except Exception: + logger.error('upload failed') + exit() + logger.info('upload success') + + #2.安装client包 + stdin, stdout, stderr = \ + ssh_client.exec_command(f'rpm -ivh {CLIENT_PKG_PATH}') + if not stdout: + logger.error('install x2openEuler-client failed') + exit() + else: + logger.info('install x2openEuler-client success') + + #3.升级前检查 + stdin, stdout, stderr = \ + ssh_client.exec_command(f'x2openEuler-client upgrade-check-collect') + if not stdout: + logger.error('upgrade-check-collect failed') + exit() + else: + logger.info('upgrade-check-collect success') + result = stdout.readlines() + result_path = result.split('saved: ')[-1] + filename = result_path.split('collect/')[-1] + + # 4.将结果传回本地/opt下 + remote = result_path + try: + put_info = ftp_client.put(remote, '/opt', callback=None) + except Exception: + logger.error('download failed') + exit() + logger.info('download success') + + # 5.执行升级前检查 + collect_path = os.path.join(local, filename) + REPO_EVE = '' + REPO_UPDATE = '' + REPO_EPOL = '' + cmd = ['x2openEuler_python39', 'x2openEuler.pyc', 'upgrade-check', + '-repo', REPO_EVE + ',' + REPO_UPDATE + ',' + REPO_EPOL, + '-o', collect_path] + try: + result = Commands().run_single_cmd(cmd, logging_error=False)\ + .strip().split('\n') + except Exception: + logger.error('upgrade check failed') + exit() + logger.info(f'upgrade check result: {result}') + + + # 6.将upgrade.json传输到client端 + lines = result.split('\n') + for line in lines: + if 'Upgrade results are saved: ' in line: + upgrade_local_path = line.split('Upgrade results are saved: ')[-1] + try: + put_info = ftp_client.put(upgrade_local_path, '/root/upgrade.json', confirm=True) + except Exception: + logger.error('upload upgrade.json failed') + exit() + logger.info('upload upgrade.json success') + + # 7.上传repo源文件 + try: + put_info = ftp_client.put('migrate-2003.repo', 'root', confirm=True) + except Exception: + logger.error('upload repo failed') + exit() + logger.info('upload repo success') \ No newline at end of file diff --git a/tools/update_os/command.py b/tools/update_os/command.py new file mode 100644 index 0000000000000000000000000000000000000000..f113c4fba5f73fe27afaafade9d8560f76e10d7c --- /dev/null +++ b/tools/update_os/command.py @@ -0,0 +1,100 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" +Copyright: Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved +Create: 2022/12/20 +Content: +""" + +import subprocess +import logging + +logger = logging + + +class Commands(object): + """ + 系统命令封装,收编挪到公共组件目录 + """ + + @staticmethod + def run_single_cmd_and_get_error(cmd): + result = '' + try: + pipe = subprocess.Popen(cmd, universal_newlines=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + except (ValueError, OSError) as error_except: + logger.error("Command error : " + str(error_except)) + return result, 'error' + + try: + result, error = pipe.communicate(timeout=10) + except (ValueError, OSError) as error_except: + logger.error("Command error : " + str(error_except)) + error = 'error' + error = error.strip() + if error: + error = error.replace("\n", "").replace("\r", "") + logger.error('command execute ERROR, \ + Command: {}, Because:{}'.format(' '.join(cmd), error)) + if error.startswith('Warning:'): + error = '' + return result, error + + @staticmethod + def run_single_cmd(cmd, raise_exception=False, logger_error=True): + result = '' + try: + pipe = subprocess.Popen(cmd, universal_newlines=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + except (ValueError, OSError) as error_except: + logger.error("Command error : " + str(error_except)) + return result + + try: + result, error = pipe.communicate(timeout=10) + except (ValueError, OSError) as e: + logger.error("Command error : " + str(e)) + error = 'error' + if raise_exception: + raise e + if error and logger_error: + error = error.replace("\n", "").replace("\r", "") + logger.error('command execute ERROR, \ + Command: {}, Because:{}'.format(' '.join(cmd), error)) + return result + + @staticmethod + def run_mult_cmd(cmds, raise_exception=False, logger_error=True): + result = '' + pipes = [] + for cmd in cmds: + pipe_stdout = subprocess.PIPE + if len(pipes) != 0: + pipe_stdout = pipes[-1].stdout + try: + pipe = subprocess.Popen(cmd, stdin=pipe_stdout, + universal_newlines=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + except (ValueError, OSError) as error_except: + logger.error("Command error : " + str(error_except)) + return result + + if pipe_stdout is not subprocess.PIPE: + pipe_stdout.close() + pipes.append(pipe) + try: + result, error = pipes[-1].communicate(timeout=10) + except (ValueError, OSError) as e: + logger.error("Command error : " + str(e)) + error = 'error' + if raise_exception: + raise e + if pipes[-1].returncode != 0 and len(error) != 0 and logger_error: + error = error.replace("\n", "").replace("\r", "") + logger.error('command execute ERROR,Because:{}'.format(error)) + + return result diff --git a/tools/update_os/extract_pkg_info.py b/tools/update_os/extract_pkg_info.py new file mode 100644 index 0000000000000000000000000000000000000000..bb24f70a38167d31d3ca6cc4767f4befdbcc92df --- /dev/null +++ b/tools/update_os/extract_pkg_info.py @@ -0,0 +1,41 @@ +import json +import os +import stat +import sys + + +def extract_pkg_info(check_result_path, local_upgrade_json_path): + if not os.path.exists(check_result_path): + return + + if not os.access(check_result_path, os.R_OK): + return + + with open(check_result_path, "r") as file_pointer: + ret = json.load(file_pointer) + pkg_info = { + "reserved_rpm": ret.get("src_reserve_pkg", list()), + "deleted_rpm": ret.get("src_pre_delete_pkg", list()), + "swap_rpm_source": ["centos-logos", "centos-release"], + "swap_rpm_target": ["openEuler-logos", "openEuler-release"], + "cleaned_rpm": ret.get("src_post_delete_pkg", list())} + if os.path.exists(local_upgrade_json_path): + os.remove(local_upgrade_json_path) + flags = os.O_WRONLY | os.O_CREAT + modes = stat.S_IWUSR | stat.S_IRUSR + with os.fdopen(os.open(local_upgrade_json_path, + flags, modes), "w+") as pkg_file: + pkg_info = json.dumps(pkg_info) + pkg_info = pkg_info.replace(" ", "") + pkg_file.write(pkg_info) + +if __name__ == '__main__': + if len(sys.argv) != 3: + exit(1) + + check_path = sys.argv[1] + if not os.path.exists(check_path): + exit(1) + + upgrade_json_path = os.path.realpath(sys.argv[2]) + extract_pkg_info(check_path, upgrade_json_path) \ No newline at end of file diff --git a/tools/update_os/install.sh b/tools/update_os/install.sh new file mode 100644 index 0000000000000000000000000000000000000000..34ee9d0fce7eef86dd923951e11d846afc250b7b --- /dev/null +++ b/tools/update_os/install.sh @@ -0,0 +1,235 @@ +#!/usr/bin/bash +currDir=`dirname $(readlink -f $0)` +driverName=$1 +fileType=$2 +filePath=$3 +postTest=$4 + +function install_tar() +{ + if test -z "`rpm -qa | grep tar-`" + then + dnf install -y tar + fi +} + +function rpm_install() +{ + oldfile=`modinfo -F filename $driverName` + newfile=`rpm -ql $filePath | grep ko` + rpm -ivh `basename $filePath` --force 2>&1 | tee tmp.log + if test $? -ne 0 + then + rm -rf tmp.log + echo "$driverName install failure." + exit 1 + fi + grep -qi -e error -e fail tmp.log + if test $? -eq 0 + then + rm -rf tmp.log + exit 1 + fi + rm -rf tmp.log + if test -n "$newfile" + then + rm -rf $oldfile + cp -rf $newfile `dirname $oldfile` + if test $postTest -eq 0 + then + rmmod $driverName + insmod "`dirname $oldfile`/`basename $newfile`" + if test $? -ne 0 + then + echo "$newfile insmod failure..." + exit 1 + fi + fi + fi +} + +function ensure_env() +{ + dependent="" + for d in $@ + do + rpm -qa | grep -q $d + if test $? -ne 0 + then + dependent="$dependent $d" + fi + done + if test -n "$dependent" + then + yum install -y $dependent + fi +} + + +function do_rpm_install() +{ + case $driverName in + qla2xxx) + ensure_env dkms + rpm_install + ;; + *) + rpm_install + ;; + esac +} + +function do_tar_gz_install() +{ + case $driverName in + qla2xxx) + ;; + lpfc) + rm -rf $currDir/tmp + mkdir -p $currDir/tmp + tar -xzvf `basename $filePath` -C $currDir/tmp + cd $currDir/tmp/* + chmod a+x elx_lpfc_install.sh && ./elx_lpfc_install.sh + cp -f ./extra/elx-lpfc/lpfc.ko `modinfo -F filename $driverName` + if test $? -ne 0 + then + rm -rf $currDir/tmp + exit 1 + fi + dracut -f + rm -rf $currDir/tmp + ;; + *) + rpm_install + ;; + esac +} + +function do_tgz_install() +{ + case $driverName in + megaraid_sas) + oldfile=`modinfo -F filename $driverName` + rm -rf $currDir/tmp + mkdir -p $currDir/tmp + tar -xzvf `basename $filePath` -C $currDir/tmp + tmp_dir=$currDir/tmp/openEuler/rpms-2 + cd $tmp_dir + newfile=`rpm -ql ./*megaraid_sas*.rpm | grep ko` + rpm -ivh ./*megaraid_sas*.rpm --force 2>&1 | tee tmp.log + if test $? -ne 0 + then + rm -rf tmp.log + echo "$driverName install failure." + exit 1 + fi + grep -qi -e error -e fail tmp.log + if test $? -eq 0 + then + rm -rf tmp.log + exit 1 + fi + rm -rf tmp.log + if test -n "$newfile" + then + cp -rf $newfile `dirname $oldfile` + fi + ;; + mlx5_core) + ensure_env elfutils-devel python3-devel lsof createrepo pciutils-devel fuse-devel tcsh + ensure_env patch gdb-headless rpm-build make gcc + ensure_env python3-unversioned-command + + rm -rf $currDir/tmp + mkdir -p $currDir/tmp + tar -xzvf `basename $filePath` -C $currDir/tmp + cd $currDir/tmp/* + chmod a+x mlnxofedinstall && ./mlnxofedinstall --add-kernel-support + if test $? -eq 0 + then + dracut -f + /etc/init.d/openibd restart + rm -rf $currDir/tmp + else + rm -rf $currDir/tmp + exit 1 + fi + ;; + lpfc) + rm -rf $currDir/tmp + mkdir -p $currDir/tmp + tar -xzvf `basename $filePath` -C $currDir/tmp + cd $currDir/tmp/* + chmod a+x elx_lpfc_install.sh && ./elx_lpfc_install.sh + if test $? -ne 0 + then + rm -rf $currDir/tmp + exit 1 + fi + + oldfile=`modinfo -F filename $driverName` + newfile=`rpm -ql lpfc-openEuler20-12.8.340.17-ds/kmod-elx-lpfc-12.8.340.17-1.openEuler20.03.aarch64.rpm | grep ko` + rm -rf $oldfile + cp -rf $newfile $oldfile + dracut -f + rm -rf $currDir/tmp + ;; + *) + rpm_install + ;; + esac +} + +function do_run_install() +{ + case $driverName in + nvidia) + rmmod nouveau > /dev/null 2>&1 + bash `basename $filePath` --silent + if test $? -ne 0 + then + exit 1 + fi + ;; + cuda) + rmmod nouveau > /dev/null 2>&1 + bash `basename $filePath` --silent + if test $? -ne 0 + then + exit 1 + fi + ;; + *) + bash `basename $filePath` --silent + ;; + esac +} + +function do_install() +{ + install_tar + +# driverName=$1 +# fileType=$2 +# filePath=$3 + cd `dirname $filePath` + case $fileType in + rpm) + do_rpm_install + ;; + tar.gz) + do_tar_gz_install + ;; + tgz) + do_tgz_install + ;; + run) + do_run_install + ;; + *) + echo "not supported driver filetype: $fileType for driver $driverName" + ;; + esac +} + +do_install diff --git a/tools/update_os/rollback_consistency.sh b/tools/update_os/rollback_consistency.sh new file mode 100644 index 0000000000000000000000000000000000000000..30fb95510180d550975ca5ca451ee5b406350e51 --- /dev/null +++ b/tools/update_os/rollback_consistency.sh @@ -0,0 +1,70 @@ +#!/bin /bash +# Error return code +SUCCESS=0 +DIR_NO_EXIST=1 +DIR_ALREADY_EXIST=2 +function os_infomation() +{ + local dir=$1 + rpm -qa > $dir/rpm_list.log + rpm -qa | xargs rpm -qc | xargs md5sum > $dir/rpm_config_list.log + systemctl lists-units --all > $dir/service_list.log + sysctl -a > $dir/kernel_parameters.log + tree / > $dir/tree.log +} + +function diff_check() +{ + local dir=$1 + local result_path=$dir/result.log + echo '============rpm_list============' >> $result_path + diff $dir/pre_upgrade/rpm_list.log $dir/after_rollback/rpm_list.log >> $result_path + echo '============rpm_config_list============' >> $result_path + diff $dir/pre_upgrade/rpm_config_list.log $dir/after_rollback/rpm_config_list.log >> $result_path + echo '============service_list============' >> $result_path + diff $dir/pre_upgrade/service_list.log $dir/after_rollback/service_list.log >> $result_path + echo '============kernel_parameters============' >> $result_path + diff $dir/pre_upgrade/kernel_parameters.log $dir/after_rollback/kernel_parameters.log >> $result_path + echo '============tree============' >> $result_path + diff $dir/pre_upgrade/tree.log $dir/after_rollback/tree.log >> $result_path + echo "diff result path: $result_path" +} + +function main() +{ + local cmd=$1 + local bak_dir=$2 + case $cmd in + pre-upgrade) + if [ -d $bak_dir ];then + echo "dir is exists, please check" + return $DIR_ALREADY_EXIST + fi + mkdir $bak_dir + local pre_upgrade_dir=$bak_dir/pre_upgrade + mkdir $pre_upgrade_dir + os_infomation $pre_upgrade_dir + ;; + after-rollback) + if [ ! -d $bak_dir ];then + echo "os information is not backed up before upgrading" + return $DIR_NO_EXIST + fi + local after_rollback_dir=$bak_dir/after_rollback + mkdir $after_rollback_dir + os_infomation $after_rollback_dir + ;; + os-check) + if [ ! -d $bak_dir ] || [ ! -d $bak_dir/pre_upgrade ] || [ ! -d $bak_dir/after_rollback ];then + echo "dir does not exist, please check" + return $DIR_NO_EXIST + fi + diff_check $bak_dir + ;; + *) + echo "please check parameters: pre-upgrade or after-rollback or os-check" + esac + return $SUCCESS +} + +main "$@" \ No newline at end of file diff --git a/tools/update_os/ssh.py b/tools/update_os/ssh.py new file mode 100644 index 0000000000000000000000000000000000000000..1ffffd6b2050d02827c4637bc1e084e977b1b402 --- /dev/null +++ b/tools/update_os/ssh.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" +Copyright: Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved +Create: 2022/12/19 +Content: +""" + +#导入paramiko,(导入前需要先在环境里安装该模块) +import paramiko + + +#定义函数ssh,把操作内容写到函数里 +class SSHConnect: + + def __init__(self, hostname: str, port: str, username: str, password: str): + #ip地址 + self.hostname = hostname + # 端口号 + self.port = port + #用户名 + self.username = username + #密码 + self.password = password + + def get_hostname(self): + return self.hostname + + def get_username(self): + return self.username + + def get_port(self): + return self.port + + def get_password(self): + return self.password + + +def login(ssh_connect: SSHConnect): + #定义一个变量ssh_clint + ssh_client = paramiko.SSHClient() + #使用cnnect类来连接服务器 + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + try: + ssh_client.connect(ssh_connect.hostname, + ssh_connect.port, + ssh_connect.username, + ssh_connect.password + ) + return ssh_client + except Exception as e: + raise Exception('连接服务器失败!') from e diff --git a/tools/update_os/upgrade.py b/tools/update_os/upgrade.py new file mode 100644 index 0000000000000000000000000000000000000000..f1dd077e76148e24e0c10ecdc5577d40da20bbbc --- /dev/null +++ b/tools/update_os/upgrade.py @@ -0,0 +1,95 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" +Copyright: Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved +Create: 2022/12/20 +Content: +""" +import logging +from ssh import SSHConnect, login + + +if __name__ == '__main__': + + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s %(filename)s \ + [line:%(lineno)d] \ + %(levelname)s %(message)s', + filename='check_pre_upgrade.log', + filemode='w', + ) + + logger = logging + + UPGRADE_PKG_PATH = '/opt/x2openEuler-upgrade\ + /x2openEuler-upgrade-1.1.3-33.x86_64.rpm' +#创建ssh对象 + ssh_info = SSHConnect('192.168.137.xx', + '22', + 'root', + 'xxx') + #获取ssh连接 + ssh_client = login(ssh_info) + if ssh_client is None: + logger.error('ssh connect failed') + exit() + else: + logger.info('ssh connect successd') + + #获取ftp工具 + ftp_client = ssh_client.open_sftp() + if ftp_client is None: + logger.error('get ftp client failed') + exit() + else: + logger.info('get ftp client successd') + + #1.传输upgrade包到client端 + + try: + put_info = ftp_client.put(UPGRADE_PKG_PATH, '/root', confirm=True) + except Exception: + logger.error('upload failed') + exit() + logger.info('upload success') + + #2.安装client包 + stdin, stdout, stderr = \ + ssh_client.exec_command(f'yum install -y {UPGRADE_PKG_PATH}') + if not stdout: + logger.error('install x2openEuler-upgrade failed') + exit() + else: + logger.info('install x2openEuler-upgrade success') + + # 3.环境变量生效 + stdin, stdout, stderr = ssh_client.exec_command(f'source /root/.bashrc') + if not stdout: + logger.error('validate environment variable failed') + exit() + else: + logger.info('validate environment variable success') + + # 4.执行升级任务 + cmd = ['nohup', 'sh', '/usr/bin/centos2openEuler', + 'upgrade', 'upgrade.json', 'migrate-2003.repo', + '/usr,/run,/boot,/var,/etc', 'empty_dir', + '/.osbak', '> upgrade.log'] + stdin, stdout, stderr = ssh_client.exec_command(cmd) + if not stdout: + logger.error('upgrade fail, please check log') + exit() + else: + logger.info('end of upgrade') + + # 5.检查系统 + stdin, stdout, stderr = ssh_client.exec_command('cat /etc/os-release') + if not stdout: + logger.error('command failed') + exit() + else: + logger.info('command success') + if 'openEuler' in stdout.readlines(): + logger.info('upgrade success') + exit() \ No newline at end of file