# -*- coding: utf-8 -*-
import re
import time
import os
import traceback
import utils.common.log as logger
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.exception import HCCIException
from utils.constant.path_constant import ProjectPluginsPath
from plugins.ResourceCheck.common.libs import common_libs, network_libs


class CheckNetworkConnectivity(object):
    def __init__(self, project_id, pod_id, fs_args):
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = BaseOps()
        self.port_name = fs_args.get("port_name")
        self.net_info = fs_args.get("net_info")
        self.net_plane = fs_args.get("net_plane")
        self.nic_bond_mode = fs_args.get("nic_bond_mode")
        self.vlan_flag = fs_args.get("vlan_flag")
        self.port_index = fs_args.get("port_index")
        self.node_role = fs_args.get("node_role")
        self.min_speed = fs_args.get("min_speed", 10000)
        self.management_plane = "management_plane"
        logger.info(fs_args)

    def procedure(self):
        try:
            common_libs.check_flag()
            logger.info("Start to check network connectivity of separate storage node.")
            bmc_ip_list = list()
            mgmt_net_data = dict()
            timestamp = str(int(time.time()))
            check_type = 'network_connectivity'
            plugin_path = ProjectPluginsPath.project_plugins_path()
            script_src_file = r'{}/ResourceCheck/common/scripts/Network/shells/check_network_connectivity.sh'\
                .format(plugin_path)
            network_list = [self.port_name]
            mgmt_net_data[self.port_name] = self.net_info
            if self.node_role:
                nodes_info = self.db.get_install_os_list_info(self.pod_id, self.node_role)
            else:
                nodes_info = self.db.get_install_os_list_info(self.pod_id)
            bmc_verify_list = [bmc for bmc in nodes_info]
            pci_obj = network_libs.NicPciCls(bmc_verify_list)
            ip_index = 0
            speed_check_result = []
            for bmc in bmc_verify_list:
                ip_index += 1
                node_ip = list()
                bmc_ip = bmc["bmc_ip"]
                network_verify_list = list(network_list)

                node_ip_gw = [mgmt_net_data[i]['gateway'] for i in network_verify_list]
                node_ip_start = [mgmt_net_data[i]['ip_start'] for i in network_verify_list]
                node_ip_mask = [mgmt_net_data[i]['netmask'] for i in network_verify_list]
                node_ip_vlan = [mgmt_net_data[i]['vlan'] for i in network_verify_list]
                slot_list = bmc[self.net_plane].split(',')
                if self.port_index:
                    slot_list = [slot_list[self.port_index - 1]]
                for start_ip in node_ip_start:
                    node_ip.append(network_libs.gen_ip(start_ip, ip_index))
                for slot in slot_list:
                    nic_info = pci_obj.get_nic_info_by_slot(bmc_ip, slot)
                    if not nic_info:
                        err_msg = 'No NIC information exists in the slot %s of the node %s' % (slot, bmc_ip)
                        logger.error(err_msg)
                        raise HCCIException("627607", slot, bmc_ip, err_msg)
                    speed_str = re.findall(r'\d+', nic_info.get("speed"))
                    if len(speed_str) == 0:
                        logger.info("Failed to get speed of nic. Detail:%s" % nic_info)
                        raise HCCIException("627607", slot, bmc_ip, nic_info)
                    else:
                        speed_data = speed_str[0]
                    speed = int(speed_data)
                    if speed < self.min_speed:
                        failed_info = "%s(slot:%s)" % (bmc_ip, slot)
                        logger.error("node %s speed is less than %s." % (failed_info, self.min_speed))
                        speed_check_result.append(failed_info)
                node_nic_list = [pci_obj.get_nic_name_by_slot(bmc_ip, slot) for slot in slot_list]
                bmc_ip_list.append(bmc_ip)
                nic_list = ','.join(node_nic_list)
                ip_list = ','.join(node_ip)
                mask_list = ','.join(node_ip_mask)
                gw_list = ','.join(node_ip_gw)
                bond_mode = self._get_nic_mode(self.nic_bond_mode)
                if self.net_plane == self.management_plane:
                    self.vlan_flag = True
                else:
                    manage_slot_list = bmc[self.management_plane].split(',')
                    if not list(set(slot_list).difference(set(manage_slot_list))):
                        self.vlan_flag = True
                if not self.vlan_flag:
                    parm_dic = {
                        'TIMESTAMP': timestamp,
                        'CHECKTYPE': check_type,
                        'ETHNICS': '(' + nic_list + ')',
                        'NICIPMAPS': '(' + ip_list + ')',
                        'NETMASKMAPS': '(' + mask_list + ')',
                        'CHECKIPMAPS': '(' + gw_list + ')',
                        'NICBONDMODEMAPS': '(' + str(bond_mode) + ')'
                    }
                else:
                    vlan_list = ','.join(node_ip_vlan)
                    parm_dic = {
                        'TIMESTAMP': timestamp,
                        'CHECKTYPE': check_type,
                        'ETHNICS': '(' + nic_list + ')',
                        'NICIPMAPS': '(' + ip_list + ')',
                        'NICVLANMAPS': '(' + vlan_list + ')',
                        'NETMASKMAPS': '(' + mask_list + ')',
                        'CHECKIPMAPS': '(' + gw_list + ')',
                        'NICBONDMODEMAPS': '(' + str(bond_mode) + ')'
                    }
                common_libs.create_check_script(script_src_file, bmc_ip, **parm_dic)
            if len(bmc_ip_list) != 0:
                common_libs.check_all_result(bmc_ip_list, check_type, timestamp)
            if speed_check_result:
                logger.error("Nic speed check failed!")
                raise HCCIException("625303", ','.join(speed_check_result))
        except HCCIException as e1:
            logger.error(traceback.format_exc())
            raise e1
        except Exception as e2:
            logger.error(traceback.format_exc())
            raise e2
        return True, None

    @staticmethod
    def _get_nic_mode(nic_bond_mode):
        logger.info("Get nic mode:%s" % nic_bond_mode)
        if nic_bond_mode == 'active_standby':
            bond_mode = 1
        elif nic_bond_mode == 'lacp':
            bond_mode = 4
        else:
            bond_mode = 4
        logger.info("bond mode:%s" % bond_mode)
        return bond_mode
