#!/usr/bin/env python3
# -*- coding:utf-8 -*-


try:
    import sys
    import importlib

    importlib.reload(sys)
    import os
    from gspylib.inspection.common import SharedFuncs
    from gspylib.inspection.common.CheckItem import BaseItem
    from gspylib.inspection.common.CheckResult import ResultStatus
    from gspylib.hardware.gsdisk import g_disk
except ImportError as ie:
    raise Exception("[GAUSS-52200] : Unable to import module: %s." % str(ie))

TOTAL_THRESHOLD_NG = 500000000


class CheckInodeUsage(BaseItem):
    def __init__(self):
        super(CheckInodeUsage, self).__init__(self.__class__.__name__)
        self.Threshold_NG = None
        self.Threshold_Warning = None

    def preCheck(self):
        # check current node contains cn instances if not raise  exception
        super(CheckInodeUsage, self).preCheck()
        # check the threshold was set correctly
        if (not (self.threshold.__contains__('Threshold_NG') and self.threshold.__contains__('Threshold_Warning'))):
            raise Exception("The threshold Threshold_NG and Threshold_Warning can not be empty.")
        if (not self.threshold['Threshold_NG'].isdigit() or not self.threshold['Threshold_Warning'].isdigit()):
            raise Exception("The threshold Threshold_NG[%s] and Threshold_Warning[%s] must be integer." % (
                self.Threshold_NG, self.Threshold_Warning))
        self.Threshold_NG = int(self.threshold['Threshold_NG'])
        self.Threshold_Warning = int(self.threshold['Threshold_Warning'])
        if (self.Threshold_NG < self.Threshold_Warning):
            raise Exception("The threshold Threshold_NG[%d] must be greater than Threshold_Warning[%d]." % (
                self.Threshold_NG, self.Threshold_Warning))
        if (self.Threshold_NG > 99 or self.Threshold_Warning < 1):
            raise Exception("The threshold Threshold_NG[%d] and Threshold_Warning[%d] must be integer from 1 to 99." % (
                self.Threshold_NG, self.Threshold_Warning))

    def obtainDataDir(self, nodeInfo):
        dataDirList = []
        for inst in nodeInfo.datanodes:
            dataDirList.append(inst.datadir)
        for inst in nodeInfo.cmservers:
            dataDirList.append(inst.datadir)
        for inst in nodeInfo.coordinators:
            dataDirList.append(inst.datadir)
        for inst in nodeInfo.gtms:
            dataDirList.append(inst.datadir)
        if (hasattr(nodeInfo, 'etcds')):
            for inst in nodeInfo.etcds:
                dataDirList.append(inst.datadir)

        dataDirList.append(os.getenv("PGHOST"))
        dataDirList.append(os.getenv("GPHOME"))
        dataDirList.append(os.getenv("GAUSSHOME"))
        dataDirList.append(os.getenv("GAUSSLOG"))
        dataDirList.append("/tmp")
        return dataDirList

    def obtainDiskDir(self):
        cmd = "df -h -P | awk '{print $6}'"
        output = SharedFuncs.runShellCmd(cmd)
        allDiskPath = output.split('\n')[1:]
        return allDiskPath

    def doCheck(self):
        flag = "Normal"
        resultStr = ""
        DiskList = []
        DiskInfoDict = {}
        if self.cluster:
            pathList = self.obtainDataDir(self.cluster.getDbNodeByName(self.host))
        else:
            pathList = self.obtainDiskDir()

        for path in pathList:
            diskName = g_disk.getMountPathByDataDir(path)
            diskType = g_disk.getDiskMountType(diskName)
            if diskType not in ["xfs", "ext3", "ext4"]:
                resultStr = "%sPath(%s) inodes usage(%s)     " \
                             "Warning reason: The file system type [%s] is unrecognized or not support." \
                             " Please check it.\n" % (resultStr, path, 0, diskType)
                if flag == "Normal":
                    flag = "Warning"
                continue
            usageInfo = round(g_disk.getDiskInodeUsage(path), 2)
            if diskName in DiskList:
                continue
            else:
                DiskList.append(diskName)
            DiskInfoDict[usageInfo] = "%s %s%%" % (diskName, usageInfo)
            if usageInfo > self.Threshold_NG:
                resultStr = "%sThe usage of the device disk inodes[%s:%d%%] cannot be greater than %d%%.\n" % (
                    resultStr, diskName, usageInfo, self.Threshold_NG)
                flag = "Error"
            elif usageInfo > self.Threshold_Warning:
                resultStr = "%sThe usage of the device disk inodes[%s:%d%%] cannot be greater than %d%%.\n" % (
                    resultStr, diskName, usageInfo, self.Threshold_Warning)
                if flag == "Normal":
                    flag = "Warning"
        self.result.val = resultStr
        if flag == "Normal":
            self.result.rst = ResultStatus.OK
            self.result.val = "All disk inodes are sufficient."
        elif flag == "Warning":
            self.result.rst = ResultStatus.WARNING
        else:
            self.result.rst = ResultStatus.NG

        keys = list(DiskInfoDict.keys())
        keys.sort()
        self.result.raw = "diskname inodeUsage"
        for diskInfo in map(DiskInfoDict.get, keys):
            self.result.raw = "%s\n%s" % (self.result.raw, diskInfo)
