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

import utils.common.log as logger
from utils.common.ssh_util import Ssh as ssh
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.exception import HCCIException
from utils.business.project_condition_utils import get_project_condition_boolean
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc
from plugins.DistributedStorage.Deploy.scripts.PreCheck.common.DeviceOperate import CpuOperate
from plugins.DistributedStorage.logic.InstallOperate import InstallOperate


class SPDKDeviceCheck(object):
    def __init__(self, project_id, pod_id):
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = BaseOps()
        self.cpu_support_list = ['Xeon_V4', 'Xeon_V5', 'Jintide', 'Hygon_C86']

    def check_storage_node_spdk(self):
        all_bmc_data = self.db.get_install_os_list_info(self.pod_id)
        if get_project_condition_boolean(self.project_id, '!TenantStorFB_Heterogeneous'):
            bmc_client = BMCCmdExc()
            # 检查NVMe SSD缓存厂商是否[es3000，intel，samsung，A28, DP]
            logger.info("Checking nvme type")
            pool_name_str = "storage_pool_name_and_slot"
            pool_dict = dict()
            nvme_node_list = list()
            for temp in all_bmc_data:
                pool_name = temp.get(pool_name_str)
                if pool_name not in pool_dict.keys():
                    pool_dict[pool_name] = list()
                    pool_dict[pool_name].append(temp)
                else:
                    pool_dict[pool_name].append(temp)
            for key, data in pool_dict.items():
                logger.info("start to check pool,pool name [%s]", key)
                bmc_cache = data[0].get('cache_type')
                if bmc_cache == 'ssd_card' or bmc_cache == "none":
                    bmc_ip_list = [bmc.get('bmc_ip') for bmc in data]
                    cmd = "lspci -mm -n -D | grep 0108 | tr -d '\"'| awk '{print $3}'"
                    nvme_result = bmc_client.run(bmc_ip_list, cmd)
                    for bmc_ip in bmc_ip_list:
                        if nvme_result[bmc_ip]['result'] != '0':
                            stderr = nvme_result[bmc_ip]['stderr']
                            logger.error("Failed to get nvme type from node[%s], DetaiL:%s" % (bmc_ip, stderr))
                            continue
                        nvme_disk_list = nvme_result[bmc_ip]['stdout'].strip('\n').split('\n')
                        if nvme_result[bmc_ip]['stdout'] == "":
                            logger.info("The host[%s] cache type is not NVME, no need to check SPDK" % bmc_ip)
                            continue
                        logger.info("Current node[%s] nvme:%s" % (bmc_ip, nvme_disk_list))
                        nvme_node_list.append(bmc_ip)
                        for nvme in nvme_disk_list:
                            if nvme not in ['19e5', '8086', '144d', '1e81', '1cc4', '1e3b', '1c5f']:
                                logger.error("The nvme disk[%s] is not huawei or intel or"
                                             " samsung or white-lable nvme disk." % nvme)
                                raise HCCIException(627436, bmc_ip)
            if not nvme_node_list:
                logger.info("The cache type is not NVME, no need to check SPDK")
                return
            # x86架构的节点检查cpu type是否为[Xeon_V4、Xeon_V5、Jintide、Hygon C86]
            # Hygon C86海光服务器不检查SPDK，所以加进白名单
            # Jintide包含C4、C5、C6
            bmc_ip_list = nvme_node_list
            logger.info("Checking cpu type")
            operate = CpuOperate()
            cpu_arch_dict = operate.get_system_arch(bmc_ip_list)
            x86_bmc_ip_list = list()
            for bmc_ip in bmc_ip_list:
                cpu_arch = cpu_arch_dict.get(bmc_ip).get('stdout')
                if cpu_arch == 'X86':
                    x86_bmc_ip_list.append(bmc_ip)
            if x86_bmc_ip_list:
                cpu_result = bmc_client.run(x86_bmc_ip_list, X86_CPU_TYPE)
                for bmc_ip in x86_bmc_ip_list:
                    if cpu_result[bmc_ip]['result'] != '0':
                        stderr = cpu_result[bmc_ip]['stderr']
                        logger.error("Failed to get CPU type from node[%s], DetaiL:%s" % (bmc_ip, stderr))
                        continue
                    cpu_type_list = cpu_result[bmc_ip]['stdout'].strip('\n').split('\n')
                    logger.info("Current node[%s] cpu type list:%s" % (bmc_ip, cpu_type_list))
                    for cpu in cpu_type_list:
                        if cpu not in self.cpu_support_list:
                            logger.error("The CPU type not supported")
                            raise HCCIException(627605, bmc_ip)
            return
        # 手动装机场景
        operate = InstallOperate()
        for node in all_bmc_data:
            om_ip = node.get("manageIp")
            account_info = node["creuser"].split(',')
            user = account_info[2]
            passwd = account_info[3]
            root_pwd = account_info[1]
            ssh_client = operate.create_ssh_root_client(om_ip, user, passwd, root_pwd)
            # 检查NVMe SSD缓存厂商是否[es3000，intel，samsung，A28]
            logger.info("Checking nvme type")
            if node.get('cache_type') == 'ssd_card' or node.get('cache_type') == "none":
                nvme_cmd = "lspci -mm -n -D | grep 0108 | tr -d '\"'| awk '{print $3}'"
                ret_cmd = ssh.ssh_exec_command_return(ssh_client, nvme_cmd)
                if not ret_cmd:
                    logger.info("The host[%s] cache type is not NVME, no need to check SPDK" % om_ip)
                    continue
                for nvme in ret_cmd:
                    if nvme.strip('\n') not in ['19e5', '8086', '144d', '1e81', '1cc4', '1e3b', '1c5f']:
                        logger.error("The nvme disk[%s] is not huawei or intel or samsung or white-lable nvme disk."
                                     % nvme)
                        raise HCCIException(627436, om_ip)
            else:
                logger.info("The host[%s] cache type is not NVME, no need to check SPDK" % om_ip)
                continue
            # x86架构的节点检查cpu type是否为[Xeon_V4、Xeon_V5、Jintide、Hygon C86]
            # Hygon C86海光服务器不检查SPDK，所以加进白名单
            # Jintide包含C4、C5、C6
            logger.info("Checking cpu type")
            cpu_arch = operate.get_cpu_arch(ssh_client)
            if cpu_arch == 'x86_64':
                ret_cmd = ssh.ssh_exec_command_return(ssh_client, X86_CPU_TYPE)
                logger.info("The x86_cpu_type query result : %s", str(ret_cmd))
                index = -2
                for content in ret_cmd:
                    if re.findall('sh /x86_cpu_type.sh', content):
                        index = ret_cmd.index(content)
                        break
                cpu_type_list = ret_cmd[index + 1:]
                logger.info("Current node[%s] cpu type list:%s" % (om_ip, cpu_type_list))
                for cpu in cpu_type_list:
                    if cpu.strip('\n') not in self.cpu_support_list:
                        logger.error("The CPU type not supported")
                        raise HCCIException(627605, om_ip)
        return


X86_CPU_TYPE = r"""
cat << EOF >/x86_cpu_type.sh
#!/bin/bash

# Hygon C86 不支持spdk,直接返回
cat /proc/cpuinfo|grep 'model name'|sort -k 3,6 -u|grep -q 'Hygon C86'
if [ \$? -eq 0 ]
then
    echo "Hygon_C86"
    exit 0
fi

#Xeon V4以上才能使用spdk
cat /proc/cpuinfo | grep 'model name' | sort -k 4,9 -u | grep -iq -e 'Xeon' -e 'Jintide'
if [ \$? -ne 0  ];then
    echo "Other"
    exit 0
fi

#C4、C5、C6
cat /proc/cpuinfo | grep 'model name' |sort -k 4,9 -u | awk -F':' '{print \$2}' | awk '{ for(i =1; i<=NF; i++) {print \$i}  }' | grep -qi -e C4215R -e C5218R -e C5220R -e C6230R -e C6330
if [  \$? -eq 0 ];then
    echo "Jintide"
    exit 0
fi

#V5
cat /proc/cpuinfo | grep 'model name' |sort -k 4,9 -u | awk -F':' '{print \$2}' | awk '{ for(i =1; i<=NF; i++) {print \$i}  }' | grep -qi -e Platinum -e Gold -e Silver -e Bronze
if [ \$? -eq 0 ];then
    echo "Xeon_V5"
fi

#V4
xeonCpuV4Verion=\$(cat /proc/cpuinfo | grep 'model name' |sort -k 4,9 -u | awk -F':' '{print \$2}' | awk '{ for(i =1; i<=NF; i++) {print \$i}  }' | grep -i -e "v[0-9]" | awk -F'v' '{print \$2}' | awk '{temp=\$1} END{print temp}')
if [ x"\${xeonCpuV4Verion}" == x"4" ];then
    echo "Xeon_V4"
fi

exit 0
EOF
sh /x86_cpu_type.sh """
