#!/usr/bin/env python
# -*- 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.common.fic_base import TestCase
from utils.common.exception import HCCIException
from utils.common.fic_base import StepBaseInterface
from utils.business.param_util import ParamUtil
from utils.business.manageone_cmdb_util import ManageOneCmdbUtil
from utils.business.project_condition_utils import get_project_condition_boolean
from plugins.DistributedStorage.logic.vm_operate import VMOperate
from plugins.DistributedStorage.utils.common.query_for_cmdb import DealInfoForCMDB, DistributedStorageRegCMDBBase
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.utils.interface.DistributedStorage import DistributedStorageArgs
from plugins.DistributedStorage.utils.iterm.parameter_gain import ParamsGain
from plugins.DistributedStorage.utils.iterm.storage_cmdb_util import StorageCMDBUtil
from plugins.DistributedStorage.Deploy.scripts.PreCheck.common.device_operate import PreCheckPublicOperate
from plugins.DistributedStorage.Replication.scripts.common_utils.config_params import Params


logger.init("business DistributedStorage RegisterCMDB")


class FSB8RegisterCMDB(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        super(FSB8RegisterCMDB, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.reg_cmdb = DistributedStorageRegCMDBImpl(project_id, pod_id)
        self.error_code = 626267

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

    def execute(self, project_id, pod_id):
        """
        标准调用接口：执行安装前预检查&安装&配置
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        try:
            self.reg_cmdb.procedure()
        except HCCIException as err:
            logger.error("Failed to register with the CMDB:{}".format(traceback.format_exc()))
            return Message(500, err)
        except Exception as err:
            logger.error("Failed to register with the CMDB:{}".format(traceback.format_exc()))
            return Message(500, HCCIException(self.error_code, str(err)))
        return Message(200)


class DistributedStorageRegCMDBImpl(TestCase, DistributedStorageRegCMDBBase):
    def __init__(self, project_id, pod_id):
        super(DistributedStorageRegCMDBImpl, self).__init__(project_id, pod_id)
        self.param_util = ParamUtil()
        self.region_code = self.param_util.get_param_value(
            self.pod_id,
            service_name=DeployConstant.CLOUD_SERVICE_NAME,
            param_key=DeployConstant.CLOUD_SERVICE_PARAMS_KEY
        )
        self.az_id = ParamsGain(self.project_id, self.pod_id, self.db).get_az_id()
        self.mo_cmdb = ManageOneCmdbUtil(self.project_id, self.pod_id)
        self.storage_tool = DistributedStorageArgs(self.project_id, self.pod_id)
        self.vm_opr = VMOperate(self.project_id, self.pod_id, None)
        self.pre_check_opr = PreCheckPublicOperate(self.project_id, self.pod_id)
        self.fs_cmdb_util = StorageCMDBUtil(self.project_id, self.pod_id)
        self.is_new_storage_cluster = get_project_condition_boolean(
            self.project_id,
            "(ProjectDeploy|ExpansionAZ_KVM|ExpansionAZ_BMS|ExpansionServiceStorage)&TenantStorFB80")
        self.is_exp_rep = get_project_condition_boolean(
            self.project_id,
            "(ExpansionAdCloudService|ExpansionServiceStorage&!TenantStorFB80)"
            "&DRStorage_TFB_Sep&(CSHAStorage_TFB|CSDRStorage_TFB)")
        self.dm_login_args = self.get_dm_login_args()

    def procedure(self):
        """
        业务存储微服务分为FSM和FSA。FSM拓扑视图下包含主备虚拟机，FSA拓扑视图下包含存储节点
        """
        logger.info("Start to reg cmdb. region code:{}, az id:{}".format(self.region_code, self.az_id))

        cloud_service_info = self.get_cloud_service_info()
        self.mo_cmdb.set_cloud_service_info_v3(self.region_code, cloud_service_info)
        logger.info("The DistributedStorage information is successfully registered with the CMDB")

    def get_dm_login_args(self):
        if self.is_exp_rep:
            parameters = Params(self.project_id, self.pod_id, DeployConstant.REP_SERVICE_NAME).get_rep_fsa_params()
            float_ip = parameters.get("float_ip")
            dm_update_pwd = parameters.get("dm_update_pwd")
        else:
            float_ip = self.storage_tool.get_business_storage_float_ip()
            dm_update_pwd = self.storage_tool.get_business_fsm_portal_pwd()
        if not float_ip or not dm_update_pwd:
            err_msg = "Failed to get dm_login_args, float ip:{}.".format(float_ip)
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info("Business storage float ip:{}".format(float_ip))
        return {'float_ip': float_ip, 'dm_update_pwd': dm_update_pwd}

    def get_cloud_service_info(self):
        """
        生成V3接口注册cmdb的信息
        """
        deploy_node_infos, fsm_ip_list, name, version, osd_host_name_list = self.get_info_from_dm(self.dm_login_args)
        vm_hostnames = self.get_fsm_vm_hostname_list()
        all_bmc_ip = self.get_all_bmc_ip(name)
        services = DealInfoForCMDB.get_services_info(version, self.region_code, osd_host_name_list, vm_hostnames)

        cloud_service_info = {
            "indexName": DeployConstant.CLOUD_SERVICE_INDEX,
            "version": version,
            "name": name,
            "extendInfos": [
                {'key': "az_id", "value": self.az_id},
                {'key': "deployment_type", "value": DeployConstant.DEPLOYMENT_TYPE},
                {"key": "fsm_float_ip", "value": self.dm_login_args.get("float_ip")},
                {"key": "fsm_primary_ip", "value": fsm_ip_list[0]},
                {"key": "fsm_slave_ip", "value": fsm_ip_list[1]},
                {"key": "deploy_bmc_node", "value": ";".join(all_bmc_ip)}
            ],
            "deployNodeInfos": deploy_node_infos,
            "services": services
        }
        logger.info("get param cloud_service: %s" % str(cloud_service_info))
        return cloud_service_info

    def get_fsm_vm_hostname_list(self):
        master_fsm, standby_fsm = self.vm_opr.get_vm_data(self.pod_id, self.dm_login_args.get("float_ip"))
        return [master_fsm.get('hostname'), standby_fsm.get('hostname')]

    def get_all_bmc_ip(self, name):
        bmc_nodes_info = self.pre_check_opr.get_bmc_info(need_rep=True)
        bmc_ip_list = [node.get("bmc_ip") for node in bmc_nodes_info]
        if not self.is_new_storage_cluster:
            bmc_ip_list.extend(self.fs_cmdb_util.get_deployed_bmc_ip_list_by_name(name))
        return sorted(set(bmc_ip_list))
