# coding=utf-8
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import traceback

import utils.common.log as logger
from utils.common.message import Message
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.exception import HCCIException
from utils.common.fic_base import StepBaseInterface
from plugins.DistributedStorage.utils.iterm.parameter_gain import ParamsGain
from utils.business.project_condition_utils import get_project_condition_boolean
from plugins.DistributedStorage.logic.deploy_operate import DeployOperate
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant


class CheckNetworkingConsistency(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        super().__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = BaseOps()
        self.params = ParamsGain(project_id, pod_id, self.db)
        self.fs_args = self.params.get_business_separate_expand_fusionstorage_args_while_new_pool_or_new_node()
        self.imlp = CheckNetworking(self.project_id, self.pod_id, self.fs_args)

    def pre_check(self, project_id, pod_id):
        """
        插件内部接口：执行安装前的资源预检查，该接口由execute接口调用，工具框架不会直接调用此接口。
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message(200)

    def execute(self, project_id, pod_id):
        try:
            self.imlp.main()
        except HCCIException as e1:
            logger.error(traceback.format_exc())
            return Message(500, e1)
        except Exception as e2:
            logger.error(traceback.format_exc())
            return Message(500, HCCIException(626276, str(e2)))
        return Message(200)

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

    def retry(self, project_id, pod_id):
        """
        标准调用接口：重试
        :return: Message类对象
        """
        return self.execute(project_id, pod_id)

    def check(self, project_id, pod_id):
        """
        标准调用接口：重试
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message(200)


class CheckNetworking:
    def __init__(self, project_id, pod_id, fs_args):
        self.project_id = project_id
        self.pod_id = pod_id
        self.fs_args = fs_args
        self.float_ip = self.fs_args.get('float_ip')
        self.update_pwd = fs_args.get("dm_update_pwd")
        self.opr = DeployOperate(self.fs_args)
        self.net_types = ["storage_frontend", "storage_backend"]
        self.local_backend_net_independent = None
        self.cluster_backend_net_independent = None

    def main(self):
        self.local_backend_net_independent = get_project_condition_boolean(self.project_id, "TenantStorBackendNetSep")
        logger.info(f"Is the front-end and back-end independent networking of service storage: "
                    f"{self.local_backend_net_independent}")

        self.opr.login(DeployConstant.DM_LOGIN_USER, self.update_pwd)

        logger.info("Query cluster network")
        try:
            net_result = self.query_cluster_network()
            cluster_networking_status = self.compare_networking_status(net_result)
            if cluster_networking_status == self.local_backend_net_independent:
                logger.info("The cluster configuration is the same as that of nodes with capacity expansion.")
                return
            else:
                msg = f"The front-end and back-end networking separation options are different. " \
                      f"cluster:{cluster_networking_status}   nodes to be added:{self.local_backend_net_independent}"
                raise Exception(msg)
        finally:
            self.opr.logout()

    def query_cluster_network(self):
        net_result = []
        for net_type in self.net_types:
            rsp_result, rsp_data = self.opr.get_storage_net_plane(net_type)
            error_code = rsp_result.get('code')
            if error_code != 0:
                err_msg = f"Failed to query frontend storage network, details:{rsp_result.get('description')}"
                logger.error(err_msg)
                raise Exception(err_msg)
            net_info_list = rsp_data.get("ip_list")
            net_result.append(net_info_list)
        return net_result

    @staticmethod
    def compare_networking_status(net_result):
        front_net = net_result[0][0]
        back_net = net_result[1][0]
        if front_net.get("ip_segment").get("begin_ip") != back_net.get("ip_segment").get("begin_ip"):
            return True
        if front_net.get("ip_segment").get("end_ip") != back_net.get("ip_segment").get("end_ip"):
            return True
        if front_net.get("default_gateway") != back_net.get("default_gateway"):
            return True
        return False
