# -*- coding: utf-8 -*-
import utils.common.log as logger
from plugins.ResourceCheck.common.libs.BMCCmd import BMCCmdExc
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


class DoCheckDisk(TestCase):
    def pre_condition(self):
        pass

    def procedure(self):

        """
        检查eBackupDISK
       """
        try:
            # 查询带装机的IP
            self.cmd_exe = BMCCmdExc()
            self.db = BaseOps()
            self.bmc_info_lists = self.db.get_install_os_list_info(self.pod_id, "rep")
            # 判断是否为全消A场景,全消A场景与非全消A场景查询硬盘容量执行不同命令
            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)
            return True, None
        except HCCIException as e1:
            raise e1
        except Exception as e2:
            raise e2

    def divide_ip_list(self):
        """
        根据节点是否为full_off_A划分不同节点
        :param project_id:
        :param pod_id:
        :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):
        disk_min_required = 400
        disk_max_required = 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:
            logger.info("bmc_ip:%s Disk check" % bmc_info['bmc_ip'])
            bmc_result = result[bmc_info["bmc_ip"]]
            if bmc_result["result"] == '0':
                discs = bmc_result["stdout"]
                if not discs:
                    err_msg = "The first disk does not exist."
                    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 int(disk_size) >= disk_min_required and int(disk_size) <= disk_max_required:
                        logger.info("Disk_size check is ok !")
                    else:
                        logger.error("Disk_size check is Failed! BMC: %s,"
                                     " Current Configuration: %s GB, Required Configuration: %s ~ %s GB." %
                                     (bmc_info['bmc_ip'], disk_size,
                                      disk_min_required, disk_max_required))

                        raise HCCIException("625306", bmc_info["equipment_model"],
                                           bmc_info['bmc_ip'], disk_size,
                                           disk_min_required, disk_max_required
                                           )

            else:
                logger.info("Disk_size check is Failed,%s!", bmc_result["stderr"])
                raise HCCIException("625301", bmc_result["stderr"])

    def post_condition(self):
        pass

    def failure(self):
        super(DoCheckDisk, self).failure()
        # 环境恢复脚本


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()
            return Message(200)
        except HCCIException as e1:
            return Message(500, e1)
        except Exception as e2:
            return Message(500, HCCIException('625301', str(e2)))

    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'''
rear_slot1=4
rear_slot2=5
#System disk plugged on the I/O module 1 rear plate system disk
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)

#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}
'''
