#!/usr/bin/env python3
#-*- coding:utf-8 -*-
try:
    import sys
    import importlib
    importlib.reload(sys)
    from gspylib.inspection.common.CheckItem import BaseItem
    from gspylib.inspection.common.CheckResult import ResultStatus
    from gspylib.os.gsfile import g_file
except ImportError as ie:
    raise Exception("[GAUSS-52200] : Unable to import module: %s." % str(ie))


class CheckPortRange(BaseItem):
    def __init__(self):
        super(CheckPortRange, self).__init__(self.__class__.__name__)
        self.ip_local_port_range = None

    def preCheck(self):
        # check current node contains cn instances if not raise  exception
        super(CheckPortRange, self).preCheck()
        # check the threshold was set correctly
        if (not self.threshold.__contains__('ip_local_port_range')):
            raise Exception("threshold ip_local_port_range can not be empty")
        self.ip_local_port_range = self.threshold['ip_local_port_range']

    def getPort(self):
        cooInst = None
        portList = {}
        dbNode = self.cluster.getDbNodeByName(self.host)
        # get node port from cmserver
        for cmsInst in dbNode.cmservers:
            portList[cmsInst.port] = cmsInst.instanceRole
            portList[cmsInst.haPort] = cmsInst.instanceRole
        # get node port from gtm
        for gtmInst in dbNode.gtms:
            portList[gtmInst.port] = gtmInst.instanceRole
            portList[gtmInst.haPort] = gtmInst.instanceRole
        # get node port from cn
        for cooInst in dbNode.coordinators:
            portList[cooInst.port] = cooInst.instanceRole
            portList[cooInst.haPort] = cooInst.instanceRole
        # get node port from dn
        for dnInst in dbNode.datanodes:
            portList[dnInst.port] = dnInst.instanceRole
            portList[dnInst.haPort] = dnInst.instanceRole
        if (hasattr(dbNode, 'etcds')):
            for etcdInst in dbNode.etcds:
                portList[etcdInst.port] = etcdInst.instanceRole
                portList[etcdInst.haPort] = etcdInst.instanceRole

        return portList

    def doCheck(self):
        parRes = ""
        flag = None
        instance = {0: "CMSERVER", 1: "GTM", 2: "ETCD", 3: "COODINATOR", 4: "DATANODE", 5: "CMAGENT"}
        portList = self.getPort()
        #Check the port range
        output = g_file.readFile('/proc/sys/net/ipv4/ip_local_port_range')[0].strip()
        smallValue = output.split('\t')[0].strip()
        bigValue = output.split('\t')[1].strip()
        expect = self.ip_local_port_range.split()
        if (int(smallValue) < int(expect[0].strip()) or int(bigValue) > int(expect[1].strip())):
            parRes += "The value of net.ipv4.ip_local_port_range is incorrect, expect value is %s.\n"\
                      % self.ip_local_port_range
        parRes += "The value of net.ipv4.ip_local_port_range is %d %d." % (int(smallValue), int(bigValue))

        for port in portList.keys():
            if (int(port) <= int(bigValue) and int(port) >= int(smallValue)):
                flag = 1
                parRes += "\n            %s" % (
                    "The instance %s port \"%d\" is incorrect." % (instance[portList[port]], int(port)))
        if (flag == 1):
            self.result.rst = ResultStatus.NG
        else:
            self.result.rst = ResultStatus.OK
        self.result.val = parRes
        self.result.raw = output
