# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
from IPy import IP
import utils.common.log as logger
from utils.common.fic_base import TestCase
from utils.Driver.CloudDC.OpenStack.Network.networkutils import ManageMentStorageData
from platforms.project.ProjectUtils import get_project_condition_boolean
from plugins.DistributedStorage.scripts.logic.DeployOperate import DeployOperate
from plugins.DistributedStorage.scripts.utils.common.DeployConstant import DeployConstant


class ConfigStorageNetwork(TestCase):
    def __init__(self, project_id, pod_id, fs_args, **kwargs):
        super(ConfigStorageNetwork, self).__init__(project_id, pod_id)
        self.fs_args = fs_args
        self.opr = DeployOperate(self.fs_args)
        self.more_args = kwargs

    def procedure(self):
        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'])

    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
