# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import traceback

import utils.common.log as logger
from utils.common.fic_base import StepBaseInterface
from utils.common.fic_base import TestCase
from utils.common.message import Message
from utils.common.exception import HCCIException
from plugins.ResourceCheck.common.libs import common_libs
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc


class DoCheckTenantFBHeterogeneousSSD(TestCase):

    @classmethod
    def get_huawei_server_node(cls, bmc_ip_list, cmd_exe):
        logger.info('Start to exec cmd to bmc, bmc list：%s' % bmc_ip_list)
        cmd = "ipmitool fru print 0 | grep Huawei | wc -l"
        result_all = cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result_all))
        not_huawei_list = list()
        logger.info('Start to check nvme ssd')
        for bmc_ip in bmc_ip_list:
            result = result_all[bmc_ip]['stdout']
            if int(result) == 0:
                logger.info('node %s is not a Huawei server' % bmc_ip)
                not_huawei_list.append(bmc_ip)
        return not_huawei_list

    @classmethod
    def get_ssd_card_node(cls, bmc_list):
        bmc_ip_list = list()
        for bmc in bmc_list:
            bmc_ip = bmc.get("bmc_ip")
            cache_type = bmc.get("cache_type")
            if cache_type == 'ssd_card':
                logger.info('Need to check BMC: %s' % bmc_ip)
                bmc_ip_list.append(bmc_ip)
        return bmc_ip_list

    def procedure(self):
        """分离部署,检查存储节点SSD硬盘数量和类型:1. 资源池内的SSD卡/SSD盘数量和类型必须一致。2. 资源池内缓存介质类型一致。"""
        common_libs.check_flag()
        bmc_list = self.db.get_install_os_list_info(self.pod_id)
        if not bmc_list:
            return

        bmc_ip_list = self.get_ssd_card_node(bmc_list)
        if not bmc_ip_list:
            logger.info('No bmc found')
            return
        cmd_exe = BMCCmdExc()
        not_huawei_list = self.get_huawei_server_node(bmc_ip_list, cmd_exe)
        if not_huawei_list:
            logger.error('These nodes is not a Huawei server: %s, skip.' % not_huawei_list)
            return

        # 19e5:0123/19e5:3714：ES3000 V3/V5
        # 144d:a822/144d:a824：Samsung PM1725b/PM1735
        # 8086:0a54：Intel P4610
        # 1e81:1203/1cc4:1203：白牌A28
        cmd = "lspci -n | grep -E '19e5:0123|19e5:3714|144d:a822|144d:a824|8086:0a54|1e81:1203|1cc4:1203' | wc -l"
        result_all = cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result_all))
        fail_list = list()
        logger.info('Start to check nvme ssd')
        for bmc_ip in bmc_ip_list:
            result = result_all[bmc_ip]['stdout']
            if int(result) > 0:
                logger.info('node %s has %s nvme SSD' % (bmc_ip, result))
            else:
                logger.info('node %s has no nvme SSD' % bmc_ip)
                fail_list.append(bmc_ip)
        if fail_list:
            logger.error('These nodes have no nvme ssd %s' % fail_list)
            raise HCCIException(113191, str(fail_list))

        logger.info('start to check nvme ssd count')
        ssd_count = None
        first_bmc = None
        for bmc_ip in bmc_ip_list:
            result = result_all[bmc_ip]['stdout']
            if ssd_count is None:
                ssd_count = int(result)
                first_bmc = bmc_ip
            if int(result) != ssd_count:
                logger.error("bmc[%s] ssd card number(%s) is difference with first bmc[%s] ssd card number(%s)"
                             % (bmc_ip, int(result), first_bmc, ssd_count))
                raise HCCIException(113192, bmc_ip, first_bmc)


class CheckTenantFBHeterogeneousSSD(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        self.project_id = project_id
        self.pod_id = pod_id
        self.implement = DoCheckTenantFBHeterogeneousSSD(project_id, pod_id)

    def pre_check(self, project_id, pod_id):
        """
        插件内部接口：执行安装前的资源预检查，该接口由execute接口调用，工具框架不会直接调用此接口。
        :param project_id:
        :param pod_id:
        :return:
        """
        pass

    def execute(self, project_id, pod_id):
        try:
            self.implement.procedure()
        except HCCIException as e1:
            logger.error("TenantFB ssd_card check error:{}".format(traceback.format_exc()))
            return Message(500, e1)
        except Exception as e:
            logger.error("TenantFB ssd_card check error:{}".format(traceback.format_exc()))
            return Message(500, e)
        return Message(200)

    def rollback(self, project_id, pod_id):
        """
        标准调用接口：执行回滚
        :param project_id:
        :param pod_id:
        :return:Message类对象
        """
        return Message(200)

    def retry(self, project_id, pod_id):
        """
        标准调用接口：重试
        :return: Message类对象
        """
        return self.execute(project_id, pod_id)

    def check(self, project_id, pod_id):
        """
        标准调用接口：重试
        :param project_id:
        :param pod_id:
        :return:
        """
        pass

