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

try:
    import os
    import subprocess
    import stat
    import sys
    import importlib

    importlib.reload(sys)
    from gspylib.inspection.common import SharedFuncs
    from gspylib.inspection.common.CheckItem import BaseItem
    from gspylib.inspection.common.CheckResult import ResultStatus
    from gspylib.common.DbClusterStatus import DbClusterStatus
    from gspylib.common.Common import ClusterCommand
    from gspylib.os.gsfile import g_file
except ImportError as e:
    raise Exception("[GAUSS-52200] : Unable to import module: %s." % str(e))

KEY_FILE_MODE = 600


class CheckClusterState(BaseItem):
    def __init__(self):
        super(CheckClusterState, self).__init__(self.__class__.__name__)

    def doCheck(self):
        tmpFile = os.path.join(self.tmpPath, "gauss_cluster_status.dat")
        self.result.val = ""
        self.result.raw = ""
        # Check the cm_server process
        cmd = "pgrep -U %s cm_agent" % self.user
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            self.result.val += "Process cm_agent does not exist."
            self.result.rst = ResultStatus.NG
        # Check the cm_server process
        nodeInfo = self.cluster.getDbNodeByName(self.host)
        if len(nodeInfo.cmservers) != 0:
            cmd = "pgrep -U %s cm_server" % self.user
            (status, output) = subprocess.getstatusoutput(cmd)
            if status != 0:
                self.result.val += "\nProcess cm_server does not exist."
                self.result.rst = ResultStatus.NG
        if self.result.rst == ResultStatus.NG:
            return
        # Check the cluster status with cm_ctl
        cmd = ClusterCommand.getQueryStatusCmd(self.user, 0, tmpFile)
        output = SharedFuncs.runShellCmd(cmd, self.user, self.mpprcFile)
        self.result.raw += output
        # Check whether the cluster needs to be balanced
        # Check whether redistribution is required
        # Initialize cluster status information for temporary file
        clusterStatus = DbClusterStatus()
        clusterStatus.initFromFile(tmpFile)
        # Get the status of cluster
        statusInfo = clusterStatus.getClusterStauts()
        self.result.val = statusInfo
        # check fencedUDFs
        AbnormalfencedUDFNode = []
        if hasattr(clusterStatus.dbNodes[0], 'fencedUDFs') and len(clusterStatus.dbNodes[0].fencedUDFs) > 0:
            for nodeStatus in clusterStatus.dbNodes:
                if not nodeStatus.fencedUDFs[0].isInstanceHealthy():
                    AbnormalfencedUDFNode.append(nodeStatus.name)
            if AbnormalfencedUDFNode:
                self.result.val += "The gaussdb fenced UDF master process status is down on host[%s]" \
                                   % ",".join(AbnormalfencedUDFNode)
        if clusterStatus.isAllHealthy():
            if AbnormalfencedUDFNode:
                self.result.rst = ResultStatus.WARNING
            else:
                self.result.rst = ResultStatus.OK
            if os.path.exists(tmpFile):
                os.remove(tmpFile)
            return
        self.print_abnormal_node_details(clusterStatus, tmpFile)

    def print_abnormal_node_details(self, cluster_status, tmp_file):
        # If the abnormal node is present, create a temporary file and print out the details
        tmpFileName = os.path.join(self.tmpPath, "abnormal_node_status.dat")
        g_file.createFile(tmpFileName, True, KEY_FILE_MODE)
        flags = os.O_RDWR | os.O_CREAT
        modes = stat.S_IWUSR | stat.S_IRUSR
        tmpFileFp = os.fdopen(os.open(tmpFileName, flags, modes), "w+")
        for dbNode in cluster_status.dbNodes:
            if not dbNode.isNodeHealthy():
                dbNode.outputNodeStatus(tmpFileFp, self.user, True)
        tmpFileFp.flush()
        tmpFileFp.seek(0)
        self.result.raw = tmpFileFp.read()
        tmpFileFp.close()
        if self.result.raw == "":
            self.result.raw = "Failed to obtain the cluster status."
        self.result.rst = ResultStatus.NG
        # Delete the temporary file
        if os.path.exists(tmpFileName):
            os.remove(tmpFileName)
        if os.path.exists(tmp_file):
            os.remove(tmp_file)
