# -*- coding:utf-8 -*-
import traceback

import IPy

import utils.common.log as logger
from plugins.DistributedStorage.scripts.logic.DeployOperate import DeployOperate
from utils.business.project_util import ProjectApi
from utils.common.exception import FCDException
from utils.common.fic_base import TestCase
from utils.common.message import Message


class ConfigRoute(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None,
                 metadata=None, **kwargs):
        super(ConfigRoute, self).__init__(project_id, pod_id)
        self.float_ip = fs_args.get("float_ip")
        self.node_list = fs_args.get("node_list")
        self.update_pwd = fs_args.get("dm_update_pwd")
        self.frontend_net_port = fs_args.get("frontend_net_port_name")
        self.frontend_net_gw = fs_args.get("fs_stg_gw")
        self.backend_net_port = fs_args.get("backend_net_port_name")
        self.backend_net_gw = fs_args.get("fs_stg_inner_gw")
        self.username = fs_args.get("rest_username", "admin")
        self.condition = condition
        self.metadata = metadata
        self.more_args = kwargs
        self.ip_type_is_ipv6 = ProjectApi().is_ipv6_project(self.project_id)
        self.opr = DeployOperate(fs_args)

    def procedure(self):
        try:
            logger.info("Start to config policy route to storage node.")
            self.login_deploy_manager()

            if not self.node_list:
                logger.error("osd list(%s) is null" % self.node_list)
                return Message(200)
            om_ip_list = [node['om_ip'] for node in self.node_list]
            route_info = dict()
            route_info["nodeMgrIps"] = om_ip_list
            net_type = "storage_frontend"
            frontend_port_name = self.frontend_net_port
            if not frontend_port_name:
                frontend_port_name = self._get_port_name(om_ip_list[0], net_type)
            route_info["portName1"] = frontend_port_name
            frontend_gw = self.frontend_net_gw
            if not frontend_gw:
                ip_address = self._get_ip_address(om_ip_list[0], net_type)
                frontend_gw = self._get_gateway(ip_address, net_type)
            route_info["gateway1"] = frontend_gw
            if self.backend_net_gw:
                net_type = "storage_backend"
                backend_port_name = self.backend_net_port
                if not backend_port_name:
                    backend_port_name = self._get_port_name(om_ip_list[0], net_type)
                backend_gw = self.backend_net_gw
                if not backend_gw:
                    ip_address = self._get_ip_address(om_ip_list[0], net_type)
                    backend_gw = self._get_gateway(ip_address, net_type)
                route_info["portName2"] = backend_port_name
                route_info["gateway2"] = backend_gw
            rsp_result, _ = self.opr.add_policy_route(route_info)
            if rsp_result != 0:
                err_msg = ("add policy route failed, Detail:[result: %s]" % rsp_result)
                raise Exception(err_msg)
        except FCDException as exc:
            logger.error(traceback.format_exc())
            return Message(500, exc)
        except Exception as exc:
            logger.error(traceback.format_exc())
            return Message(500, FCDException(626257, str(exc)))
        finally:
            self.opr.logout()
        return Message(200)

    def login_deploy_manager(self):
        status_code, error_code, error_des = self.opr.login(
            self.username, self.update_pwd)
        if status_code != 200 or error_code != 0:
            err_msg = ("Failed to login deploy manager, "
                       "Detail:[status:%s,code:%s]%s"
                       % (status_code, error_code, error_des))
            logger.error(err_msg)
            raise Exception(err_msg)

    def _get_port_name(self, manage_ip, net_type):
        rsp_result, rsp_data = self.opr.query_network_servers(
            manage_ip=manage_ip, net_type=net_type)
        if rsp_result.get("code") != 0:
            err_msg = ("get net servers failed, "
                       "Detail:[result: %s]" % rsp_result)
            raise Exception(err_msg)
        for node_info in rsp_data:
            ip_list = node_info.get("ip_address_list")
            for ip_info in ip_list:
                if net_type not in ip_info.get("ip_usage"):
                    continue
                return ip_info.get("port_name")
        return None

    def _get_ip_address(self, manage_ip, net_type):
        rsp_result, rsp_data = self.opr.query_network_servers(
            manage_ip=manage_ip, net_type=net_type)
        if rsp_result.get("code") != 0:
            err_msg = ("get net servers failed, "
                       "Detail:[result: %s]" % rsp_result)
            raise Exception(err_msg)
        for node_info in rsp_data:
            ip_list = node_info.get("ip_address_list")
            for ip_info in ip_list:
                if net_type not in ip_info.get("ip_usage"):
                    continue
                return ip_info.get("ip_address")
        return None

    def _get_gateway(self, ip_addr, net_type):
        rsp_result, rsp_data = self.opr.get_storage_net_plane(net_type)
        if rsp_result.get("code") != 0:
            err_msg = "get net plane failed, Detail:[result: %s]" % rsp_result
            raise Exception(err_msg)
        ip_list = rsp_data.get("ip_list")
        for ip_info in ip_list:
            begin_ip = ip_info.get("ip_segment").get("begin_ip")
            end_ip = ip_info.get("ip_segment").get("end_ip")
            if IPy.IP(begin_ip) < IPy.IP(ip_addr) < IPy.IP(end_ip):
                return ip_info.get("default_gateway")
        return None
