# -*- coding: utf-8 -*-
import pathlib
import traceback

import utils.common.log as logger
from utils.common.exception import HCCIException
from utils.common.message import Message
from utils.common.ssh_util import Ssh
from utils.common.fic_base import StepBaseInterface
from utils.common.software_package_util import find_software_package
from plugins.DistributedStorage.common.base import TestCase
from plugins.DistributedStorage.common.ParameterGain import ParamsGain
from plugins.DistributedStorage.logic.InstallOperate import InstallOperate
from plugins.DistributedStorage.utils.common.DeployConstant import DeployConstant


class InstallDeploymanagerPkgInf(StepBaseInterface):
    def __init__(self, project_id, pod_id, regionid_list=None, suit_id=None):
        super(InstallDeploymanagerPkgInf, 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.install_Deploymanager_pkg = InstallDeploymanagerPkgImp(self.project_id, self.pod_id, self.fs_args)

    def execute(self, project_id, pod_id, regionid_list=None, suit_id=None):
        logger.info('Start install Deploymanager Package')
        try:
            self.install_Deploymanager_pkg.procedure()
        except Exception as err:
            logger.error("Install Deploymanager Package error:{}".format(traceback.format_exc()))
            return Message(500, str(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类对象
        """
        return self.execute(self.project_id, self.pod_id, self.regionid_list, self.suit_id)


class InstallDeploymanagerPkgImp(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None, metadata=None, **kwargs):
        super(InstallDeploymanagerPkgImp, self).__init__(project_id, pod_id)
        self.condition = condition
        self.metadata = metadata
        self.fs_args = fs_args
        self.more_args = kwargs
        self.admin_pwd = fs_args.get("password")
        self.master_ip = self.fs_args.get("master_ip")
        self.master_username = self.fs_args.get("master_username")
        self.master_password = self.fs_args.get("master_password")
        self.master_root_pwd = self.fs_args.get("master_root_pwd")
        self.slaver_ip = self.fs_args.get("slaver_ip")
        self.slaver_username = self.fs_args.get("slaver_username")
        self.slaver_password = self.fs_args.get("slaver_password")
        self.slaver_root_pwd = self.fs_args.get("slaver_root_pwd")
        self.master_client = None
        self.slaver_client = None
        self.standby_client = None
        self.standby_node = None
        self.active_node = None
        self.client_list = []
        self.error_code = 621020
        self.deploymanager_pkg_pattern = list(DeployConstant.STORAGE_PACKAGES_PATTERN[6].values())[0]
        self.deploymanager_pkg, self.deploymanager_dir = self.get_deploymanger_pkg_name_and_dir()

    def procedure(self):
        try:
            logger.info("step1. Log in to the management nodes")
            self.ssh_mgmt_nodes()
            logger.info("step2. Querying the Standby Node")
            self.get_standby_node()
            logger.info("step3. Decompress the {} package on the standby node".format(self.deploymanager_pkg))
            self.unzip_pkg_dir()
            logger.info("step4. Run the installation script on the standby node")
            try:
                self.install_pkg()
            except Exception as e:
                logger.error("Install deploymanager package failed:{}".format(e))
                raise HCCIException(self.error_code, self.deploymanager_pkg, e, self.standby_node[0])
            logger.info("Succeeded in performing the upgrade")
        finally:
            for client in self.client_list:
                Ssh.ssh_close(client)

    def ssh_mgmt_nodes(self):
        self.master_client = InstallOperate.create_ssh_root_client(
            self.master_ip, self.master_username, self.master_password, self.master_root_pwd)
        self.client_list.append(self.master_client)
        self.slaver_client = InstallOperate.create_ssh_root_client(
            self.slaver_ip, self.slaver_username, self.slaver_password, self.slaver_root_pwd)
        self.client_list.append(self.slaver_client)

    def get_standby_node(self):
        logger.info("Start to Querying the Standby Node")
        cmd = "if [ -e /root/{} ];then echo pkg_exist;fi".format(self.deploymanager_pkg)
        ret = Ssh.ssh_exec_command_return(self.master_client, cmd)
        if str(ret).__contains__("pkg_exist"):
            logger.info("The Standby node ip is {}".format(self.master_ip))
            self.standby_client = self.master_client
            self.standby_node = [self.master_ip, self.master_username, self.master_password, self.master_root_pwd]
            self.active_node = [self.slaver_ip, self.slaver_username, self.slaver_password, self.slaver_root_pwd]
            return
        ret = Ssh.ssh_exec_command_return(self.slaver_client, cmd)
        if not str(ret).__contains__("pkg_exist"):
            err_msg = "The {} does not exist in the /root directory " \
                      "on the nodes{}".format(self.deploymanager_pkg, [self.master_ip, self.slaver_ip])
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info("The Standby node ip is {}".format(self.slaver_ip))
        self.standby_client = self.slaver_client
        self.standby_node = [self.slaver_ip, self.slaver_username, self.slaver_password, self.slaver_root_pwd]
        self.active_node = [self.master_ip, self.master_username, self.master_password, self.master_root_pwd]

    def unzip_pkg_dir(self):
        cmd = "echo -e 'A' | tar -zxf /root/{} -C /root/;echo last_result=$?".format(self.deploymanager_pkg)
        ret = Ssh.ssh_exec_command_return(self.standby_client, cmd)
        if not str(ret).__contains__("last_result=0"):
            err_msg = "Unzip {} failed, node ip:{}, result：{}".format(self.deploymanager_pkg, self.slaver_ip, ret)
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info("Decompressing the {} package succeeded.".format(self.deploymanager_pkg))

    def install_pkg(self):
        logger.info("start to install deploymanager package")
        cmd = "bash /root/{}/action/upgrade.sh".format(self.deploymanager_dir)
        ret = Ssh.ssh_send_command(self.standby_client, cmd, "(yes/no)", 20, 3)
        logger.info("input [{}] cmd result:{}".format(cmd, ret))
        ret = Ssh.ssh_send_command(self.standby_client, "yes", "username", 20, 3)
        logger.info("input yes cmd result:{}".format(ret))
        ret = Ssh.ssh_send_command(self.standby_client, DeployConstant.DM_LOGIN_USER, "admin password", 20, 3)
        logger.info("input admin user result:{}".format(str(ret).replace("password", "***")))
        ret = Ssh.ssh_send_command(self.standby_client, self.admin_pwd, "remote username", 60, 3)
        logger.info("Authentication admin user result:{}".format(ret))
        ret = Ssh.ssh_send_command(self.standby_client, DeployConstant.FSM_USER, "fsadmin password", 20, 3)
        logger.info("Input fsadmin user result:{}".format(str(ret).replace("password", "***")))
        ret = Ssh.ssh_send_command(self.standby_client, self.active_node[2], "root password", 20, 3)
        logger.info("Authentication fsadmin user result:{}".format(str(ret).replace("password", "***")))
        Ssh.ssh_send_command(self.standby_client, self.active_node[3], "Succeeded in performing the upgrade", 3600, 3)
        logger.info("Succeeded in performing the upgrade")

    def get_deploymanger_pkg_name_and_dir(self):
        pkg_dict, num = find_software_package(self.deploymanager_pkg_pattern, self.project_id)
        if not pkg_dict:
            err_msg = "The {} does not exist in the /home/pkg directory of the upgrade tool, " \
                      "result:{}".format(self.deploymanager_pkg_pattern, pkg_dict)
            logger.error(err_msg)
            raise Exception(err_msg)
        deploymanager_pkg = pathlib.Path(list(pkg_dict.keys())[0])
        deploymanager_dir = pathlib.Path(deploymanager_pkg.stem).stem
        logger.info("Deploymanager pkg {}".format(deploymanager_pkg))
        return str(deploymanager_pkg), deploymanager_dir
