# -*- coding: utf-8 -*-
import traceback
from IPy import IP
from utils.common.fic_base import TestCase
import utils.common.log as logger
from utils.common.message import Message
from utils.common.exception import HCCIException
from plugins.DistributedStorage.logic.DeployOperate import DeployOperate
from plugins.DistributedStorage.utils.common.DeployConstant import DeployConstant
from plugins.DistributedStorage.implement.TC_Config_StorageNetwork import ExtractNetInf
from utils.business.project_condition_utils import get_project_condition_boolean
from utils.business.project_condition_utils import get_project_conditions


class ConfigStorageNetwork(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None, metadata=None, **kwargs):
        super(ConfigStorageNetwork, self).__init__(project_id, pod_id)
        self.fs_args = fs_args
        self.opr = DeployOperate(self.fs_args)
        self.condition = condition
        self.metadata = metadata
        self.more_args = kwargs
        self.network_info_list = list()
        self.storage_network_list = list()
        self.project_id = project_id
        self.pod_id = pod_id
        self.condition_dic = get_project_conditions(self.project_id)

    def procedure(self):
        try:
            logger.info("Start to config storage network.")
            self.opr.login(DeployConstant.DM_LOGIN_USER, self.fs_args['dm_update_pwd'])

            logger.info("Query frontend storage network.")
            net_type = 'storage_frontend'
            net_info_list = self.query_storage_network(net_type)
            if net_info_list:
                ExtractNetInf.exist_network_info_handler(net_info_list, self.network_info_list)

            if get_project_condition_boolean(self.project_id, '(TenantStorFB80|TenantStorFBReuse80)&'
                                                              '(ExpansionAZ_KVM|ExpansionAZ_BMS)|'
                                                              '(TenantStorFB80&ExpansionServiceStorage)'):
                self.get_compute_net_plane()

            if get_project_condition_boolean(self.project_id,
                                             '(TenantStorFB80|TenantStorFBReuse80|DRStorage_TFB_Sep)&'
                                             '(!TenantStorFB_Heterogeneous|TenantStor_ThreeTierNetwork)'):
                self.get_storage_net_plane("business_separate_storage_netmask",
                                           "business_separate_storage_gateway", "business_separate_storage_subnet")

            if get_project_condition_boolean(self.project_id, '((ExpansionPOD_KVM|ExpansionPOD_BMS)&'
                                                              'ExpansionPOD_CloudService)|ExpansionAZ_KVM|'
                                                              'ExpansionServiceStorage|ExpansionAZ_BMS|'
                                                              'ExpansionMgmtRes_ServiceNode|'
                                                              'ExpansionScale_CloudServiceNode|'
                                                              'DRStorage_TFB_Sep&(CSHAStorage_TFB|CSDRStorage_TFB|'
                                                              'TenantStorFBHCI80)'):
                scenario = 'extend'
            else:
                scenario = 'initialization'
            logger.info("Current scenario: %s." % scenario)

            logger.info("Config frontend storage network, network info:{}".format(self.network_info_list))
            net_type = 'storage_frontend'
            self.config_storage_network(net_type, scenario)

            logger.info("Config backend storage network, network info:{}".format(self.network_info_list))
            net_type = 'storage_backend'
            self.config_storage_network(net_type, scenario)

            node_list = [vbs['om_ip'] for vbs in self.fs_args['vbs_list']]
            self.validity_config_net(net_type, node_list)

            logger.info("Config storage network finished.")
            self.opr.login_out(DeployConstant.DM_LOGIN_USER, self.fs_args['dm_update_pwd'])
        except HCCIException as e:
            logger.error(traceback.format_exc())
            return Message(500, e)
        except Exception as e:
            return Message(500, HCCIException(626064, str(e)))
        return Message()

    def query_storage_network(self, net_type):
        rsp_obj = self.opr.get_storage_frontend_net_plane(net_type)
        rsp_code, rsp_result, rsp_data = rsp_obj.get_rsp_data()
        error_code = rsp_result.get('code')
        if error_code != 0:
            err_msg = "Failed to query storage_frontend network"
            logger.error(err_msg)
            raise Exception(err_msg)
        net_info_list = rsp_data.get("ip_list")
        return net_info_list

    def config_storage_network(self, net_type, scenario):
        res_result, res_data = self.opr.set_net_plane(self.network_info_list, net_type, scenario)
        if res_result.get("code") != 0 or res_data is not None:
            err_msg = "Failed to config storage network[network:%s, nettype:%s], Detail:[%s]%s" \
                      % (self.network_info_list, net_type, res_result, res_data)
            logger.error(err_msg)
            raise Exception(err_msg)

    def get_compute_net_plane(self):
        exp_compute_net_planes = self.db.get_computing_node_network_planning(self.project_id)
        compute_net_plane = None
        for compute_net in exp_compute_net_planes:
            if compute_net.get('network_plane') == DeployConstant.MGR_STORAGE_NET_INTF:
                compute_net_plane = compute_net
                break
        if compute_net_plane:
            ip_net = IP(compute_net_plane.get('network_segment_plan'))
            manage_storage_gateway = compute_net_plane.get('gateway')
            ExtractNetInf.ip_segment_handler(manage_storage_gateway, ip_net, self.network_info_list)
        else:
            err_msg = "Failed to get compute storage network from 1.2Sheet"
            logger.error(err_msg)
            raise Exception(err_msg)

    def validity_config_net(self, net_type, node_list):
        rsp = self.opr.config_net_validity(net_type, node_list)
        rsp_code, rsp_data = rsp.get_net_validity_data()
        fail_ip_list = list(rsp_data.keys())
        if rsp_code != 0 or len(fail_ip_list) > 0:
            err_msg = "Failed to config storage network on host%s, Detail:%s" % (fail_ip_list, rsp_data)
            logger.error(err_msg)
            raise Exception(err_msg)

    def get_storage_net_plane(self, netmask, gateway, subnet):
        storage_netmask = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageReplication", netmask)
        storage_gateway = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageReplication", gateway)
        storage_subnet = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageReplication", subnet)
        if not storage_netmask or not storage_gateway or not storage_subnet:
            err_msg = "Failed to get storage network[netmask:%s, gateway:%s, subnet:%s]" \
                      % (storage_netmask, storage_gateway, storage_subnet)
            logger.error(err_msg)
            raise Exception(err_msg)
        ip_net = IP(storage_subnet)
        ExtractNetInf.ip_segment_handler(storage_gateway, ip_net, self.network_info_list)
