# -*- coding: UTF-8 -*-
"""
@desc: 检查升级过程中ibase无法连接问题
"""


from java.lang import Exception as JException

from common import cliUtils, constant
from common.baseFactory import log

import time
import traceback
import re


class DefunctProcessCheck:
    """
    检查升级过程中ibase无法连接问题
    """

    def __init__(self, data_dict):
        self.data_dict = data_dict
        self.cli = data_dict.get("ssh")
        self.lang = self.data_dict.get("lang")

    def execute(self):
        if not self.is_risk_defunct_process_version() or self.data_dict.get(
            "repair_process"
        ):
            return

        id_list, in_mini_mode = self.query_i_base_defunct_process()
        log.error(
            self.data_dict,
            "query ibase process res:{},{}".format(id_list, in_mini_mode),
        )

        if not id_list:
            if not in_mini_mode:
                cliUtils.back_to_normal_mode_from_other_model(self.cli)
            return

        self.repair_i_base_process(in_mini_mode, id_list)
        self.data_dict["repair_process"] = True

        if not in_mini_mode:
            cliUtils.back_to_normal_mode_from_other_model(self.cli)

    def is_risk_defunct_process_version(self):
        """
        是否僵尸进程风险版本
        :return:
        """
        risk_version_list = ("V300R006C20", "V500R007C10")
        product_version = str(self.data_dict.get("dev").getProductVersion())
        risk_flag = product_version in risk_version_list
        log.info(
            self.data_dict, "is risk defunct process ver:{}".format(risk_flag)
        )
        return risk_flag

    def query_i_base_defunct_process(self):
        """
        查询是否存在僵尸进程
        :return:
        """
        try:
            ret = self.cli.execCmd("show system general")
            in_mini_system_mode = cliUtils.isInMinisystemMode(ret)
            cmd = "ps -C ibase"
            __, ret, __ = cliUtils.excuteCmdInMinisystemModel(
                self.cli, cmd, self.lang)
            re_string = "(\d+).*ibase\s*<defunct>"
            return re.compile(re_string).findall(ret), in_mini_system_mode
        except (JException, Exception):
            log.error(
                self.data_dict,
                "query_i_base_defunct_process except:{}".format(
                    traceback.format_exc()
                ),
            )
            return list(), False

    def repair_i_base_process(self, in_mini_system_mode, id_list):
        """
        修复ibase进程
        cli模式:reboot ism
        minisystem模式：kill -9 进程id
        1.	cli命令 reboot ism 返回值：Command executed successfully. 才算成功，
        如果执行失败超过3次都失败就返回，不再执行。
        :param in_mini_system_mode:
        :param id_list:
        :return:
        """
        retry_time = 3
        try:

            if in_mini_system_mode:
                for process_id in id_list:
                    cmd = "kill -9 {}".format(process_id)
                    __, ret, __ = cliUtils.excuteCmdInMinisystemModel(
                        self.cli, cmd, self.lang)
                    log.info(self.data_dict, "kill -9 ret:[{}]".format(ret))
                    self.__execute_y_cmd(ret)
                return

            for i in range(retry_time):
                # 退到developer
                cliUtils.mini_system_to_developer(self.cli)
                cmd = "reboot ism"
                ret = self.cli.execCmd(cmd)
                self.__execute_y_cmd(ret)
                if cliUtils.isExecuteCmdSuccess(ret):
                    log.info(self.data_dict, "repair ibase process success!")
                    return
                log.error(
                    self.data_dict, "repair fail! retry times:{}".format(i)
                )
                time.sleep(constant.UPGRADE_REBOOT_AFTER_CONNECT_INTERVAL)
        except (JException, Exception):
            log.error(
                self.data_dict,
                "repair_i_base_process except:{}".format(
                    traceback.format_exc()
                ),
            )

    def __execute_y_cmd(self, ret):
        """
        执行y
        :param ret:
        :return:
        """
        while "y/n" in ret:
            ret = self.cli.execCmd("y")
