# -*- coding: UTF-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import re
import utils.common.log as logger
from utils.common.exception import FCDException
from utils.common.fic_base import StepBaseInterface
from utils.common.ssh_util import Ssh as ssh
from plugins.DistributedStorage.scripts.utils.common.separate_storage_node_check_network import get_bmc_ip


class ExecCmd:
    @classmethod
    def check_fsadmin(cls, client):
        cmd = "id fsadmin;echo last_result=$?"
        resp = ssh.ssh_exec_command_return(client, cmd, retry_times=3)
        return str(resp).__contains__("last_result=0")

    @classmethod
    def check_switch_root(cls, client, root_pwd):
        try:
            ssh.ssh_send_command(client, "su - root", "Password:", timeout=30)
        except FCDException as e:
            client.clear()
            logger.error("Switch root fail. Not get expected output,detail: %s" % str(e))
            return False
        try:
            ssh.ssh_send_command(client, root_pwd, "#", timeout=30)
        except FCDException as e:
            client.clear()
            logger.error("Switch root fail. Not get expected output,detail: %s" % str(e))
            return False
        return True

    @classmethod
    def check_language(cls, client):
        pattern = re.compile("zh_CN")
        cmd = "echo $LANG"
        try:
            resp = ssh.ssh_exec_command_return(client, cmd, retry_times=3)
        except FCDException as e:
            logger.error("[FSBR] Check language fail.detail: %s" % str(e))
            return False
        result = ''.join(resp)
        logger.info("[FSBR] exec command success. detail:%s" % result)
        if pattern.findall(result):
            return False
        return True

    @classmethod
    def create_client(cls, host_ip, username, passwd):
        return ssh.ssh_create_client(host_ip, username, passwd)

    @classmethod
    def close_client(cls, client):
        ssh.ssh_close(client)


class SystemCheck(StepBaseInterface):
    def __init__(self, project_id, pod_id, db):
        super(SystemCheck, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = db
        self.fsadmin_fail_list = list()
        self.switch_fail_list = list()
        self.language_fail_list = list()
        self.bmc_confirm_fail_list = list()
        self.bmc_info_lists = self.db.get_install_os_list_info(self.pod_id)

    def procedure(self):
        for bmc_info in self.bmc_info_lists:
            logger.info("bmc_ip:%s Mem check" % bmc_info['bmc_ip'])
            creuser_info = bmc_info['creuser'].split(',')
            datamover_ip = bmc_info["manageIp"].split("/")[0]
            exec_obj = ExecCmd()
            client = exec_obj.create_client(datamover_ip, creuser_info[2], creuser_info[3])
            # 检查切root
            result = exec_obj.check_switch_root(client, creuser_info[1])
            if not result:
                self.switch_fail_list.append(datamover_ip)
            else:
                self._check_bmc_ip_consistent(bmc_info, client)
            if client['channel'].closed:
                client = exec_obj.create_client(datamover_ip, creuser_info[2], creuser_info[3])
                exec_obj.check_switch_root(client, creuser_info[1])
            # 检查语言
            logger.info("Check the language configuration of the node:[{}]".format(datamover_ip))
            result = exec_obj.check_language(client)
            if not result:
                self.language_fail_list.append(datamover_ip)
            # 校验fsadmin用户可登陆性
            logger.info("Check whether the fsadmin user exists on the node:[{}]".format(datamover_ip))
            if not exec_obj.check_fsadmin(client):
                self.fsadmin_fail_list.append(datamover_ip)
            exec_obj.close_client(client)
        self.error_msg_handle()
        logger.info("Finish to check and config configuration items on all host")

    def error_msg_handle(self):
        if self.bmc_confirm_fail_list:
            curr_bmc_list = list()
            target_bmc_list = list()
            for curr_bmc, target_bmc in self.bmc_confirm_fail_list:
                curr_bmc_list.append(curr_bmc)
                target_bmc_list.append(target_bmc)
            current_bmc = ','.join(curr_bmc_list)
            target_bmc = ','.join(target_bmc_list)
            raise FCDException(626107, current_bmc, target_bmc)

        if self.language_fail_list and self.switch_fail_list:
            msg = "[FSBR] Check switch root and language fail.detail: switch fail list:%s,language fail list: %s" \
                  % (self.switch_fail_list, self.language_fail_list)
            logger.error(msg)
            raise FCDException(626042, str(self.switch_fail_list), str(self.language_fail_list))

        if self.switch_fail_list:
            logger.error("[FSBR] check switch root fail,fail list: %s" % str(self.switch_fail_list))
            raise FCDException(626041, str(self.switch_fail_list))

        if self.language_fail_list:
            logger.error("[FSBR] check system default language fail,fail list: %s" % str(self.language_fail_list))
            raise FCDException(626043, str(self.language_fail_list))

        if self.fsadmin_fail_list:
            logger.error("[FSBR] Failed to login with username <fsadmin> on hosts[%s]" % self.fsadmin_fail_list)
            raise FCDException(626334, str(self.fsadmin_fail_list))

    def _check_bmc_ip_consistent(self, bmc_info, client):
        """
        切root成功后，才能检查目标节点一致性
        """
        current_node_bmc_ip = get_bmc_ip(client)
        target_node_bmc_ip = bmc_info["bmc_ip"]
        logger.info("This is the current node BMC IP[%s] "
                    "and the target node BMC IP[%s]." % (current_node_bmc_ip, target_node_bmc_ip))
        # 检查节点BMC IP是否与目标节点一致
        if current_node_bmc_ip != target_node_bmc_ip:
            err_msg = "The BMC IP[%s] of the current node is inconsistent with the BMC IP[%s] of the node" \
                      " in the installation system." % (current_node_bmc_ip, target_node_bmc_ip)
            logger.info(err_msg)
            self.bmc_confirm_fail_list.append((current_node_bmc_ip, target_node_bmc_ip))
