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

import utils.common.log as logger
from utils.common.exception import HCCIException
from plugins.DistributedStorage.common.RestClient import StorageSSHClient
from plugins.DistributedStorage.common.UpgradeOperate import UpgradeOperate
from plugins.DistributedStorage.common.UpgradeHotPatchOperate import UpgradeHotPatchOperate
from plugins.DistributedStorage.common.base import TestCase
from plugins.DistributedStorage.common.constants import UpgradeStateKey
from plugins.DistributedStorage.common.constants import UpgradeStates
from plugins.DistributedStorage.Upgrade.scripts.impl.TC_Upgrade_Confirm import UpgradeConfirm


class RollBackConfirm(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None,
                 metadata=None, **kwargs):
        super(RollBackConfirm, self).__init__(project_id, pod_id)
        self.condition = condition
        self.metadata = metadata
        self.more_args = kwargs
        self.opr = UpgradeOperate(fs_args)
        self.fs_args = fs_args
        self.master_node = fs_args.get("master_node")
        self.master_client, self.slaver_client = None, None
        self.slaver_node = fs_args.get("slaver_node")
        self.remote_path = "/tmp/upgrade_tmp_hotpatch"
        self.user_name = fs_args["user_name"]
        self.password = fs_args["password"]
        self.region_id = fs_args.get("region_id")
        self.upgrade_type = fs_args["upgrade_type"]

    def procedure(self):
        logger.info('Start %s commit.' % self.upgrade_type)
        try:
            status_code, error_code, error_des = self.opr.try_login(
                self.user_name, self.password)
            if status_code != 200 or error_code != 0:
                err_msg = "Failed to login, Detail:[status:%s,code:%s]%s" % \
                          (status_code, error_code, error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
            # 获取主备节点
            self.create_fsm_client()
            # 上传脚本到主备fsm节点
            self.upload_script_to_fsm()
            if not self.fs_args.get("rollback_product_tag") and \
                    self.get_product_upgrade_state() > UpgradeStates.PRODUCT_UPGRADE_COMMIT_START:
                self.fs_args["upgrade_type"] = "upgrade"
            self.upgrade_confirm()
            self.clear_fsm_backup_data()
        except HCCIException as e:
            logger.error('failed commit upgrade:{}'.format(e))
            logger.error(traceback.format_exc())
            raise e
        except Exception as e:
            logger.error('failed commit upgrade:{}'.format(e))
            logger.error(traceback.format_exc())
            raise HCCIException(620017, str(e))
        finally:
            if self.fs_args.get("hot_patch_tag"):
                self.del_script_om_fsm()

    def upgrade_confirm(self):
        UpgradeConfirm(self.project_id, self.pod_id, self.fs_args).procedure()

    def clear_fsm_backup_data(self):
        UpgradeHotPatchOperate.clear_backup_data(self.remote_path, self.master_client)
        UpgradeHotPatchOperate.clear_backup_data(self.remote_path, self.slaver_client)

    def upload_script_to_fsm(self):
        """
        上传脚本至fsm主备节点
        """
        node_list = [(self.master_client, self.master_node),
                     (self.slaver_client, self.slaver_node)]
        for ssh_client, node in node_list:
            UpgradeHotPatchOperate.upload_script_to_fsm(ssh_client, node, self.remote_path)

    def del_script_om_fsm(self):
        """
        删除fsm节点上的脚本文件
        """
        client_list = [client for client in
                       [self.master_client, self.slaver_client] if client]
        for ssh_client in client_list:
            UpgradeHotPatchOperate.del_script_om_fsm(ssh_client, self.remote_path)
            del ssh_client

    def create_fsm_client(self):
        """
        获取当前主节点
        """
        node_infos = [self.master_node, self.slaver_node]
        self.master_client, node = UpgradeHotPatchOperate.get_master_node_client(node_infos)
        slaver_node = self.slaver_node if node == self.master_node else self.master_node
        self.slaver_client = StorageSSHClient(*slaver_node[:3])
        self.slaver_client.switch_root(slaver_node.root_pwd)

    def get_product_upgrade_state(self):
        param_key = UpgradeStateKey.PRODUCT_UPGRADE_STATE.format(self.fs_args.get("suit_id"))
        return UpgradeHotPatchOperate.get_operate_state(self.project_id, self.region_id, param_key)
