# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import re
import time
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)
        self.check_type = 'network_connectivity'
        self.script_src_file = r'{}/ResourceCheck/common/scripts/Network/shells/check_network_connectivity.sh'.format(
            ProjectPluginsPath.project_plugins_path())
        self.speed_check_result = []

    @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

    def procedure(self):
        common_libs.check_flag()
        logger.info("Start to check network connectivity of separate storage node.")
        timestamp = str(int(time.time()))

        nodes_info = self.get_nodes_info()
        pci_obj = network_libs.NicPciCls(nodes_info)
        bmc_ip_list = list()
        ip_index = 0
        for bmc in nodes_info:
            ip_index += 1
            bmc_ip = bmc.get("bmc_ip")
            bmc_ip_list.append(bmc_ip)
            slot_list = self.get_slot_list(bmc)
            self.check_slot_status(bmc_ip, pci_obj, slot_list)
            node_nic_list = [pci_obj.get_nic_name_by_slot(bmc_ip, slot) for slot in slot_list]
            bond_mode = self._get_nic_mode(self.nic_bond_mode)
            self.update_vlan_flag(bmc, slot_list)
            if not self.vlan_flag:
                parm_dic = {
                    'TIMESTAMP': timestamp,
                    'CHECKTYPE': self.check_type,
                    'ETHNICS': '(' + ','.join(node_nic_list) + ')',
                    'NICIPMAPS': '(' + network_libs.gen_ip(self.net_info.get('ip_start'), ip_index) + ')',
                    'NETMASKMAPS': '(' + self.net_info.get('netmask') + ')',
                    'CHECKIPMAPS': '(' + self.net_info.get('gateway') + ')',
                    'NICBONDMODEMAPS': '(' + str(bond_mode) + ')'
                }
            else:
                parm_dic = {
                    'TIMESTAMP': timestamp,
                    'CHECKTYPE': self.check_type,
                    'ETHNICS': '(' + ','.join(node_nic_list) + ')',
                    'NICIPMAPS': '(' + network_libs.gen_ip(self.net_info.get('ip_start'), ip_index) + ')',
                    'NICVLANMAPS': '(' + self.net_info.get('vlan') + ')',
                    'NETMASKMAPS': '(' + self.net_info.get('netmask') + ')',
                    'CHECKIPMAPS': '(' + self.net_info.get('gateway') + ')',
                    'NICBONDMODEMAPS': '(' + str(bond_mode) + ')'
                }
            common_libs.create_check_script(self.script_src_file, bmc_ip, **parm_dic)
        if len(bmc_ip_list) != 0:
            common_libs.check_all_result(bmc_ip_list, self.check_type, timestamp)
        if self.speed_check_result:
            logger.error("Nic speed check failed!")
            raise HCCIException("625303", ','.join(self.speed_check_result))

    def get_nodes_info(self):
        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)
        return nodes_info

    def update_vlan_flag(self, bmc, slot_list):
        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

    def check_slot_status(self, bmc_ip, pci_obj, slot_list):
        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))
                self.speed_check_result.append(failed_info)

    def get_slot_list(self, bmc):
        slot_list = bmc[self.net_plane].split(',')
        if self.port_index:
            slot_list = [slot_list[self.port_index - 1]]
        return slot_list
