#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
VRM服务模块
"""
import os
import re
import time

from server.constant import INSTALL_INFO_FILE, ENV_CONSTANT
from installer.components.local_info import LOCAL_INFO
from installer.components.vrm_static import VRM_STATIC_INFO
from installer.components.vrm.params import PARAMS
from installer.constants import system
from installer.constants.vrm import CREATE_IPTABLES_TASK
from installer.constants.file import CONFIG_FILE_MODES, CREATE_WRITE_FLAGS, SECRET_FILE_MODES
from installer.framework.error import ProcessError, ServiceError
from installer.framework.service import Service
from installer.utils import log
from installer.utils.ip import explod_ip
from installer.utils.file import add_or_delete_line_in_file, delete_file_or_dir, write_file, uncompress, \
    replace_string_in_file, move_file, chown_file, mkdir, copy_file, copy_dir, chmod_file, load_json_file, FileError
from installer.utils.kmc import decrypt
from installer.utils.shell import run_cmd_force, run_cmd_result, run_cmd_status, run_commands_with_pipe, RemoteClient
from installer.utils.node import open_node_root_right, open_sftp

OM_COMMON = '/opt/galax/vrm/om/common'
OM_COMMON_BAK = '/opt/galax/vrm/om/common_bak'
OM_OLM_DIR = '/opt/galax/vrm/om/olmbackup'
OM_TEMP_DIR = '/opt/galax/vrm/om/temp'

VRM_STOP = 'systemctl stop vrmd'
VRM_RESTART = 'systemctl restart vrmd'
VRM_STATUS = 'systemctl status vrmd'

VRM_GATEWAY_OLD = 'address="127.0.0.1"'
VRM_GATEWAY_NEW = ''
VRM_DELETE_LINE = 'className="org.apache.catalina.security.SecurityListener"'
VRM_SERVER_XML = '/opt/galax/vrm/tomcat/conf/server.xml'

VRM_FMC_DIR = '/etc/galax/fmc/'
VRM_SNMP_CONFIG_FILE = '/etc/galax/fmc/snmp.properties'
VRM_SNMP_CONFIG = '#bootsTimes\n#Thu Aug 03 23:03:01 GMT+08:00 2017\n' \
                  'ENGINE_ID=7c2556ece0b343b5a6d03228e46b56d7\n'
VRM_VRM_DIR = '/etc/galax/vrm'

VRM_MGNT_COFNIG_FILE = '/opt/galax/root/vrm/tomcat/script/nrm/getMgntIP.sh'
VRM_MGNT_COFNIG = 'echo 127.0.0.1'

VRM_CONFIG_FILE = '/opt/galax/vrm/tomcat/webapps/ROOT/WEB-INF/classes/vrmconfig.properties'
MAC_CONFIG_FILE = '/opt/galax/vrm/tomcat/webapps/ROOT/WEB-INF/classes/macConfig.properties'
VRM_CONFIG_OLD = 'SUPPORT_REDUCE_MANAGER_RES=false'
VRM_CONFIG_NEW = 'SUPPORT_REDUCE_MANAGER_RES=true'
VRM_CONFIG_BOOT_OPTION_OLD = 'BOOT_OPTION=local_disk_boot'
VRM_CONFIG_BOOT_OPTION_NEW = 'BOOT_OPTION=iscsi_san_boot'
MAC_CONFIG_START_OLD = 'DEFAULT_BEGIN_MAC=28:6E:D4:88:C6:29'
MAC_CONFIG_END_OLD = 'DEFAULT_END_MAC=28:6E:D4:8A:39:40'
VRM_CONFIG_CIPHER_MODE = 'CIPHER_MODE='

VRM_SH_FILE = '/opt/galax/root/vrm/tomcat/script/vrm.sh'

VRM_WAR = '/opt/galax/vrm/tomcat/webapps/ROOT.war'
VRM_WAR_DIR = '/opt/galax/vrm/tomcat/webapps/ROOT'

VRM_DIR = '/opt/galax/vrm/tomcat'
VRM_DIR_ROOT = '/opt/galax/root'
VRM_LOG_DIR = '/opt/galax/vrm/logs'
VRM_SERVICE_DIR = '/sys/fs/cgroup/cpuset/system.slice/system-hostos.slice/vrmd.service/'
VRM_LOG_DIR = '/var/log/galaxenginelog/vrm'
OMS_LOG_DIR = '/var/log/galaxenginelog/oms'

VRMD_SERIVCE_FILE = '/usr/lib/systemd/system/vrmd.service'
VRMD_CPULIMIT_CGROUP = 'ExecStartPre=/usr/bin/sh /opt/galax/root/vrm/tomcat/script/setCpuLimit.sh cgroup vrmd'
VRMD_CPULIMIT_MEMS = 'ExecStartPre=/usr/bin/sh /opt/galax/root/vrm/tomcat/script/setCpuLimit.sh mems vrmd'
VRMD_CPULIMIT_CPUS = 'ExecStartPre=/usr/bin/sh /opt/galax/root/vrm/tomcat/script/setCpuLimit.sh cpus vrmd'
VRMD_CPULIMIT_TASKS = 'ExecStartPost=/usr/bin/sh /opt/galax/root/vrm/tomcat/script/setCpuLimit.sh tasks vrmd $MAINPID'

PMC_DIR = '/opt/galax/vrm/om/pmc'
FMC_DIR = '/opt/galax/vrm/om/fms'
PMC_PROPERTIES = '/opt/galax/vrm/om/pmc/config/pmconfig.properties'
FMC_PROPERTIES = '/opt/galax/vrm/om/fms/config/fmconfig.properties'
CMS_PROPERTIES = '/etc/galax/cms/config.properties'
COMMON_CERTS = "/etc/galax/certs/"
GEN_CERT = "sh /opt/galax/vrm/om/cert/scripts/gencert.sh"
WEB_SERVER_XML = '/etc/galax/portal/conf/server.xml'
GAUSS_SERVER_CERT = "/opt/gaussdb/servercert/"
GAUSS_CLIENT_CERT = "/opt/gaussdb/servercert/"
HA_CERT = "/opt/omm/ha/local/cert/"

GAUSSDB_STATUS = 'su - postgres -s /bin/bash -c \"gs_ctl status\"'
GAUSS_ROOT_DIR = "/opt/gaussdb"
GAUSS_CLIENTCERT_DIR = f"{GAUSS_ROOT_DIR}/clientcert/"
GAUSS_SERVERCERT_DIR = f"{GAUSS_ROOT_DIR}/servercert/"

POSTGRES_HOME = '/home/postgres/db'
VRM_SQL_FILE = '/opt/galax/root/vrm/tomcat/script/vrm.sql'
TBL_SQL_FILES = '/opt/galax/root/vrm/tomcat/script/omsconfig/db'
PRIV_SQL_FILE = '/opt/galax/vrm/tomcat/script/obj_priv.sql'
VMTOOLS_DIR = ENV_CONSTANT.PACKAGE_UPDATE_PATH + "/vmtools"
VMTOOLS_RPM_DIR = "/opt/galax/patch/internal/vmtools"
VMTOOLS_RPM_CNA_DIR = "/opt/patch/programfiles/vmtools"


class VrmService(Service):
    """
    VRM服务类
    """

    def __init__(self, name: str):
        super().__init__(name)
        self.package_name = ''
        self.oms_package_name = ''
        self.local_ip = ''
        self.cna_master_ip = ''
        self.cna_slave_ip = ''

    def install_check(self):
        self.find_pacakge()
        self.local_ip = explod_ip(LOCAL_INFO.ip)
        self.cna_master_ip = explod_ip(PARAMS.cna.master_ip)
        if PARAMS.is_double():
            self.cna_slave_ip = explod_ip(PARAMS.cna.slave_ip)

    def install_deploy(self) -> None:
        # 备份/opt/galax/vrm/om/common
        move_file(OM_COMMON, OM_COMMON_BAK)

        rpm_path = f'{system.DEPENDENCIES_DIR}/{self.package_name}'
        # vrm rpm，忽略冲突的部分
        cmd = f"rpm -ivh --excludepath=/opt/galax/vrm/om/ --replacefiles {rpm_path}"
        log.info("install vrm command: " + cmd)
        if not run_cmd_status(cmd, shell=False):
            log.error('vrm rpm install failed')
            raise ServiceError('300102')
        rpm_path = f'{system.DEPENDENCIES_DIR}/{self.oms_package_name}'
        cmd = f"rpm -ivh --force --excludepath=/opt/galax/vrm/om/ --replacefiles {rpm_path}"
        log.info("install oms command: " + cmd)
        if not run_cmd_status(cmd, shell=False):
            log.error('oms rpm install failed')
            raise ServiceError('300102')

    def install_config(self) -> None:
        # 停止服务
        if not run_cmd_status(VRM_STOP):
            log.error('vrm rpm install failed')
            raise ServiceError('300102')
        # 设置环境变量MALLOC_ARENA_MAX，防止在多线程并发申请内存的场景下虚拟内存暴涨
        cmd = "sed -i -E '/\#\!\/bin\/sh/a\export\ MALLOC_ARENA_MAX=1' /opt/galax/vrm/tomcat/bin/catalina.sh"
        run_cmd_force(cmd)
        # 配置server.xml
        add_or_delete_line_in_file(VRM_DELETE_LINE, VRM_SERVER_XML, True)
        # 统一gateway需要删除address信息
        replace_string_in_file(VRM_GATEWAY_OLD, VRM_GATEWAY_NEW, VRM_SERVER_XML)
        # 初始化数据库
        copy_dir(TBL_SQL_FILES, POSTGRES_HOME, overwrite=False)
        copy_file(VRM_SQL_FILE, f'{POSTGRES_HOME}/vrm.sql')
        copy_file(PRIV_SQL_FILE, f'{POSTGRES_HOME}/obj_priv.sql')
        chown_file(POSTGRES_HOME, 'postgres', 'postgres', recursive=True)
        chmod_file(POSTGRES_HOME, 0o700, recursive=True)

        vrm_sql_cmd = [f'echo {VRM_STATIC_INFO.db_pwd}', 'su - postgres -c "/home/postgres/vrm_db.sh"']
        status, _ = run_commands_with_pipe(vrm_sql_cmd, nolog=True)
        if not status:
            log.error('init gaussdb failed')
            raise ServiceError('300102')
        # 修改SNMP
        write_file(VRM_SNMP_CONFIG_FILE, CREATE_WRITE_FLAGS, CONFIG_FILE_MODES, VRM_SNMP_CONFIG)
        # 修改获取管理IP脚本
        write_file(VRM_MGNT_COFNIG_FILE, CREATE_WRITE_FLAGS, CONFIG_FILE_MODES, VRM_MGNT_COFNIG)
        # 修改VRM配置文件
        uncompress(VRM_WAR, VRM_WAR_DIR, 'zip')
        replace_string_in_file('su fcs -s /bin/bash -c', 'su root -c', VRM_SH_FILE)
        replace_string_in_file(VRM_CONFIG_OLD, VRM_CONFIG_NEW, VRM_CONFIG_FILE)
        if PARAMS.is_iscsi_san_boot():
            replace_string_in_file(VRM_CONFIG_BOOT_OPTION_OLD, VRM_CONFIG_BOOT_OPTION_NEW, VRM_CONFIG_FILE)
        replace_string_in_file(VRM_CONFIG_CIPHER_MODE, VRM_CONFIG_CIPHER_MODE + PARAMS.vrm.cipher_mode, VRM_CONFIG_FILE)

        # 虚拟机MAC段范围
        try:
            json_obj = load_json_file(INSTALL_INFO_FILE)
            mac_start_addr = json_obj.get('setVrmInfo', {}).get('startMAC')
            mac_end_addr = json_obj.get('setVrmInfo', {}).get('endMAC')
            if mac_start_addr and mac_end_addr:
                replace_string_in_file(MAC_CONFIG_START_OLD, f'DEFAULT_BEGIN_MAC={mac_start_addr}', MAC_CONFIG_FILE)
                replace_string_in_file(MAC_CONFIG_END_OLD, f'DEFAULT_END_MAC={mac_end_addr}', MAC_CONFIG_FILE)
        except FileError:
            log.info(f'load file {INSTALL_INFO_FILE} fail')

        # 修改vrmd.service文件
        add_or_delete_line_in_file(VRMD_CPULIMIT_CGROUP, VRMD_SERIVCE_FILE, True)
        add_or_delete_line_in_file(VRMD_CPULIMIT_MEMS, VRMD_SERIVCE_FILE, True)
        add_or_delete_line_in_file(VRMD_CPULIMIT_CPUS, VRMD_SERIVCE_FILE, True)
        add_or_delete_line_in_file(VRMD_CPULIMIT_TASKS, VRMD_SERIVCE_FILE, True)
        cmd = f"sed -i '/\[Service\]/a\Slice=user.slice' {VRMD_SERIVCE_FILE}"
        run_cmd_force(cmd)
        if not run_cmd_status('systemctl daemon-reload'):
            log.error('reload systemd failed')
            raise ServiceError('300102')
        # 修改FMWS与PMWS thrift配置
        self.update_certs()
        # 开启国密，且存在加密机信息。上传证书到加密机
        if not PARAMS.is_general_cipher_mode() and PARAMS.vrm.hsm_company == 'Sansec' and PARAMS.vrm.hsm_account:
            self.upload_crt_to_hsm()
        # x86场景下处理vmtools的包
        self.deal_vmtools_pacakge()
        # 在检查和配置主机前，先更新iptables规则，保证后续节点间通信链路稳定
        if not run_cmd_status(CREATE_IPTABLES_TASK):
            log.error('Update MCNA iptables failed.')
            raise ProcessError('300102')

    def install_start(self):
        if not VrmService.restart_vrm():
            raise ServiceError('300102')

    def uninstall_check(self):
        self.find_pacakge()

    def uninstall_stop(self):
        run_cmd_force(VRM_STOP, nolog=self.nolog)

    def uninstall_clear(self):
        delete_file_or_dir('/etc/galax/fmc')
        delete_file_or_dir('/etc/galax/data/hostinfo')
        # vrm 安装时添加
        add_or_delete_line_in_file('/opt/galax/root/vrm/tomcat/script/tls/auth_ca.sh', '/etc/crontab', is_delete=True)
        # 基线版本【8.0.0】为gandalf，8.0.0.SPC1修改权限为root
        chown_file('/opt/galax/data', 'root', 'root')
        chown_file('/opt/galax/data/storage', 'root', 'root')

    def uninstall_remove(self) -> None:
        rpm_name = self.package_name[:len(self.package_name) - 4]
        if not run_cmd_status(f'rpm -e {rpm_name}', shell=False, nolog=self.nolog):
            # 删除失败尝试强制删除
            run_cmd_force(f'rpm -e {rpm_name} --noscripts --nodeps', shell=False)
        # 删除 oms
        rpm_name = self.package_name[:len(self.oms_package_name) - 4]
        if not run_cmd_status(f'rpm -e {rpm_name}', shell=False):
            # 删除失败尝试强制删除
            run_cmd_force(f'rpm -e {rpm_name} --noscripts --nodeps', shell=False)
        # 删除 oms
        rpm_name = self.package_name[:len(self.oms_package_name) - 4]
        if not run_cmd_status(f'rpm -e {rpm_name}', shell=False):
            # 删除失败尝试强制删除
            run_cmd_force(f'rpm -e {rpm_name} --noscripts --nodeps', shell=False)
        delete_file_or_dir(VRM_DIR_ROOT)
        delete_file_or_dir(VRM_DIR)
        delete_file_or_dir(OM_OLM_DIR)
        delete_file_or_dir(OM_TEMP_DIR)
        delete_file_or_dir(FMC_DIR)
        delete_file_or_dir(PMC_DIR)
        # 恢复/opt/galax/vrm/om/common
        move_file(OM_COMMON_BAK, OM_COMMON)
        chown_file(OM_COMMON, 'root', 'root', True)
        delete_file_or_dir(VRM_LOG_DIR)
        # vrm增加了资源隔离，而在安装过程中不应有该配置
        delete_file_or_dir(VRM_SERVICE_DIR)
        delete_file_or_dir(VRMD_SERIVCE_FILE)
        # 删除vrm服务在CNA生成的日志
        delete_file_or_dir(VRM_LOG_DIR)
        delete_file_or_dir(OMS_LOG_DIR)
        delete_file_or_dir(VRM_VRM_DIR)
        # 删除vmtools包目录
        delete_file_or_dir(VMTOOLS_RPM_DIR)
        # 清理rest.conf
        add_or_delete_line_in_file('password=', system.FILE_HTTP_CONFIG, True)
        add_or_delete_line_in_file(f'password_plain=', system.FILE_HTTP_CONFIG, True)
        if not run_cmd_status('systemctl reset-failed vrmd', nolog=self.nolog):
            run_cmd_force('systemctl reset-failed vrmd', nolog=self.nolog)
        self.clear_certs()
        self.delete_local_cna_iptables()

    # 安装工具所在主机如果不是主备主机，需要清理该主机上iptables规则，否则添加至其他集群会失败
    def delete_local_cna_iptables(self) -> None:
        need_delete_flag = False
        if PARAMS.is_double():
            log.info(f'local_ip: {self.local_ip}, cna_master_ip: {self.cna_master_ip},'
                     f' cna_slave_ip: {self.cna_slave_ip}')
            if self.local_ip and self.local_ip != self.cna_master_ip and self.local_ip != self.cna_slave_ip:
                need_delete_flag = True
        else:
            log.info(f'local_ip: {self.local_ip}, cna_master_ip: {self.cna_master_ip}')
            if self.local_ip and self.local_ip != self.cna_master_ip:
                need_delete_flag = True
        if need_delete_flag:
            log.info('local cna need to delete iptables.')
            if run_cmd_status("service iptables restart", nolog=self.nolog):
                if not run_cmd_status("iptables -F", nolog=self.nolog):
                    log.error('delete iptables failed.')
                    raise ProcessError('301201')
            log.info('delete iptables successfully.')

    def find_pacakge(self) -> None:
        if len(self.package_name) > 0:
            # 如果有就不找了
            return True
        package = f'GalaX-VRM-{LOCAL_INFO.version}(.*).rpm'
        pattern = re.compile(package)
        oms_package = f'oms-server-gw-(.*).rpm'
        oms_pattern = re.compile(oms_package)
        for file in os.listdir(system.DEPENDENCIES_DIR):
            if re.match(pattern, file):
                self.package_name = file
            if re.match(oms_pattern, file):
                self.oms_package_name = file
            if len(self.package_name) > 0 and len(self.oms_package_name) > 0:
                return True
        if self.package_name == '':
            log.error('Can not find the VRM package')
        if self.oms_package_name == '':
            log.error('Can not find the oms package')
        raise ServiceError('300102')

    def deal_vmtools_pacakge(self) -> None:
        """
        处理vmtools包，arm场景只往vrm上放置，x86还需要在主备主机上放置
        """
        if os.path.exists(VMTOOLS_DIR):
            package = f'(.*)_SIA-(.*)-GuestOSDriver_X86.zip'
            pattern = re.compile(package)
            vmtools_package = f'uvp-vmtools-(.*).rpm'
            vmtools_pattern = re.compile(vmtools_package)
            for file in os.listdir(VMTOOLS_DIR):
                if re.match(pattern, file) and file.endswith('zip'):
                    log.info('Find the vmtools zip success')
                    uncompress(f'{VMTOOLS_DIR}/{file}', VMTOOLS_DIR, 'zip')
                    log.info('Unzip the vmtools zip success')
            for file in os.listdir(VMTOOLS_DIR):
                if re.match(vmtools_pattern, file):
                    log.info('Find the vmtools package success')
                    # x86和arm均需要在当前假vrm上放置vmtools包，后续从假vrm上传输包到真正的主备vrm上
                    mkdir(VMTOOLS_RPM_DIR, 0o700)
                    copy_file(f'{VMTOOLS_DIR}/{file}', f'{VMTOOLS_RPM_DIR}/{file}')
                    chown_file(VMTOOLS_RPM_DIR, 'fcs', 'fusioncompute', True)
                    log.info('Deal the vmtools package success')
        else:
            if not LOCAL_INFO.is_arm():
                log.error('Current is x86 but no vmtools package exists.')
                raise ProcessError('300102')
            else:
                log.info('No need to deal with vmtools package')

    def update_certs(self) -> None:
        """
        更新证书文件
        """
        log.info("Start to generate new certs.")
        run_cmd_status(f"rm -fr {COMMON_CERTS}", shell=False)
        mkdir(HA_CERT, 0o700)
        mkdir(GAUSS_SERVER_CERT, 0o700)
        mkdir(GAUSS_CLIENT_CERT, 0o700)
        if not run_cmd_status(GEN_CERT, shell=False):
            log.error('Generate new certs failed.')
            raise ProcessError('300102')
        self.generate_gaussdb_key_password()
        write_file(FMC_PROPERTIES, CREATE_WRITE_FLAGS, SECRET_FILE_MODES, f"fmc.service.certPwd=")
        write_file(PMC_PROPERTIES, CREATE_WRITE_FLAGS, SECRET_FILE_MODES, f"pmc.collector.certPwd=")
        run_cmd_result("service vna-api restart", shell=False)
        log.info("Generate new certs successfully")

    def generate_gaussdb_key_password(self):
        for _ in range(10):
            if not run_cmd_status(GAUSSDB_STATUS):
                log.info('Gaussdb status is not ok, please wait a monent, and will retry.')
                time.sleep(10)
                continue
            status, pkpasswd = run_cmd_result(f'cat {GAUSS_SERVERCERT_DIR}pkpasswd', nolog=True)
            if not status:
                log.error(f'Get {GAUSS_SERVERCERT_DIR}pkpasswd failed.')
                raise ProcessError('300102')
            log.info(f'Get {GAUSS_SERVERCERT_DIR}pkpasswd successfully.')

            pkpasswd = decrypt(pkpasswd[0].strip())
            gen_server_cmd = [
                f'echo {pkpasswd}',
                f'su - postgres -s /bin/bash -c "gs_guc encrypt -M server -D {GAUSS_SERVERCERT_DIR} -k"'
            ]
            status, _ = run_commands_with_pipe(gen_server_cmd)
            if not status:
                log.error('encrypt server key password failed.')
                raise ProcessError('300102')
            log.info(f'encrypt server key password successfully.')
            gen_client_cmd = [
                f'echo {pkpasswd}',
                f'su - postgres -s /bin/bash -c "gs_guc encrypt -M client -D {GAUSS_CLIENTCERT_DIR} -k"'
            ]
            status, _ = run_commands_with_pipe(gen_client_cmd, nolog=True)
            if not status:
                log.error('encrypt client key password failed.')
                raise ProcessError('300102')
            log.info(f'encrypt client key password successfully.')
            return
        log.error('generate gaussdb key password failed.')
        raise ProcessError('300102')

    def upload_crt_to_hsm(self):
        for hsm_ip in [str(PARAMS.vrm.hsm_ip), str(PARAMS.vrm.hsm_ip_02)]:
            if not hsm_ip:
                continue
            remote_client = RemoteClient(hsm_ip, PARAMS.vrm.hsm_account, PARAMS.vrm.hsm_password)
            self.clean_old_crt(remote_client)
            self.upload_cer_file_to_hsm(remote_client)
            self.upload_pfx_file_to_hsm(remote_client)
            self.restart_hsm(remote_client)

    def clean_old_crt(self, remote_client):
        """上传证书前，需要把已经存在的证书删除，保证环境一致"""
        cmd_rm_cer = 'rm -f /mnt/linux/etc/certs/service_root.cer'
        cmd_rm_pfx = 'rm -f /mnt/linux/etc/certs/service.pfx'
        status, result = remote_client.exec_result(cmd_rm_cer, nolog=True)
        if not status:
            log.error('clean cer file fail')
            raise ProcessError('300102')
        status, result = remote_client.exec_result(cmd_rm_pfx, nolog=True)
        if not status:
            log.error('clean pfx file fail')
            raise ProcessError('300102')

    def upload_cer_file_to_hsm(self, remote_client):
        """上传可信证书链"""
        if not remote_client.sftp('/etc/galax/certs/kms-hsm/rootCA.cer', '/var/swhsm/rootCA.cer'):
            log.error('upload cer file to kms server fail')
            raise ProcessError('300102')
        expected_list = [
            ('hsmm\n', '欢迎使用', False, None),
            ('6', '密码服务', False, None),
            ('7', '密码服务证书', False, None),
            ('1', '请使用SCP工具将证书文件(*.cer)上传到目录/var/swhsm 。', False, None),
            ('1', '证书导入完成。', False, None)
        ]
        if not remote_client.expect(expected_list, nolog=True, expecte_mode='in', send_add_line_break=False):
            log.error('upload cer file to kms service fail')
            raise ProcessError('300102')

    def upload_pfx_file_to_hsm(self, remote_client):
        """上传服务证书"""
        if not remote_client.sftp('/etc/galax/certs/kms-hsm/server.pfx', '/var/swhsm/server.pfx'):
            log.error('upload pfx file to kms server fail')
            raise ProcessError('300102')
        with open('/etc/galax/certs/kms-hsm/pkpasswd') as f:
            password = f.read().strip()
        password = decrypt(password)
        expected_list = [
            ('hsmm\n', '欢迎使用', False, None),
            ('6', '密码服务', False, None),
            ('7', '密码服务证书', False, None),
            ('2', '请使用SCP工具将证书文件(*.pfx)上传到目录/var/swhsm 。', False, None),
            ('1', '输入证书口令。', False, None),
            ('\b' + password + '\n', '证书导入完成。', False, None)
        ]
        if not remote_client.expect(expected_list, nolog=True, expecte_mode='in', send_add_line_break=False):
            log.error('upload pfx file to kms service fail')
            raise ProcessError('300102')

    def restart_hsm(self, remote_client):
        """重启服务"""
        # 重启前查看服务状态，如果未启动则启动，启动则重启
        status, _ = remote_client.exec_result('netstat -nlp | grep 8008', nolog=True)
        expected_list = [
            ('hsmm\n', '欢迎使用', False, None),
            ('6', '密码服务', False, None),
        ]
        if status:
            expected_list.extend([
                ('4', '重新启动服务', False, None),
                ('2', '已启动', False, None),
            ])
        else:
            expected_list.extend([
                ('4', '启动密码服务', False, None),
                ('1', '已启动', False, None),
            ])
        if not remote_client.expect(expected_list, nolog=True, expecte_mode='in', send_add_line_break=False):
            log.error('restart kms service fail')
            raise ProcessError('300102')

    def clear_certs(self) -> None:
        """
        删除cna不使用的证书文件
        """
        log.info('Start to release unused certs.')
        delete_file_or_dir(GAUSS_SERVER_CERT)
        delete_file_or_dir(GAUSS_CLIENT_CERT)
        delete_file_or_dir("/opt/omm")
        for certs in ["migrate", "vnc", "vnc-proxy", "vrm", "web"]:
            delete_file_or_dir(os.path.join(COMMON_CERTS, certs))
        for root, _, files in os.walk(COMMON_CERTS):
            for filename in files:
                if filename.endswith(".sha256") or filename.endswith(".jks"):
                    delete_file_or_dir(os.path.join(root, filename))
        delete_file_or_dir(os.path.join(COMMON_CERTS, "vna-api/pkpasswd"))
        log.info('Release unused certs successfully.')

    @classmethod
    def restart_vrm(cls) -> bool:
        for _ in range(3):
            if not run_cmd_status(VRM_RESTART):
                log.error('restart vrm error')
                return False
            time.sleep(30)
            if run_cmd_status(VRM_STATUS):
                return True
        log.error('restart vrm status error')
        return False
