# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import utils.common.log as logger
from utils.business.hardware_driver_util import DriverApi
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.exception import HCCIException
from utils.common.fic_base import StepBaseInterface
from utils.common.fic_base import TestCase
from utils.common.message import Message
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc


class DoCheckDisk(TestCase):
    def __init__(self, project_id, pod_id):
        super(DoCheckDisk, self).__init__(project_id, pod_id)
        self.cmd_exe = BMCCmdExc()
        self.db = BaseOps()
        self.bmc_info_lists = self.db.get_install_os_list_info(self.pod_id, "rep")

    def procedure(self):
        """检查复制节点系统盘容量"""
        full_off_ip_list, other_ip_list = self.divide_ip_list()
        if full_off_ip_list:
            self.check_disk_capacity(full_off_ip_list, FULL_OFF_CMD)
        if other_ip_list:
            cmd = "fdisk -l | grep 'Disk /dev/sd' | head -n 1 | awk '{print int($5/1024/1024/1024)}'"
            self.check_disk_capacity(other_ip_list, cmd)

    def divide_ip_list(self):
        """
        根据节点是否为full_off_A划分不同节点
        :return:full_off_A节点IP列表和非full_off_A节点（Raid与half_off_A）列表
        """
        full_off_ip_list = []
        other_ip_list = []
        for sub_bmc_info in self.bmc_info_lists:
            bmc_ip = sub_bmc_info.get("bmc_ip")
            raid_card_flag = DriverApi().check_host_is_hard_raid(bmc_ip)
            if not raid_card_flag:
                full_off_ip_list.append(bmc_ip)
                msg = ("There is no RAID card on the server [%s],"
                       "full off A mode" % bmc_ip)
                logger.info(msg)
            else:
                other_ip_list.append(bmc_ip)
        logger.info("full off A bmc ip list:%s, other bmc ip list:%s" % (full_off_ip_list, other_ip_list))
        return full_off_ip_list, other_ip_list

    def check_disk_capacity(self, bmc_ip_list, cmd):
        min_size = 400
        max_size = 2048
        result = self.cmd_exe.run(bmc_ip_list, cmd)
        logger.info("Exec cmd: %s, result: %s" % (cmd, result))
        for bmc_info in self.bmc_info_lists:
            bmc_ip = bmc_info.get('bmc_ip')
            logger.info("bmc_ip:%s Disk check" % bmc_ip)
            bmc_result = result.get(bmc_ip)
            if bmc_result.get("result") != '0':
                logger.info("Disk_size check is Failed,%s!", bmc_result.get("stderr"))
                raise HCCIException("625301", bmc_result.get("stderr"))
            discs = bmc_result.get("stdout")
            if not discs:
                err_msg = "The system disk does not exist.BMC IP:{}".format(bmc_ip)
                logger.error(err_msg)
                raise Exception(err_msg)
            disk_size_list = discs.strip().split(" ")
            for disk_size in disk_size_list:
                logger.info("Disk_size is %s" % disk_size)
                if min_size <= int(disk_size) <= max_size:
                    logger.info("Disk_size check is ok !")
                    continue
                logger.error("Disk_size check is Failed! BMC: %s, Current Configuration: %s GB, "
                             "Required Configuration: %s ~ %s GB." % (bmc_ip, disk_size, min_size, max_size))
                raise HCCIException("625306", bmc_info.get("equipment_model"), bmc_ip, disk_size, min_size, max_size)


class CheckDisk(StepBaseInterface):
    def __init__(self, project_id, pod_id):
        super(CheckDisk, self).__init__(project_id, pod_id)
        self.project_id = project_id
        self.pod_id = pod_id
        self.implement = DoCheckDisk(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:
            return Message(500, e1)
        except Exception as e2:
            return Message(500, HCCIException('625301', str(e2)))
        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


# 全消A场景查询系统盘命令
FULL_OFF_CMD = r'''
fs_sd1=$(ls /sys/devices/pci0000\:74/0000\:74\:03.0/ata1/host*/target*/*/block/ 2>/dev/null)
fs_sd2=$(ls /sys/devices/pci0000\:74/0000\:74\:03.0/ata2/host*/target*/*/block/ 2>/dev/null)

rear_slot1=4
rear_slot2=5
#System disk plugged on the I/O module 1 rear plate system disk
if [ -z "${fs_sd1}" -o -z "${fs_sd2}" ]; then
    fs_sd1=$(ls /sys/devices/pci0000\:74/0000\:74\:04.0/host*/phy-*\:${rear_slot1}/port*/end_device-*/target*/*/block/ 2>/dev/null)
    fs_sd2=$(ls /sys/devices/pci0000\:74/0000\:74\:04.0/host*/phy-*\:${rear_slot2}/port*/end_device-*/target*/*/block/ 2>/dev/null)
fi

#Match slot failed, using rear panel no.4 and no.5 slot to create raid by default
if [ -z "${fs_sd1}" -o -z "${fs_sd2}" ]; then
    fs_sd1=$(ls /sys/devices/pci0000\:b4/0000\:b4\:04.0/host*/phy-*\:${rear_slot1}/port*/end_device-*/target*/*/block/ 2>/dev/null)
    fs_sd2=$(ls /sys/devices/pci0000\:b4/0000\:b4\:04.0/host*/phy-*\:${rear_slot2}/port*/end_device-*/target*/*/block/ 2>/dev/null)
fi

front_slot1=0
front_slot2=1
#Match slot failed, using front panel no.0 and no.1 slot to create raid by default
if [ -z "${fs_sd1}" -o -z "${fs_sd2}" ]; then
    fs_sd1=$(ls /sys/devices/pci0000\:74/0000\:74\:02.0/host*/phy-*\:${front_slot1}/port*/end_device-*/target*/*/block/ 2>/dev/null)
    fs_sd2=$(ls /sys/devices/pci0000\:74/0000\:74\:02.0/host*/phy-*\:${front_slot2}/port*/end_device-*/target*/*/block/ 2>/dev/null)
fi

#Match slot failed, using CPU2 front panel no.0 and no.1 slot to create raid by default
if [ -z "${fs_sd1}" -o -z "${fs_sd2}" ]; then
    fs_sd1=$(ls /sys/devices/pci0000\:b4/0000\:b4\:02.0/host*/phy-*\:${front_slot1}/port*/end_device-*/target*/*/block/ 2>/dev/null)
    fs_sd2=$(ls /sys/devices/pci0000\:b4/0000\:b4\:02.0/host*/phy-*\:${front_slot2}/port*/end_device-*/target*/*/block/ 2>/dev/null)
fi
disk_size1=$(fdisk -l | grep 'Disk /dev/'${fs_sd1} | head -n 1 | awk '{print int($5/1024/1024/1024)}')
disk_size2=$(fdisk -l | grep 'Disk /dev/'${fs_sd2} | head -n 1 | awk '{print int($5/1024/1024/1024)}')
echo ${disk_size1} ${disk_size2}
'''
