#!/usr/bin/env python3
# -*- coding:utf-8 -*-
try:
    import sys
    import subprocess
    import os
    import pwd
    import time
    import re
    import socket
    import stat
    import multiprocessing
    from datetime import datetime, timedelta
    from gspylib.common.Common import DefaultValue, ClusterCommand
    from gspylib.common.VersionInfo import VersionInfo
    from gspylib.common.DbClusterStatus import DbClusterStatus
    from multiprocessing.pool import ThreadPool
    from gspylib.os.gsfile import g_file

    from gspylib.hardware.gsdisk import g_disk
    from gspylib.os.gsnetwork import g_network
    from gspylib.os.platform import support_platform
    from gspylib.os.gsplatform import Platform, g_Platform
    from gspylib.inspection.common.Exception import TrustException, ShellCommandException, SshCommandException, \
        SQLCommandException

    localPath = os.path.dirname(__file__)
    sys.path.insert(0, localPath + "/../lib")
except ImportError as ie:
    sys.exit("[GAUSS-52200] : Unable to import module: %s." % str(ie))

FILE_MODE = 640
FILE_WRITE_MODE = 220
DIRECTORY_MODE = 750
KEY_FILE_MODE = 600
KEY_DIRECTORY_MODE = 700
MAX_FILE_NODE = 755
MAX_DIRECTORY_NODE = 755
INIT_FILE_SUSE = "/etc/init.d/boot.local"
INIT_FILE_REDHAT = "/etc/rc.d/rc.local"


def runShellCmd(cmd, user=None, mpprcFile=""):
    if (mpprcFile):
        cmd = "source '%s'; %s" % (mpprcFile, cmd)
    # Set the output LANG to English
    cmd = "export LC_ALL=C; %s" % cmd
    # change user but can not be root user
    if (user and user != getCurrentUser()):
        cmd = "su - %s -c \"source /etc/profile 2>/dev/null; %s\"" % (user, cmd)
    (status, output) = subprocess.getstatusoutput(cmd)
    if (status != 0):
        raise ShellCommandException(cmd, output)
    return output


def runSshCmd(cmd, host, user="", mpprcFile="", timeout=""):
    if (timeout):
        timeout = "-o ConnectTimeout=%s" % timeout
    if (mpprcFile):
        cmd = "source '%s'; %s" % (mpprcFile, cmd)
    # Set the output LANG to English
    cmd = "export LC_ALL=C; %s" % cmd
    # RedHat does not automatically source /etc/profile but SuSE executes when using ssh to remotely execute commands
    # Some environment variables are written in /etc/profile when there is no separation of environment variables
    if host == socket.gethostname():
        sshCmd = cmd
    else:
        sshCmd = "export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH; " \
                 "ssh %s -n %s %s 'source /etc/profile 2>/dev/null;%s'" % (host, DefaultValue.SSH_OPTION, timeout, cmd)
    if (user and user != getCurrentUser()):
        sshCmd = "su - %s -c \"%s\"" % (user, sshCmd)
    (status, output) = subprocess.getstatusoutput(sshCmd)
    if (status != 0):
        raise SshCommandException(host, sshCmd, output)
    return output


def runSshCmdWithPwd(cmd, host, user="", passwd="", mpprcFile=""):
    # Environment variables separation
    if (mpprcFile):
        cmd = "source '%s'; %s" % (mpprcFile, cmd)
    ssh = None
    try:
        if (passwd):
            import paramiko
            cmd = "export LC_ALL=C; source /etc/profile 2>/dev/null; %s" % cmd
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # Remote Connection
            ssh.connect(host, 22, user, passwd)
            _, stdout, stderr = ssh.exec_command(cmd)
            output = stdout.read()
            error = stderr.read()
            if (error):
                raise SshCommandException(host, cmd, error)
            return output.decode()
        else:
            cmd = "export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH; " \
                  "ssh %s \"export LC_ALL=C; source /etc/profile 2>/dev/null; %s\"" % (host, cmd)
            (status, output) = subprocess.getstatusoutput(cmd)
            if (status != 0):
                raise SshCommandException(host, cmd, output)
            return output
    except Exception as e:
        raise Exception(str(e))
    finally:
        if (ssh):
            ssh.close()


def runRootCmd(cmd, rootuser, passwd, mpprcFile=''):
    if (mpprcFile):
        cmd = "source '%s'; %s" % (mpprcFile, cmd)
    ssh = None
    try:
        import paramiko
        cmd = "export LC_ALL=C; source /etc/profile 2>/dev/null; %s" % cmd
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect('localhost', 22, rootuser, passwd)
        _, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
        output = stdout.read()
        error = stderr.read()
        if (error):
            raise SshCommandException("localhost", cmd, error)
        return output.decode()
    except Exception as e:
        raise Exception(str(e))
    finally:
        if (ssh):
            ssh.close()


def verifyPasswd(host, user, pswd=None):
    # Connect to the remote node
    import paramiko
    ssh = paramiko.Transport((host, 22))
    try:
        ssh.connect(username=user, password=pswd)
        return True
    except paramiko.AuthenticationException:
        return False
    finally:
        ssh.close()


def cleanOutput(output):
    # clean warning or password message
    lines = output.splitlines()
    if (len(lines) == 0):
        return ''
    idx = 1
    for line in lines:
        if (line.lower().find('password:') != -1):
            break
        idx += 1
    return output if idx == len(lines) + 1 else "\n".join(lines[idx:])


def runSqlCmdWithTimeOut(sql, user, host, port, tmpPath, database="postgres", mpprcFile="", needmpara=False,
                         timeout=60):
    infoList = [[sql, user, host, port, tmpPath, database, mpprcFile, needmpara]]
    endTime = datetime.now() + timedelta(seconds=timeout)
    pool = ThreadPool(1)
    result = pool.map_async(executeSql, infoList)
    while datetime.now() < endTime:
        if (result.ready()):
            pool.close()
            if (result._value[0] == "NO RESULT"):
                return ""
            elif (result._value[0].startswith("ERROR")):
                raise SQLCommandException(sql, result._value[0])
            else:
                return result._value[0]
        else:
            time.sleep(1)
    pool.close()
    raise SQLCommandException(sql, "Running timeout, exceed the limit %s seconds" % timeout)


def executeSql(paraList):
    sql = paraList[0]
    user = paraList[1]
    host = paraList[2]
    port = paraList[3]
    tmpPath = paraList[4]
    database = paraList[5]
    mpprcFile = paraList[6]
    needmpara = paraList[7]
    try:
        output = runSqlCmd(sql, user, host, port, tmpPath, database, mpprcFile, needmpara)
        if (not output):
            output = "NO RESULT"
    except Exception as e:
        output = "ERROR:%s" % (str(e))
    return output


def runSqlCmd(sql, user, host, port, tmpPath, database="postgres", mpprcFile="", maintenance=False):
    """
    function : Execute sql command
    input : String,String,String,int
    output : String
    """
    database = database.replace('$', '\$')
    # Get the current time
    currentTime = time.strftime("%Y-%m-%d_%H%M%S")
    # Get the process ID
    pid = os.getpid()
    # init SQL query file
    sqlFile = os.path.join(tmpPath,
                           "check_query.sql_%s_%s_%s" % (str(port), str(currentTime), str(pid)))
    # init SQL result file
    queryResultFile = os.path.join(tmpPath,
                                   "check_result.sql_%s_%s_%s" % (str(port), str(currentTime), str(pid)))
    # Clean up the file
    cleanFile("%s,%s" % (queryResultFile, sqlFile))

    # write the SQL command into sql query file
    try:
        g_file.write_file_with_default_permission(sqlFile, sql)
        os.chmod(sqlFile, stat.S_IRWXU | stat.S_IROTH)
    except Exception as e:
        # Clean up the file
        cleanFile(sqlFile)
        raise SQLCommandException(sql, "write into sql query file failed. " + str(e))

    # read the content of query result file.
    try:
        # init host
        hostPara = ("-h %s" % host) if host != "" and host != "localhost" and host != socket.gethostname() else ""
        # build shell command
        if hostPara:
            cmd = "gsql %s -p %s -d %s -f %s --output %s -t -A -X" % (hostPara, port, database, sqlFile,
                                                                      queryResultFile)
        else:
            cmd = "gsql postgresql://:%s/%s?application_name='OM' -f %s --output %s -t -A -X" % (
                port, database, sqlFile, queryResultFile)
        if (maintenance):
            cmd += ' -m'
        # Environment variables separation
        if mpprcFile != "":
            cmd = "source '%s' && " % mpprcFile + cmd
        # Execute the shell command
        output = runShellCmd(cmd, user)
        if (findErrorInSqlFile(sqlFile, output) is True):
            raise Exception(output)

        # Reading documents
        with open(queryResultFile, 'r') as fp:
            rowList = fp.readlines()
    except Exception as e:
        cleanFile("%s,%s" % (queryResultFile, sqlFile))
        if isinstance(e, ShellCommandException):
            output = e.output
        else:
            output = str(e)
        raise SQLCommandException(sql, output)

    # remove local sqlFile
    cleanFile("%s,%s" % (queryResultFile, sqlFile))

    return "".join(rowList)[:-1]


def runSqlSimplely(sql, user, host, port, tmpPath, database="postgres", mpprcFile="", needmpara=False):
    """
    function : Execute sql command
    input : String,String,String,int
    output : String
    """
    # Get the current time
    currentTime = time.strftime("%Y-%m-%d_%H%M%S")
    # Get the process ID
    pid = os.getpid()
    # init SQL query file
    sqlFile = os.path.join(tmpPath,
                           "check_query.sql_%s_%s_%s" % (str(port), str(currentTime), str(pid)))

    # Clean up the file
    if (os.path.exists(sqlFile)):
        cleanFile("%s" % (sqlFile))

    # write the SQL command into sql query file
    try:
        g_file.write_file_with_default_permission(sqlFile, sql)
        os.chmod(sqlFile, stat.S_IRWXU | stat.S_IROTH)
    except Exception as e:
        # Clean up the file
        cleanFile(sqlFile)
        raise SQLCommandException(sql, "write into sql query file failed. " + str(e))

    # read the content of query result file.
    try:
        # init host
        hostPara = ("-h %s" % host) if host != "" and host != "localhost" else ""
        # build shell command
        if (needmpara):
            cmd = "gsql %s -p %s -d %s -f %s  -m" % (hostPara, port, database, sqlFile)
        else:
            cmd = "gsql %s -p %s -d %s -f %s" % (hostPara, port, database, sqlFile)
        # Environment variables separation
        if mpprcFile != "":
            cmd = "source '%s' && " % mpprcFile + cmd
        # Execute the shell command
        output = runShellCmd(cmd, user)
        if (findErrorInSqlFile(sqlFile, output) is True):
            raise Exception(output)

        # Reading documents
    except Exception as e:
        cleanFile("%s" % (sqlFile))
        if isinstance(e, ShellCommandException):
            output = e.output
        else:
            output = str(e)
        raise SQLCommandException(sql, output)

    # remove local sqlFile
    cleanFile("%s" % (sqlFile))

    return output


def findErrorInSqlFile(sqlFile, output):
    """
    function : Find error in the sql file
    input : String,String
    output : String
    """
    GSQL_BIN_FILE = "gsql"
    # init flag
    ERROR_MSG_FLAG = "(ERROR|FATAL|PANIC)"
    GSQL_ERROR_PATTERN = "^%s:%s:(\d*): %s:.*" % (GSQL_BIN_FILE, sqlFile, ERROR_MSG_FLAG)
    pattern = re.compile(GSQL_ERROR_PATTERN)
    for line in output.split("\n"):
        line = line.strip()
        result = pattern.match(line)
        if (result is not None):
            return True
    return False


def cleanFile(fileName, hostname=""):
    """
    function : remove file
    input : String,hostname
    output : NA
    """
    fileList = fileName.split(",")
    cmd = ""
    for fileStr in fileList:
        if cmd != "":
            cmd += ';(if [ -f %s ];then rm -f %s;fi)' % (fileStr, fileStr)
        else:
            cmd = '(if [ -f %s ];then rm -f %s;fi)' % (fileStr, fileStr)
    if hostname == "":
        (status, output) = subprocess.getstatusoutput(cmd)
        if (status != 0):
            raise Exception("[GAUSS-50207] : Failed to delete file." + " Error: \n%s" % output)
    else:
        sshCmd = "export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH; " \
                 "ssh %s -n %s '%s'" % (hostname, DefaultValue.SSH_OPTION, cmd)
        (status, output) = subprocess.getstatusoutput(sshCmd)
        if (status != 0):
            raise Exception("[GAUSS-50207] : Failed to delete file." + " Error: \n%s" % output)


def getFirstCNInstance(user, mpprcFile, tmpPath):
    """
    function: get first CN instance for the cluster
    @param prepare: prepare object
    @return: CN instance
    """
    # 1.get the information from static config file
    hostname = socket.gethostname()
    flag = False
    tmpFile = os.path.join(tmpPath, "gauss_cluster_status.dat")
    cmd = ClusterCommand.getQueryStatusCmd(user, 0, tmpFile)
    runShellCmd(cmd, user, mpprcFile)
    clusterStatus = DbClusterStatus()
    clusterStatus.initFromFile(tmpFile)
    if (os.path.exists(tmpFile)):
        os.remove(tmpFile)
    for dbNode in clusterStatus.dbNodes:
        if (len(dbNode.coordinators) != 0):
            cooInst = dbNode.coordinators[0]
            if (cooInst.isInstanceHealthy()):
                if (hostname == dbNode.name):
                    flag = True
                break
    return flag


def getVersion():
    """
    Get current file version by VersionInfo

    """
    return ("%s %s" % (sys.argv[0].split("/")[-1], VersionInfo.COMMON_VERSION))


def createFolder(folderName, path, permission=DIRECTORY_MODE, user=""):
    # Folder path
    folderName = os.path.join(path, folderName)
    # Create a folder
    g_file.createDirectory(folderName, True, permission)
    # change owner
    if (user):
        g_file.changeOwner(user, folderName)
    return folderName


def createFile(fileName, path, permission=FILE_MODE, user=""):
    # file path
    fileName = os.path.join(path, fileName)
    # Create a file
    g_file.createFile(fileName, True, permission)
    # change owner
    if (user):
        g_file.changeOwner(user, fileName)
    return fileName


def chmodFile(fileName, permission=FILE_MODE, user=""):
    # Modify the file permissions
    g_file.changeMode(permission, fileName)
    if (user):
        g_file.changeOwner(user, fileName)


def writeFile(fileName, content, path, permission=FILE_MODE, user=""):
    filePath = os.path.join(path, fileName)
    # Create a file
    g_file.createFile(filePath, True, permission)
    # Modify the file permissions
    if (user):
        g_file.changeOwner(user, filePath)
    g_file.writeFile(filePath, [content])


def readFile(fileName):
    # Get the contents of the file
    text = g_file.readFile(fileName)
    return "\n".join(text)


def sendFile(fileName, host, user, path, passwd=None):
    # Copy files remotely
    t = None
    if (passwd):
        try:
            import paramiko
            t = paramiko.Transport((host, 22))
            t.connect(username=user, password=passwd)
            sftp = paramiko.SFTPClient.from_transport(t)
            sftp.put(fileName, os.path.join(path, os.path.basename(fileName)))
        except Exception as e:
            raise Exception(str(e))
        finally:
            if (t):
                t.close()
    else:
        host = "%s@%s" % (user, g_network.makeSCPHost(host))
        cmd = "export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH; scp %s %s:%s" % (fileName, host, path)
        if (os.getuid() == 0):
            cmd = "su - %s -c \"%s\"" % (user, cmd)
        runShellCmd(cmd)


def receiveFile(fileName, host, user, path, passwd=None):
    # Receive remote files
    t = None
    if (passwd):
        try:
            import paramiko
            t = paramiko.Transport((host, 22))
            t.connect(username=user, password=passwd)
            sftp = paramiko.SFTPClient.from_transport(t)
            if isinstance(fileName, list):
                for fname in fileName:
                    sftp.get(fname, os.path.join(path, os.path.basename(fname)))
            else:
                sftp.get(fileName, os.path.join(path, fileName))
        except Exception as e:
            raise Exception(str(e))
        finally:
            if (t):
                t.close()
    else:
        host = "%s@%s" % (user, g_network.makeSCPHost(host))
        cmd = "export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH; scp %s:%s %s " % (host, fileName, path)
        if (os.getuid() == 0):
            cmd = "su - %s -c \"%s\"" % (user, cmd)
        runShellCmd(cmd)


def getCurrentUser():
    # Get the current user
    for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
        user = os.environ.get(name)
        if user:
            return user
    # If not user from os.environ.get()
    return pwd.getpwuid(os.getuid())[0]


def verifyTrust(hosts, user):
    """
    function: Ensure the proper password-less access to the remote host.
    input : hostname
    output: True/False
    """
    try:
        pool = ThreadPool(multiprocessing.cpu_count())
        params = zip(hosts, [user, ])
        results = pool.map(lambda x: checkAuthentication(x[0], x[1]), params)
        pool.close()
        pool.join()
        hostnames = ""
        for (key, value) in results:
            if (not key):
                hostnames = hostnames + ',' + value
        if (hostnames != ""):
            raise TrustException(hostnames)
    except Exception:
        raise TrustException(",".join(hosts))
    return True


def checkAuthentication(host, user):
    cmd = 'ssh -n -o "BatchMode=yes" -o "StrictHostKeyChecking=no" %s true' % host
    try:
        runSshCmd(cmd, host, user)
    except Exception:
        return (False, host)
    return (True, host)


def checkClusterUser(username, mpprcFile=''):
    try:
        pwd.getpwnam(username).pw_gid
    except Exception:
        return False
    mpprc = mpprcFile if mpprcFile else '~/.bashrc'
    cmd = "echo \"%s$GAUSS_ENV\" 2>/dev/null" % ("\\" if (username and username != getCurrentUser()) else "")
    try:
        output = runShellCmd(cmd, username, mpprc)
        gaussEnv = output.split("\n")[0]
        if (gaussEnv is None or gaussEnv == ""):
            return False
    except Exception:
        return False
    return True


def getMasterDnNum(user, mpprcFile):
    """
    function : get cluster master dn number
    input  : string, string
    output : List
    """
    masterDnList = []
    cmd = "cm_ctl query -v | grep -E 'instance_state\ *:\ Primary' -B 4| grep -E 'type\ *:\ Datanode' -B 3" \
          "| grep instance_id|awk '{print $NF}'"
    output = runShellCmd(cmd, user, mpprcFile)
    for line in output.split('\n'):
        if (line.isdigit()):
            masterDnList.append(int(line))
    return masterDnList


def checkBondMode(bondingConfFile):
    """
    function : Check Bond mode
    input  : String, bool
    output : List
    """

    netNameList = []
    cmd = "grep -w 'Bonding Mode' %s | awk  -F ':' '{print $NF}'" % bondingConfFile
    (status, output) = subprocess.getstatusoutput(cmd)
    if (status != 0 or output.strip() == ""):
        pass

    cmd = "grep -w 'Slave Interface' %s | awk  -F ':' '{print $NF}'" % bondingConfFile
    (status, output) = subprocess.getstatusoutput(cmd)
    if (status != 0):
        pass

    for networkname in output.split('\n'):
        netNameList.append(networkname.strip())
    return netNameList


def SetLimitsConf(typeList, item, value, limitFile):
    for typeName in typeList:
        cmd = """sed -i '/^.* %s *%s .*$/d' %s &&
           echo "*       %s    %s  %s" >> %s""" % (typeName, item, limitFile, typeName, item, value, limitFile)
        (status, output) = subprocess.getstatusoutput(cmd)
        if (status != 0):
            return "Failed to set variable '%s %s'. Error: \n%s" % (typeName, item, output)
    return ""


def isRedHat7():
    gs_platform = Platform()
    dist_name, version, _ = gs_platform.dist()
    lower_dist_name = dist_name.lower()
    if (lower_dist_name in support_platform.RHEL_MASTER_PLATFORM_LIST and version[0] != support_platform.RHEL6) \
            or lower_dist_name in support_platform.RHEL_DERIVATION_PLATFORM_LIST:
        return True
    elif lower_dist_name in support_platform.OTHER_PLATFORM_LIST:
        return True
    else:
        return False


def isRedHat():
    gs_platform = Platform()
    osName = gs_platform.dist()[0]
    if osName.lower() in support_platform.RHEL_SERIES_VERSION_LIST + support_platform.OTHER_PLATFORM_LIST:
        return True
    else:
        return False


def getInitFile():
    if isRedHat():
        return INIT_FILE_REDHAT
    else:
        return INIT_FILE_SUSE


def getIpByHostName(host):
    ipList = g_file.readFile("/etc/hosts", host)
    pattern = re.compile(r'^.*%s[ \t]*#Gauss.* IP Hosts Mapping' % host)
    for ipInfo in ipList:
        match = pattern.match(ipInfo.strip())
        if (match):
            return match.group().split(' ')[0].strip()
    # get local host by os function
    rs = socket.getaddrinfo(host, None)
    # rs[0] means the firstly available protocol tuple
    # rs[0][4] gets the sockaddr(ip, xx,...) of first available protocol tuple.
    return rs[0][4][0]


def isBond(netWorkNum):
    bondingConfFile = "/proc/net/bonding/%s" % netWorkNum
    if (isRedHat7()):
        cmd = "%s %s | grep -E '\<ether\>' | awk  -F ' ' '{print $2}'" % (g_Platform.getIfconfigCmd(), netWorkNum)
    else:
        cmd = "%s %s | grep -E '\<HWaddr\>' | awk  -F ' ' '{print $NF}'" % (g_Platform.getIfconfigCmd(), netWorkNum)
    MacAddr = runShellCmd(cmd)
    cmd = "%s -a | grep '\<%s\>' | wc -l" % (g_Platform.getIfconfigCmd(), MacAddr)
    output = runShellCmd(cmd)
    MacAddrNum = int(output)
    if (MacAddrNum > 2 and os.path.exists(bondingConfFile)):
        return True
    else:
        return False


def getNetWorkConfFile(networkCardNum):
    SuSENetWorkConfPath = "/etc/sysconfig/network"
    RedHatNetWorkConfPath = "/etc/sysconfig/network-scripts"
    if (isRedHat()):
        NetWorkConfFile = "%s/ifcfg-%s" % (RedHatNetWorkConfPath, networkCardNum)
    else:
        NetWorkConfFile = "%s/ifcfg-%s" % (SuSENetWorkConfPath, networkCardNum)

    if (not os.path.exists(NetWorkConfFile)):
        if (isRedHat()):
            cmd = "find %s -iname 'ifcfg-*-%s' -print" % (RedHatNetWorkConfPath, networkCardNum)
        else:
            cmd = "find %s -iname 'ifcfg-*-%s' -print" % (SuSENetWorkConfPath, networkCardNum)
        output = runShellCmd(cmd)
        if (output.strip() == "" or len(output.split('\n')) != 1):
            raise Exception("The %s does not exist." % NetWorkConfFile)
        NetWorkConfFile = output.strip()
    return NetWorkConfFile


def getTeamCardInfo(networkNum):
    result = []
    cmd = "export PATH=/bin:/usr/local/bin:/usr/bin:/sbin:/usr/sbin:$PATH && teamdctl %s stat" % networkNum
    status, output = subprocess.getstatusoutput(cmd)
    if status == 0:
        for line in output.splitlines():
            if line.find(":") < 0:
                result.append(line.strip())
    else:
        result.append(output)
    return status, result


def CheckNetWorkBonding(serviceIP, networkCards):
    for network in networkCards:
        if g_network.isSameIP(network.ipAddress, serviceIP):
            networkCardNum = network.NICNum
            break
    vlan_conf_file = "/proc/net/vlan/%s" % networkCardNum
    if os.path.exists(vlan_conf_file):
        # its vlan if the vlan_conf_file exists.
        # get bond card number from vlan config file
        cmd = "grep 'Device' %s | awk -F ':' '{print $2}'" % vlan_conf_file
        (status, output) = subprocess.getstatusoutput(cmd)
        if status == 0 and output.strip() != "":
            networkCardNum = output.strip()
    NetWorkConfFile = getNetWorkConfFile(networkCardNum)
    bondingConfFile = "/proc/net/bonding/%s" % networkCardNum
    networkCardNumList = [networkCardNum]
    cmd = "grep -i 'BONDING_OPTS\|BONDING_MODULE_OPTS' %s" % NetWorkConfFile
    (status, output) = subprocess.getstatusoutput(cmd)
    if status == 0 and output.strip() != "":
        if output.find("mode") > 0 and os.path.exists(bondingConfFile):
            networkCardNumList = networkCardNumList + checkBondMode(bondingConfFile)
        else:
            raise Exception("Failed to obtain network card bonding information.")
    elif g_file.readFile(NetWorkConfFile, "DEVICETYPE=Team") or g_file.readFile(NetWorkConfFile, "TEAM_CONFIG"):
        status, teamInfo = getTeamCardInfo(networkCardNum)
        if status != 0 or not teamInfo:
            raise Exception("Failed to obtain team network card information.")
        networkCardNumList.extend(teamInfo)
    return networkCardNumList


###########################################################################
# getTHPandOSInitFile:
###########################################################################
def getTHPandOSInitFile():
    """
    function : We know that the centos have same init file and THP file as RedHat.
    input  : NA
    output : String, String
    """
    THPFile = "/sys/kernel/mm/transparent_hugepage/enabled"
    initFile = getOSInitFile()
    if (initFile == ""):
        raise Exception("startup file of current OS" + " The startup file for SUSE OS is /etc/init.d/boot.local.\
Thestartup file for Redhat OS is /etc/rc.d/rc.local.")
    return (THPFile, initFile)


def getOSInitFile():
    """
    function : Get the OS initialization file
    input : NA
    output : String
    """
    systemd_system_dir = "/usr/lib/systemd/system/"
    systemd_system_file = "/usr/lib/systemd/system/gs-OS-set.service"
    # system init file
    initSystemFile = "/usr/local/gauss/script/gauss-OS-set.sh"
    dirName = os.path.dirname(os.path.realpath(__file__))
    if (os.path.isdir(systemd_system_dir)):
        if (not os.path.exists(systemd_system_file)):
            cmd = "cp '%s'/gs-OS-set.service '%s'; chmod %s '%s'" \
                  % (dirName, systemd_system_file, 600, systemd_system_file)
            runShellCmd(cmd)
            cmd = "systemctl enable gs-OS-set.service"
            runShellCmd(cmd)
        if (not os.path.exists(initSystemFile)):
            cmd = "mkdir -p '%s'" % os.path.dirname(initSystemFile)
            runShellCmd(cmd)
            g_file.write_file_with_default_permission(initSystemFile, "#!/bin/bash\n", False)
        return initSystemFile
    initFile = g_Platform.get_os_init_file()
    return initFile


def getIPAndMaskList():
    """
    function:
        Get all IP in CIDR format('xxx.xxx.xx.xxx/xx' or 'xxxx::xxxx:xxxx/xx')
    input:
        None
    output:
        The CIDR formatted IP string list.
    """
    cmd = "ip addr | grep -e '\<inet[6]*\>*' | awk '{print $2}' "
    rl = []
    output = runShellCmd(cmd)
    for eachLine in output.split('\n'):
        rl.append(eachLine)
    return rl


def getIPAndMaskByIP(ip):
    """
    function:
        Get IP and it's mask in CIDR format.
    input:
        ip: IP in plain text.
    output:
        The CIDR formatted IP string.
    """
    ip = g_network.formatIP(ip)
    cmd = "ip addr | grep -e '\<inet[6]*\>*' | awk '{print $2}' | grep -e '\<%s\>'" % ip
    output = str(runShellCmd(cmd))
    return output.strip()


def checkDiskInde(path, thresholdDn):
    """
    function:
        check path of disk's inode weather if more than thresholdDn
    input:
        path: the absolute path of one folder
        thresholdDn: the threshold of disk inode used
    output:
        flag: the flag of success or failed
        result: the result of current check
    """
    result = ""
    flag = True
    diskName = g_disk.getMountPathByDataDir(path)
    diskType = g_disk.getDiskMountType(diskName)
    if diskType != "btrfs":
        if diskType not in ["xfs", "ext3", "ext4"]:
            result = "Path(%s) inodes usage(%s)     " \
                     "Warning reason: The file system type [%s] is unrecognized or not support. " \
                     "Please check it.\n" % (path, 0, diskType)
            flag = False
            return flag, result
        rateNum = round(g_disk.getDiskInodeUsage(path), 2)
        if rateNum > int(thresholdDn):
            result += "Path(%s) inode usage(%d%%)     " \
                      "Abnormal reason: The usage of the device disk inode cannot be greater than %s%%.\n" \
                      % (path, rateNum, thresholdDn)
            flag = False
    return flag, result
