# -*- 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 utils.business.project_condition_utils import get_project_condition_boolean
from utils.Driver.CloudDC.OpenStack.Network.networkutils import ManageMentStorageData


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

    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('Get network list')
            network_list = self.get_network_list()

            scenario = self.get_scenario_id()
            logger.info("Current scenario: %s." % scenario)

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

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

            node_list = [fsa['om_ip'] for fsa in self.fs_args['fsa_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)

            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 get_scenario_id(self):
        if get_project_condition_boolean(
                self.project_id,
                'ExpansionAZ_KVM|ExpansionAZ_BMS|ExpansionMgmtRes_ServiceNode|ExpansionScale_CloudServiceNode'
                '|ExpansionServiceStorage|ExpansionComputeRes_KVMNode|ExpansionNetworkRes_NetworkNode'):
            scenario = 'extend'
        else:
            scenario = 'initialization'
        return scenario

    def get_network_list(self):
        network_list = []
        obj = ManageMentStorageData(self.project_id, self.pod_id)
        storage_net_data_list = obj.get_service_storage_data_info()
        for storage_net_data in storage_net_data_list:
            storage_netmask = storage_net_data.get('net_info_netmask')
            storage_gateway = storage_net_data.get('net_info_gateway')
            net_plane_segment = storage_net_data.get('net_info_range')
            if not storage_netmask or not storage_gateway or not net_plane_segment:
                err_msg = "Failed to obtain network parameters. Check the network parameters in the LLD."
                logger.error(err_msg)
                raise Exception(err_msg)
            net_segment_list = net_plane_segment.split('-')
            net_start_ip = net_segment_list[0]
            net_end_ip = net_segment_list[1]
            compute_net = {'port_name': '',
                           'ip_segment': {'begin_ip': net_start_ip, 'end_ip': net_end_ip},
                           'subnet_prefix': storage_netmask,
                           'default_gateway': storage_gateway}
            network_list.append(compute_net)
        return network_list

    def get_storage_net_plane(self, netmask, gateway, subnet):
        storage_netmask = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", netmask)
        storage_gateway = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", gateway)
        storage_subnet = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", 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)
        storage_subnet_list = storage_subnet.split('-')
        storage_net_start = storage_subnet_list[0]
        storage_net = IP(storage_net_start).make_net(storage_netmask)
        ip_net = IP(storage_net)
        net_segment = ip_net.strNormal(3)
        net_segment_list = net_segment.split('-')
        storage_start_ip = net_segment_list[0]
        storage_end_ip = net_segment_list[1]
        storage_net = {'port_name': '',
                       'ip_segment': {'begin_ip': storage_start_ip, 'end_ip': storage_end_ip},
                       'subnet_prefix': storage_netmask,
                       'default_gateway': storage_gateway}
        return storage_net
