# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import traceback
import collections
from abc import ABC

import utils.common.log as logger
from utils.common.message import Message
from utils.common.error.hcci_error_code import get_code_msg
from utils.business.vm_util import can_vm_pinged_to
from utils.business.project_condition_utils import get_project_condition_boolean
from plugins.DistributedStorage.common.parameter_gain import ParamsGain
from plugins.DistributedStorage.common.rest_client import StorageSSHClient
from plugins.DistributedStorage.logic.sandbox_operate import SandBoxHandlerForUpgrade
from plugins.DistributedStorage.Upgrade.scripts.sub_job_disable_sandbox import DisableSandBoxStatusInf


class FSMConnCheckInf(DisableSandBoxStatusInf, ABC):
    """
    813之前的版本升级：要检查连通性，SSH登录性
    813之后的版本、一跳升级：要检查连通性，SSH登录性

    """
    def __init__(self, project_id, pod_id, regionid_list=None, suit_id=None):
        super(FSMConnCheckInf, self).__init__(project_id, pod_id, regionid_list)
        self.project_id = project_id
        self.pod_id = pod_id
        self.regionid_list = regionid_list
        self.suit_id = suit_id
        self.fs_args = ParamsGain(project_id, pod_id, regionid_list).get_args(suit_id)
        self.err_info = collections.defaultdict(list)
        self.ssh_error_code = 621009
        self.switch_root_error_code = 621010
        self.ping_error_code = 621025
        self.sandbox_opr = SandBoxHandlerForUpgrade(self.fs_args)
        self.is_one_step_upgrade = get_project_condition_boolean(self.project_id, "OneStepUpgrade")

    def execute(self, project_id, pod_id, regionid_list=None, suit_id=None):
        try:
            self.procedure()
        except Exception as err:
            logger.error("fsm connectivity error:{}, details:{}".format(err, traceback.format_exc()))
            return Message(500, err)
        return Message()

    def rollback(self, project_id, pod_id, regionid_list=None, suit_id=None):
        """
        标准调用接口：执行回滚
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message()

    def retry(self, project_id, pod_id, regionid_list=None, suit_id=None):
        """
        标准调用接口：重试
        :return: Message类对象
        """
        if self.sandbox_opr.is_after_813:
            if not self.is_one_step_upgrade:
                logger.info("Current Version:{}, and no HOT patch upgrade, pass".format(self.sandbox_opr.version))
                return Message()
        self.update_fsm_cloud_params()

        logger.info("Obtain the fs_args parameters again")
        self.fs_args = ParamsGain(project_id, pod_id, regionid_list).get_args(suit_id)
        return self.execute(self.project_id, self.pod_id, self.regionid_list, self.suit_id)

    def procedure(self):
        # 813及之后版本，一跳升级，需关闭沙箱、检查ssh连通性；普通升级走rest接口，不需要
        # 813之前版本，一跳升级、普通升级，需检查ssh连通性
        if self.sandbox_opr.is_after_813:
            if not self.is_one_step_upgrade:
                logger.info("Current Version:{}, and no HOT patch upgrade, pass".format(self.sandbox_opr.version))
                return

        master_node = [self.fs_args.get("master_ip"), self.fs_args.get("master_username"),
                       self.fs_args.get("master_password"), self.fs_args.get("master_root_pwd")]
        slaver_node = [self.fs_args.get("slaver_ip"), self.fs_args.get("slaver_username"),
                       self.fs_args.get("slaver_password"), self.fs_args.get("slaver_root_pwd")]

        for node_info in [master_node, slaver_node]:
            self.do_check_ssh_connectivity(*node_info)

        ret_err_msg = []
        for error_code, err_ip_list in self.err_info.items():
            ret_err_msg.append((get_code_msg(error_code) % err_ip_list).strip())
        if ret_err_msg:
            raise Exception(ret_err_msg)

    def do_check_ssh_connectivity(self, node_ip, node_username, node_password, root_password):
        result = can_vm_pinged_to(node_ip)
        if not result:
            logger.error("IP({}) is unreachable, details: {}".format(node_ip, result))
            self.err_info[self.ping_error_code].append(node_ip)
            return
        try:
            ssh_client = StorageSSHClient(node_ip, node_username, node_password)
        except Exception as err:
            logger.error("login {} with {} failed. error:{}".format(node_ip, node_username, err))
            self.err_info[self.ssh_error_code].append(node_ip)
            return
        try:
            cmd_ret = ssh_client.send_cmd('su -', 'assword:', 20)
        except Exception as err:
            logger.error("root password has expired. Host ip [{}], details:{}".format(node_ip, err))
            self.err_info[self.switch_root_error_code].append(node_ip)
            return
        logger.info("rsp %s" % cmd_ret)
        try:
            cmd_ret = ssh_client.send_cmd(root_password, '#', 20, sensitive=True)
        except Exception as err:
            logger.error("root user password is wrong. Host ip [{}], details:{}".format(node_ip, err))
            self.err_info[self.switch_root_error_code].append(node_ip)
        logger.info("rsp %s" % cmd_ret)
