#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#############################################################################
# Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
# Portions Copyright (c) 2007 Agendaless Consulting and Contributors.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
#          http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# Description  : KerberosUtility.py is a utility to handler kerberos things.
#############################################################################
import gc
import sys
import os
import getopt
import subprocess
import shutil
import pwd
from subprocess import PIPE

sys.path.append(sys.path[0] + "/../")
from gspylib.common.DbClusterInfo import dbClusterInfo
from gspylib.common.Common import DefaultValue
from gspylib.common.GaussLog import GaussLog
from gspylib.common.ErrorCode import ErrorCode
from gspylib.threads.SshTool import SshTool
from multiprocessing.dummy import Pool as ThreadPool
from domain_utils.cluster_file.cluster_config_file import ClusterConfigFile
from base_utils.os.cmd_util import CmdUtil
from domain_utils.cluster_file.cluster_dir import ClusterDir
from domain_utils.cluster_file.cluster_log import ClusterLog
from base_utils.os.env_util import EnvUtil
from base_utils.os.file_util import FileUtil
from base_utils.os.net_util import NetUtil
from base_utils.common.fast_popen import FastPopen
from domain_utils.domain_common.cluster_constants import ClusterConstants
from domain_utils.security.random_value import RandomValue

METHOD_TRUST = "trust"
g_ignorepgHbaMiss = True
g_clusterInfo = None
#write /etc/hosts kerberos flag
VALUE_LIST = ["PGKRBSRVNAME", "KRBHOSTNAME", "MPPDB_KRB5_FILE_PATH",
              "KRB5RCACHETYPE"]
SERVER_ENV_LIST = ["KRB_HOME", "KRB5_CONFIG", "KRB5_KDC_PROFILE"]

g_logger = None
g_opts = None
g_sshTool = None


class CmdOptions():
    """
    install the cluster on local node
    """
    def __init__(self):
        self.action = ""
        self.user = ""
        self.mpprcFile = ""
        self.clusterInfo = None
        self.principal = ""
        self.keytab = ""
        self.dbNodeInfo = None
        self.krbHomePath = ""
        self.krbConfigPath = ""
        self.server = False
        self.client = False
        self.gausshome = ""
        self.gausshome_kerberso = ""


def initGlobals():
    """
    init global variables
    input : NA
    output: NA
    """
    global g_opts
    logFile = ClusterLog.getOMLogPath(ClusterConstants.LOCAL_LOG_FILE,
                                        g_opts.user, "")

    # Init logger
    global g_logger
    g_logger = GaussLog(logFile, "KerberosUtility")

    global g_clusterInfo
    # init for clusterInfo
    g_clusterInfo = dbClusterInfo()
    g_clusterInfo.initFromStaticConfig(g_opts.user)
    g_logger.debug("Cluster information: \n%s." % str(g_clusterInfo))

    global g_sshTool
    nodenames = g_clusterInfo.getClusterNodeNames()
    g_sshTool = SshTool(nodenames)

    try:
        # init for __clusterInfo and __dbNodeInfo
        g_opts.clusterInfo = g_clusterInfo
        hostName = NetUtil.GetHostIpOrName()
        g_opts.dbNodeInfo = g_clusterInfo.getDbNodeByName(hostName)

        #get env variable file
        g_opts.mpprcFile = EnvUtil.getMpprcFile()

        # create kerberso directory under GAUSSHOME
        gausshome = ClusterDir.getInstallDir(g_opts.user)
        if not gausshome:
            raise Exception(ErrorCode.GAUSS_518["GAUSS_51802"] % "GAUSSHOME")
        g_opts.gausshome = gausshome
        g_opts.gausshome_kerberso = os.path.join(gausshome, "kerberos")
        if not os.path.isdir(g_opts.gausshome_kerberso):
            dir_permission = 0o700
            os.makedirs(g_opts.gausshome_kerberso, mode=dir_permission)

        if g_opts.action == "install" and g_opts.server:
            g_logger.debug("%s the kerberos server.", g_opts.action)

        else:
            if g_opts.action == "uninstall":
                g_logger.debug("%s the kerberos tool.", g_opts.action)
            else:
                g_logger.debug("%s the kerberos client.", g_opts.action)
            tablespace = EnvUtil.getEnv("ELK_SYSTEM_TABLESPACE")
            if tablespace is not None and tablespace != "":
                xmlfile = os.path.join(os.path.dirname(g_opts.mpprcFile),
                                       DefaultValue.FI_ELK_KRB_XML)
            else:
                xmlfile = os.path.join(os.path.dirname(g_opts.mpprcFile),
                                       DefaultValue.FI_KRB_XML)
            xmlfile = os.path.realpath(xmlfile)
            if not os.path.isfile(xmlfile):
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % xmlfile)

            rootNode = ClusterConfigFile.initParserXMLFile(xmlfile)
            elementArray = rootNode.findall("property")

            for element in elementArray:
                if (element.find('name').text == "mppdb.kerberos.principal"
                    or element.find('name').text == "elk.kerberos.principal"):
                    g_opts.principal = element.find('value').text
                if (element.find('name').text == "mppdb.kerberos.keytab"
                    or element.find('name').text == "elk.kerberos.keytab"):
                    g_opts.keytab = element.find('value').text
                if (element.find('name').text == 'KRB_HOME'):
                    g_opts.krbHomePath = element.find('value').text
                if (element.find('name').text == 'KRB_CONFIG'):
                    g_opts.krbConfigPath = element.find('value').text

            if(g_opts.principal == "" or g_opts.keytab == ""
                    or g_opts.krbHomePath == "" or g_opts.krbConfigPath == ""):
                raise Exception(ErrorCode.GAUSS_512["GAUSS_51200"] %
                                "mppdb.kerberos.principal or "
                                "mppdb.kerberos.keytab"
                                " or KRB_HOME or KRB_CONFIG"
                                + " The xml file is %s." % xmlfile)

    except Exception as e:
        g_logger.logExit(str(e))
    g_logger.debug("Instance information on local node:\n%s."
                   % str(g_opts.dbNodeInfo))


class Kerberos():
    def __init__(self):
        self.__dbNodeInfo = None
        self.__allIps = []
        self.__cooConfig = {}
        self.__dataConfig = {}
        self.__gtmConfig = {}
        self.__cmsConfig = {}
        self.__IpStringList = []
        self.__DNStringList = []

    def __rollback(self, isServer):
        g_logger.log("An error happened in executing the command, "
                     "begin rollback work...")
        if isServer:
            self.__rollbackServerInstall()
        else:
            self.__uninstall(True)
        g_logger.log("rollback work complete.")

    def __rollbackServerInstall(self):
        if os.path.isdir(g_opts.gausshome_kerberso):
            shutil.rmtree(g_opts.gausshome_kerberso)
        self.__clearEnvironmentVariableValue(True)
        self.__cleanAuthConfig()
        self.__cleanServer()


    def __triggerJob(self, isUninstall, isServer=False):
        '''
        function: triggerJob for call kinit
        '''
        if(not isUninstall):
            g_logger.log("start triggerJob.")
            if isServer:
                self.__initUser()
                self.__startServer()
                self.__distributeKeyAndSite()
                self.__setServiceCron()
            else:
                self.__executeJob()
            g_logger.log("successfully start triggerJob.")
        else:
            g_logger.log("stop triggerJob.")
            self.__cancelCron()
            g_logger.log("successfully stop triggerJob.")

    def __clearEnvironmentVariableValue(self, isServer=False):
        """
        function: clear kerberos EnvironmentVariable
        input: isServer
        output: NA
        """
        for value in VALUE_LIST:
            cmd = "sed -i -e '/^.*%s=/d' '%s'" % (value, g_opts.mpprcFile)
            (status, output) = subprocess.getstatusoutput(cmd)
            if status != 0:
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
                                + "Error:\n%s" % output)
        if isServer:
            for value in SERVER_ENV_LIST:
                cmd = "sed -i -e '/^.*%s=/d' '%s' && " \
                      "sed -i -e '/^.*PATH=\$%s/d' '%s' && " \
                      "sed -i -e '/^.*LD_LIBRARY_PATH=\$%s/d' '%s'" % \
                      (value, g_opts.mpprcFile, value, g_opts.mpprcFile,
                       value, g_opts.mpprcFile)
                (status, output) = subprocess.getstatusoutput(cmd)
                if(status != 0):
                    raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
                                    + "Error:\n%s" % output)

        g_logger.log("successfully clear kerberos env Variables.")

    def __setUserEnvVariable(self, isUninstall, isServer=False,
                             isRollBack=False):
        '''
        function: set user env Variable
        '''
        g_logger.log("start set user env Variable.")
        if(not isUninstall):
            try:
                if isServer:
                    self.__clearEnvironmentVariableValue(True)

                    # SET variable KRB_HOME
                    cmd = "echo \"export KRB_HOME=%s\" >> %s" % \
                          (g_opts.gausshome, g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
                                        "KRB_HOME" + output
                                        + "\nThe cmd is %s " % cmd)
                    g_logger.log("Config environment variable KRB_HOME "
                                 "successfully.")

                    # SET variable KRB5_CONFIG
                    cmd = "echo \"export KRB5_CONFIG=%s/krb5.conf\" >> %s" % \
                          (g_opts.gausshome_kerberso, g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
                                        "KRB5_CONFIG" + output
                                        + "\nThe cmd is %s " % cmd)
                    g_logger.log("Config environment variable KRB5_CONFIG "
                                 "successfully.")

                    # SET variable KRB5_KDC_PROFILE
                    cmd = "echo \"export KRB5_KDC_PROFILE=%s/kdc.conf\" " \
                          ">> %s" \
                          % (g_opts.gausshome_kerberso, g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
                                        "KRB5_KDC_PROFILE" + output
                                        + "\nThe cmd is %s " % cmd)
                    g_logger.log("Config environment "
                                 "variable KRB5_KDC_PROFILE successfully.")

                    # SET variable PATH
                    cmd = "echo \"export PATH=\$KRB_HOME/bin:\$PATH\" " \
                          ">> %s" % (g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
                                        "PATH" + output
                                        + "\nThe cmd is %s " % cmd)
                    g_logger.log("Config environment variable PATH "
                                 "successfully.")

                    # SET variable LD_LIBRARY_PATH
                    cmd = "echo \"export LD_LIBRARY_PATH=\$KRB_HOME/lib:" \
                          "\$LD_LIBRARY_PATH\" >> %s" % (g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
                                        "LD_LIBRARY_PATH" + output
                                        + "\nThe cmd is %s " % cmd)
                    g_logger.log("Config environment variable LD_LIBRARY_PATH "
                                 "successfully.")

                else:
                    # get principal
                    principals = g_opts.principal.split("/")
                    if (len(g_opts.principal.split('/')) < 2):
                        raise Exception(ErrorCode.GAUSS_500["GAUSS_50009"]
                                        + "principal: %s" % g_opts.principal)
                    address = g_opts.principal.split('/')[1].split('@')[0]

                    self.__clearEnvironmentVariableValue()
                    # SET variable KRB5_CONFIG
                    cmd = "echo \"export MPPDB_KRB5_FILE_PATH=%s/krb5.conf\"" \
                          " >> %s" % (os.path.dirname(g_opts.mpprcFile),
                                     g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
                                        % cmd + "Error:\n%s." % output)
                    g_logger.log("Config environment variable KRB5_CONFIG "
                                 "successfully.")
                    # SET variable PGKRBSRVNAME

                    cmd = "echo \"export PGKRBSRVNAME=%s\" >>%s" % \
                          (principals[0], g_opts.mpprcFile)

                    (status, output) = subprocess.getstatusoutput(cmd)
                    if (status != 0):
                        raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
                                        % cmd + "Error:\n%s." % output)
                    g_logger.log("Config environment variable PGKRBSRVNAME "
                                 "successfully.")
                    # SET variable KRBHOSTNAME

                    cmd = "echo \"export KRBHOSTNAME=%s\" >>%s" % \
                          (address, g_opts.mpprcFile)

                    (status, output) = subprocess.getstatusoutput(cmd)
                    if status != 0:
                        raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
                                        % cmd + "Error:\n%s." % output)
                    g_logger.log("Config environment variable KRBHOSTNAME "
                                 "successfully.")
                    # SET variable KRB5RCACHETYPE
                    cmd = "echo \"export KRB5RCACHETYPE=none\" >>%s" % \
                          (g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if status != 0:
                        raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
                                        % cmd + "Error:\n%s." % output)
                        
                    # SET KRB5_CONFIG
                    cmd = "echo \"export KRB5_CONFIG=%s/krb5.conf\"" \
                          " >> %s" % (os.path.dirname(g_opts.mpprcFile),
                                     g_opts.mpprcFile)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if status != 0:
                        raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
                                        cmd + "Error:\n%s." % output)
                    g_logger.log("Config environment variable KRB5RCACHETYPE "
                                 "successfully.")
            except Exception as e:
                raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"]
                                % "" + "Error:%s." % str(e))
        else:
            if isRollBack:
                self.__clearEnvironmentVariableValue(False)
            else:
                self.__clearEnvironmentVariableValue(True)

    def __configPostgresql(self, isUninstall):
        '''
        function: set config postgresql file
        '''
        g_logger.log("start set config postgresql file")

        instanceList = []
        if(not isUninstall):
            self.__cooConfig["krb_server_keyfile"] = "'" + g_opts.keytab + "'"
            self.__dataConfig["krb_server_keyfile"] = "'" + g_opts.keytab + "'"
            self.__gtmConfig["gtm_authentication_type"] = "gss"
            self.__gtmConfig["gtm_krb_server_keyfile"] = "'" + g_opts.keytab \
                                                         + "'"
            self.__cmsConfig["cm_auth_method"] = "gss"
            self.__cmsConfig["cm_krb_server_keyfile"] = "'" + g_opts.keytab + \
                                                        "'"
        else:
            self.__cooConfig["krb_server_keyfile"] = ""
            self.__dataConfig["krb_server_keyfile"] = ""
            self.__gtmConfig["gtm_authentication_type"] = "trust"
            self.__gtmConfig["gtm_krb_server_keyfile"] = "''"
            self.__cmsConfig["cm_auth_method"] = "trust"
            self.__cmsConfig["cm_krb_server_keyfile"] = "''"

        # get coordinators instance
        for cooInst in g_opts.dbNodeInfo.coordinators:
            instanceList.append(cooInst)
        # get datanode instance
        for dnInst in g_opts.dbNodeInfo.datanodes:
            instanceList.append(dnInst)
        # get gtm instance
        for gtmInst in g_opts.dbNodeInfo.gtms:
            instanceList.append(gtmInst)
        # get cms instance
        for cmsInst in g_opts.dbNodeInfo.cmservers:
            instanceList.append(cmsInst)

        if(len(instanceList) == 0):
            return
        try:
            #config instance in paralle
            pool = ThreadPool(DefaultValue.getCpuSet())
            pool.map(self.__configInst, instanceList)
            pool.close()
            pool.join()
        except Exception as e:
            raise Exception(str(e))
        g_logger.log("successfully set config postgresql file")

    def __configPgHba(self, isUninstall):
        '''
        set pg_hba.conf file
        '''
        g_logger.log("start config pg_hba file")
        try:
            # get current node information
            hostName = NetUtil.GetHostIpOrName()
            self.__dbNodeInfo = g_clusterInfo.getDbNodeByName(hostName)
            if (self.__dbNodeInfo is None):
                raise Exception(ErrorCode.GAUSS_516["GAUSS_51620"] % "local"
                                + " There is no host named %s." % hostName)
            #getall node names
            nodenames = g_clusterInfo.getClusterNodeNames()
            for nodename in nodenames:
                nodeinfo = g_clusterInfo.getDbNodeByName(nodename)
                self.__allIps += nodeinfo.backIps
                self.__allIps += nodeinfo.sshIps
                for inst in nodeinfo.cmservers:
                    self.__allIps += inst.haIps
                    self.__allIps += inst.listenIps
                for inst in nodeinfo.coordinators:
                    self.__allIps += inst.haIps
                    self.__allIps += inst.listenIps
                for inst in nodeinfo.datanodes:
                    self.__allIps += inst.haIps
                    self.__allIps += inst.listenIps
                for inst in nodeinfo.gtms:
                    self.__allIps += inst.haIps
                    self.__allIps += inst.listenIps
            # set local ip 127.0.0.1
            self.__allIps += ['127.0.0.1', '::1']
            # get all ips. Remove the duplicates ips
            self.__allIps = DefaultValue.Deduplication(self.__allIps)
            # build ip string list
            # set Kerberos ip
            principals = g_opts.principal.split("/")
            principals = principals[1].split("@")
            # Every 1000 records merged into one"
            ipstring = ""
            for ip in self.__allIps:
                submask_length = NetUtil.get_submask_len(ip)
                if not isUninstall:
                    ipstring += " -h 'host    all             all       " \
                                "      %s/%s        gss         " \
                                "include_realm=1        krb_realm=%s'" % \
                                (ip, submask_length, principals[1])
                else:
                    ipstring += " -h 'host    all             all       " \
                                "      %s/%s       %s'" % (ip, submask_length, METHOD_TRUST)
            if ipstring != "":
                self.__IpStringList.append(ipstring)
            # write config hba
            self.__writeConfigHba()
        except Exception as e:
            raise Exception(ErrorCode.GAUSS_530["GAUSS_53024"]
                            + "Error:%s." % str(e))

        g_logger.debug("Instance information about local node:\n%s." %
                       str(self.__dbNodeInfo))
        g_logger.log("successfully config pg_hba file")

    def __configDNPgHba(self, isUninstall):
        '''
        set DN pg_hba.conf file for replication channel
        '''
        g_logger.log("start config pg_hba file for database node replication "
                     "channel")
        try:
            principals = g_opts.principal.split("/")
            principals = principals[1].split("@")
            ipstring = ""
            if (not isUninstall):
                ipstring += " -h 'host    replication             %s        " \
                            "     ::1/128        gss         include_realm=1" \
                            "        krb_realm=%s'" % \
                            (g_opts.user, principals[1])
            else:
                ipstring += " -h 'host    replication             %s        " \
                            "     ::1/128        %s'" % \
                            (g_opts.user, METHOD_TRUST)
            if (ipstring != ""):
                self.__DNStringList.append(ipstring)
            self.__writeDNConfigHba()
        except Exception as e:
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"]
                            % ("database node config for pg_hba.conf. %s"
                               % str(e)))
        g_logger.log("successfully config pg_hba file for database node "
                     "replication channel")

    def __configInst(self, dbInst):
        """
        function: Modify a parameter of postgresql.conf
        input : typename, datadir, configFile, parmeterDict
        output: NA
        """
        configFile = os.path.join(dbInst.datadir, "postgresql.conf")
        if (dbInst.instanceRole != DefaultValue.INSTANCE_ROLE_GTM and
            dbInst.instanceRole != DefaultValue.INSTANCE_ROLE_CMSERVER and
            not os.path.isfile(configFile)):
            return
        if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_COODINATOR:
            # modifying CN configuration.
            g_logger.log("Modify CN %s configuration." % dbInst.instanceId)
            configFile = os.path.join(dbInst.datadir, "postgresql.conf")
            # Set default value for each inst
            tempCommonDict =  self.__cooConfig
            self.__setConfigItem(DefaultValue.INSTANCE_ROLE_COODINATOR,
                                 dbInst.datadir, tempCommonDict)

        if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_DATANODE:
            # modifying database node configuration.
            g_logger.log("Modify database node %s configuration."
                         % dbInst.instanceId)
            # Set default value for each inst
            tempCommonDict = self.__dataConfig
            try:
                self.__setConfigItem(DefaultValue.INSTANCE_ROLE_DATANODE,
                                     dbInst.datadir, tempCommonDict)
            except Exception as e:
                raise Exception(str(e))

        if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_GTM:
            # modifying GTM configuration.
            g_logger.log("Modify GTM %s configuration." % dbInst.instanceId)
            # Set default value for each inst
            tempCommonDict = self.__gtmConfig
            try:
                self.__setConfigItem(DefaultValue.INSTANCE_ROLE_GTM,
                                     dbInst.datadir, tempCommonDict)
            except Exception as e:
                raise Exception(str(e))

        if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_CMSERVER:
            # modifying CMSERVER configuration.
            g_logger.log("Modify CMserver %s configuration."
                         % dbInst.instanceId)
            # Set default value for each inst
            tempCommonDict = self.__cmsConfig
            try:
                self.__setConfigItem(DefaultValue.INSTANCE_ROLE_CMSERVER,
                                     dbInst.datadir, tempCommonDict)
            except Exception as e:
                raise Exception(str(e))

    def __setConfigItem(self, typename, datadir, parmeterDict):
        """
        function: Modify a parameter
        input : typename, datadir, parmeterDict
        output: NA
        """
        # build GUC parameter string
        gucstr = ""
        for entry in list(parmeterDict.items()):
            if entry[1] == "":
                gucstr += " -c \"%s=\'\'\"" % (entry[0])
            else:
                gucstr += " -c \"%s=%s\"" % (entry[0], entry[1])
        # check the GUC parameter string
        if gucstr == "":
            return
        inst_type_map = {DefaultValue.INSTANCE_ROLE_DATANODE:"datanode",
                         DefaultValue.INSTANCE_ROLE_COODINATOR:"coordinator",
                         DefaultValue.INSTANCE_ROLE_CMSERVER:"cmserver"}
        inst_type = " -Z %s"%inst_type_map.get(typename) if inst_type_map.get(typename) else ""
        if typename == DefaultValue.INSTANCE_ROLE_DATANODE or \
                typename == DefaultValue.INSTANCE_ROLE_COODINATOR:
            cmd = "source '%s'; gs_guc set -D %s %s" % \
                  (g_opts.mpprcFile, datadir, gucstr)
            DefaultValue.retry_gs_guc(cmd)
            if self.__gsdbStatus():
                cmd = "source '%s'; gs_guc reload -D %s %s" % \
                      (g_opts.mpprcFile, datadir, gucstr)
                try:
                    DefaultValue.retry_gs_guc(cmd)
                except Exception as e:
                    raise Exception(str(e))
        else:
            cmd = "source '%s'; gs_guc set %s -N all -I all %s" % \
                  (g_opts.mpprcFile, inst_type, gucstr)
            DefaultValue.retry_gs_guc(cmd)

    def __gsdbStatus(self):
        """
        function: get gaussdb process
        input: NA
        output: True/False
        """
        cmd = "ps ux | grep -v '\<grep\>' | grep '%s/bin/gaussdb'" % \
              g_clusterInfo.appPath
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0 and output:
            raise Exception("Get gaussdb process failed." +
                            "The cmd is %s " % cmd)
        if output:
            return True
        return False

    def __writeConfigHba(self):
        """
        function: set hba config
        input : NA
        output: NA
        """
        instances = self.__dbNodeInfo.datanodes + \
                    self.__dbNodeInfo.coordinators
        #Determine whether this node containing CN, DN instance
        if(len(instances) == 0):
            g_logger.debug("The count number of coordinator and "
                           "datanode on local node is zero.")
            return
        try:
            pool = ThreadPool(DefaultValue.getCpuSet())
            pool.map(self.__configAnInstance, instances)
            pool.close()
            pool.join()
        except Exception as e:
            raise Exception(str(e))

    def __writeDNConfigHba(self):
        """
        function: set hba config for dn replication channel
        input : NA
        output: NA
        """
        instances = self.__dbNodeInfo.datanodes
        if (len(instances) == 0):
            g_logger.debug("The count number of datanode "
                           "on local node is zero.")
            return
        try:
            pool = ThreadPool(DefaultValue.getCpuSet())
            pool.map(self.__configAnInstanceHA, instances)
            pool.close()
            pool.join()
        except Exception as e:
            raise Exception(str(e))

    def __configAnInstance(self, instance):
        # check instance data directory
        if (instance.datadir == "" or not os.path.isdir(instance.datadir)):
            if(g_ignorepgHbaMiss):
                g_logger.debug("Failed to obtain data directory of "
                               "the instance[%s]." % str(instance))
                return
            else:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
                                ("data directory of the instance[%s]" %
                                 str(instance)))
        # check pg_hba.conf
        hbaFile = "%s/pg_hba.conf" % instance.datadir
        if(g_ignorepgHbaMiss and not os.path.isfile(hbaFile)):
            g_logger.debug("The %s does not exist." % hbaFile)
            return
        # do gs_guc to add host into pg_hba.conf
        self.__addHostToFile(instance.datadir)

    def __configAnInstanceHA(self, instance):
        instanceRole = "datanode"
        # check instance data directory
        if (instance.datadir == "" or not os.path.isdir(instance.datadir)):
            if(g_ignorepgHbaMiss):
                g_logger.debug("Failed to obtain data directory "
                               "of the instance[%s]." % str(instance))
                return
            else:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
                                ("data directory of the instance[%s]"
                                 % str(instance)))
        # check pg_hba.conf
        hbaFile = "%s/pg_hba.conf" % instance.datadir
        if(g_ignorepgHbaMiss and not os.path.isfile(hbaFile)):
            g_logger.debug("The %s does not exist." % hbaFile)
            return
        # do gs_guc to add host into pg_hba.conf
        self.__addDNhostToFile(instanceRole, instance.datadir)

    def __addHostToFile(self, instanceDataPath):
        # do gs_guc to add host into pg_hba.conf
        for IpString in self.__IpStringList:
            cmd = "source '%s';gs_guc set -D %s %s" % (g_opts.mpprcFile,
                                                       instanceDataPath,
                                                       IpString)
            DefaultValue.retry_gs_guc(cmd)

    def __addDNhostToFile(self, dbInstanceRole, instanceDataPath):
        """
        function: set DN config postgresql file for replication channel
        input:dbInstanceRole, instanceDataPath
        output:NA
        """
        if (dbInstanceRole == "datanode"):
            for IpDNString in self.__DNStringList:
                cmd = "source '%s';gs_guc set -D %s %s" % \
                      (g_opts.mpprcFile, instanceDataPath, IpDNString)
                DefaultValue.retry_gs_guc(cmd)

    def __executeJob(self):
        """
        function:call TGT from kinit's tool
        input:NA
        output:NA
        """
        try:
            kinitPath = "%s/bin/kinit" % g_opts.krbHomePath
            kcmd = 'export LD_LIBRARY_PATH=%s/lib:$LD_LIBRARY_PATH;' \
                   'export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH;%s -k -t %s %s' \
                   % (g_opts.krbHomePath, kinitPath,
                      g_opts.keytab, g_opts.principal)
            cmd = 'source %s; %s' % (g_opts.mpprcFile, kcmd)
            (status, output) = CmdUtil.retryGetstatusoutput(cmd)
            if(status != 0):
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
                                + " Output: \n%s" % str(output))
            g_logger.debug("Get ticket successfully.")
            #set cron
            self.__setCron()
        except Exception as e:
            raise Exception("Call TGT from kinit's tool: %s." % cmd +
                            " Exception: \n%s" % str(e))

    def __setCron(self):
        """
        function: Set linux cron
        input : NA
        output: NA
        """
        g_logger.log("Set CRON.")
        cronFile = "%s/gauss_cron_%d" % \
                   (EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
        setCronCmd = "crontab -l > %s && " % cronFile
        setCronCmd += "sed -i '/^.*kinit.*$/d' '%s'; " % cronFile
        setCronCmd += '''echo '*/1 * * * * source '%s';''' \
                      '''export LD_LIBRARY_PATH='%s'/lib:$LD_LIBRARY_PATH;''' \
                      '''export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH ''' % \
                      (g_opts.mpprcFile, g_opts.krbHomePath)
        setCronCmd += '''klistcmd="'%s'/bin/klist";''' % (g_opts.krbHomePath)
        setCronCmd += '''kinitcmd="'%s'/bin/kinit -k -t %s %s ";''' % \
                      (g_opts.krbHomePath, g_opts.keytab, g_opts.principal)
        setCronCmd += '''klistresult=`$klistcmd>>/dev/null 2>&1;echo $?`;'''
        setCronCmd += '''if [ $klistresult -ne 0 ];then `$kinitcmd`;else ''' \
                      '''expiresTime=`$klistcmd|grep krbtgt|awk -F "  " ''' \
                      '''"{print \\\\\\$2}"`;startTime=`$klistcmd|grep ''' \
                      '''krbtgt|awk -F "  " "{print \\\\\\$1}"`;''' \
                      '''currentTime=`date +\%%s`;currentTime=''' \
                      '''`date +\%%s`;if [ $[`date -d "$expiresTime"''' \
                      ''' +\%%s`-$currentTime] -le 300 ] || [ $[`date -d''' \
                      ''' "$startTime" +\%%s`-$currentTime] -ge 0 ];''' \
                      '''then `$kinitcmd`;fi;fi;>>/dev/null 2>&1''' \
                      '''& ' >> %s ;''' % (cronFile)
        setCronCmd += "crontab %s&&" % cronFile
        setCronCmd += "rm -f '%s'" % cronFile

        g_logger.debug("Command for setting CRON: %s" % setCronCmd)
        (status, output) = subprocess.getstatusoutput(setCronCmd)
        if(status != 0):
            raise Exception(ErrorCode.GAUSS_508["GAUSS_50801"]
                            + " Error: \n%s." % str(output)
                            + "The cmd is %s " % setCronCmd)

        cmd = "source %s;export LD_LIBRARY_PATH=%s/lib:$LD_LIBRARY_PATH;" \
              "export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH;" % \
              (g_opts.mpprcFile, g_opts.krbHomePath)
        cmd += "klistcmd='%s/bin/klist';" % (g_opts.krbHomePath)
        cmd += "kinitcmd='%s/bin/kinit -k -t %s %s';" % \
               (g_opts.krbHomePath, g_opts.keytab, g_opts.principal)
        cmd += "klistresult=`$klistcmd>>/dev/null 2>&1;echo $?`;"
        cmd += "if [ $klistresult -ne 0 ];then `$kinitcmd`;" \
               "else expiresTime=`$klistcmd|grep krbtgt|" \
               "awk -F '  ' '{print \$2}'`;" \
               "startTime=`$klistcmd|grep krbtgt|awk -F '  ' '{print \$1}'`;" \
               "currentTime=`date +\%s`;currentTime=`date +\%s`;" \
               "if [ $[`date -d $expiresTime +\%s`-$currentTime] -le 300 ] " \
               "|| [ $[`date -d $startTime +\%s`-$currentTime] -ge 0 ];" \
               "then `$kinitcmd`;fi;fi;>>/dev/null 2>&1"
        (status, output) = subprocess.getstatusoutput(cmd)
        if(status != 0):
            raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd  +
                            "Error:\n%s" % str(output))

        g_logger.log("Successfully Set CRON.")


    def __setServiceCron(self):
        g_logger.log("Set CRON.")
        cronFile = "%s/gauss_cron_%d" % \
                   (EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
        setCronCmd = "crontab -l > %s && " % cronFile
        setCronCmd += "sed -i '/^.*krb5kdc.*$/d' '%s'; " % cronFile
        setCronCmd += '''echo "*/1 * * * * source %s; ''' \
                      '''kdc_pid_list=\`ps ux | grep -E krb5kdc| ''' \
                      '''grep -v grep | awk '{print \\\\\\$2}'\` && ''' \
                      '''(if [ X\"\$kdc_pid_list\" == X\"\" ]; ''' \
                      '''then krb5kdc; fi) " >> %s; ''' % \
                      (g_opts.mpprcFile, cronFile)
        setCronCmd += "crontab %s && " % cronFile
        setCronCmd += "rm -f '%s'" % cronFile

        g_logger.debug("Command for setting CRON: %s" % setCronCmd)
        (status, output) = subprocess.getstatusoutput(setCronCmd)
        if(status != 0):
            raise Exception(ErrorCode.GAUSS_508["GAUSS_50801"]
                            + " Error: \n%s." % str(output)
                            + "The cmd is %s " % setCronCmd)

        g_logger.log("Successfully Set CRON.")

    def __cancelCron(self):
        """
        function: clean kerberos_monitor process and delete cron
        input : NA
        output: NA
        """
        g_logger.log("Deleting kerberos monitor.")
        try:
            # Remove cron
            crontabFile = "%s/gauss_crontab_file_%d" % \
                          (EnvUtil.getTmpDirFromEnv(g_opts.user),
                           os.getpid())
            cmd = "crontab -l > %s; " % crontabFile
            cmd += "sed -i '/^.*kinit.*$/d' '%s'; " % crontabFile
            cmd += "crontab '%s';" % crontabFile
            cmd += "rm -f '%s'" % crontabFile

            (status, output) = subprocess.getstatusoutput(cmd)
            if (status != 0):
                #no need raise error here, user can do it manually.
                g_logger.debug("Failed to delete regular tasks. Error: \n%s"
                               "  You can do it manually." % str(output))
                g_logger.debug("The cmd is %s " % cmd)
            cmd = "source '%s';export LD_LIBRARY_PATH=%s/lib:" \
                  "$LD_LIBRARY_PATH;export KRB5_CONFIG=" \
                  "$MPPDB_KRB5_FILE_PATH;%s/bin/kdestroy" % \
                  (g_opts.mpprcFile, g_opts.krbHomePath, g_opts.krbHomePath)
            (status, output) = CmdUtil.retryGetstatusoutput(cmd)
            if (status != 0):
                g_logger.debug("Failed to delete ticket. Error: \n%s" %
                               str(output))
                g_logger.debug("The cmd is %s " % cmd)
        except Exception as e:
            raise Exception(str(e))
        g_logger.log("Successfully deleted kerberos OMMonitor.")

    def __copyConf(self, src_dir, dest_dir, file_list):
        for config_file in file_list:
            src_path = os.path.realpath(os.path.join(src_dir, config_file))
            if (not os.path.isfile(src_path)):
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % src_path)
            dest_path = os.path.realpath(os.path.join(dest_dir, config_file))
            try:
                shutil.copy(src_path, dest_path)
            except Exception as e:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50214"] % src_path)
        g_logger.log("Copy server config files successfully.")

    def __initKadm5Conf(self, dest_dir):
        kadm5_file = os.path.realpath(os.path.join(dest_dir, "kadm5.acl"))
        cmd = "sed -i 's/#realms#/OPENGAUSS.ORG/g' %s" % kadm5_file
        (status, output) = subprocess.getstatusoutput(cmd)
        if (status != 0):
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % kadm5_file
                            + output)
        g_logger.log("Initialize \"kadm5.acl\" successfully.")

    def __initKrb5Conf(self, dest_dir, dest_file='krb5.conf'):
        krb5_file = os.path.realpath(os.path.join(dest_dir, dest_file))
        kdc_ip = g_opts.dbNodeInfo.backIps[0]
        kdc_port = 21732
        gausslog = EnvUtil.getEnvironmentParameterValue("GAUSSLOG", "")
        if not gausslog:
            raise Exception(ErrorCode.GAUSS_518["GAUSS_51802"] % "GAUSSLOG")
        cmd = "sed -i 's/#kdc_ip#/%s/g' %s && \
               sed -i 's/#kdc_ports#/%d/g' %s && \
               sed -i 's;#krb_conf#;%s;g' %s && \
               sed -i 's;#GAUSSHOME#;%s;g' %s" % \
               (kdc_ip, krb5_file,
                kdc_port, krb5_file,
                g_opts.gausshome_kerberso, krb5_file,
                gausslog, krb5_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % krb5_file
                            + output)

        kerberoslog = os.path.join(gausslog, "kerberos")
        cmd = "if [ ! -d '%s' ]; then mkdir -p '%s' -m %s; fi" % (kerberoslog,
            kerberoslog, DefaultValue.KEY_DIRECTORY_MODE)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % krb5_file
                            + output)

        g_logger.log("Initialize \"krb5.conf\" successfully.")

    def __initKdcConf(self, dest_dir):
        self.__initKrb5Conf(dest_dir, "kdc.conf")

        kdc_file = os.path.realpath(os.path.join(dest_dir, "kdc.conf"))
        cmd = "sed -i 's;#KRB_HOME#;%s;g' %s" % (g_opts.gausshome, kdc_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % kdc_file
                            + output)

        g_logger.log("Initialize \"kdc.conf\" successfully.")

    def __initMppdbSite(self, dest_dir):
        mppdb_site_file = os.path.realpath(os.path.join(dest_dir,
                                                        "mppdb-site.xml"))
        principal = "%s/opengauss.org@OPENGAUSS.ORG " % g_opts.user
        cmd = "sed -i 's;#mppdb.kerberos.principal#;%s;g' %s" % \
              (principal, mppdb_site_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
                            mppdb_site_file + output)

        cmd = "sed -i 's;#KRB_HOME#;%s;g' %s" % (g_opts.gausshome,
                                                 mppdb_site_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
                            mppdb_site_file + output)

        kdc_conf = os.path.realpath(os.path.join(g_opts.gausshome_kerberso,
                                                 "kdc.conf"))
        cmd = "sed -i 's;#KRB_CONFIG#;%s;g' %s" % (kdc_conf, mppdb_site_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
                            mppdb_site_file + output)

        keytab = os.path.realpath(os.path.join(g_opts.gausshome_kerberso,
                                               "%s.keytab" % g_opts.user))
        cmd = "sed -i 's;#mppdb.kerberos.keytab#;%s;g' %s" % (keytab,
                                                              mppdb_site_file)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
                            mppdb_site_file + output)

        g_logger.log("Initialize \"mppdb-site.xml\" successfully.")

    def __configKrb5(self, isUninstall, isServer=False):
        """
        function: config specify krb5.conf
        input:  isUninstall, isServer
        output: NA
        """
        destfile = "%s/krb5.conf" % os.path.dirname(g_opts.mpprcFile)
        if not isUninstall:
            if isServer:
                # 1.copy conf files to GAUSSHOME/kerberos
                CONFIG_LIST = ["kadm5.acl", "kdc.conf", "krb5.conf"]
                src_path = os.path.realpath(os.path.join(g_opts.gausshome,
                                                         "etc", "kerberos"))
                self.__copyConf(src_path, g_opts.gausshome_kerberso,
                                CONFIG_LIST)
                # 2.initialize conf files
                self.__initKadm5Conf(g_opts.gausshome_kerberso)
                self.__initKrb5Conf(g_opts.gausshome_kerberso)
                self.__initKdcConf(g_opts.gausshome_kerberso)

            else:
                #1. copy "krb5.conf"
                if (os.path.isfile(g_opts.krbConfigPath)):
                    shutil.copy(g_opts.krbConfigPath, destfile)
                else:
                    raise Exception(ErrorCode.GAUSS_502["GAUSS_50228"] %
                                    g_opts.krbConfigPath)
                #2. change cache file path of kerberos
                if(not os.path.isdir("%s/auth_config" %
                                     os.path.dirname(g_opts.mpprcFile))):
                    raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] %
                                    ("%s/auth_config" %
                                     os.path.dirname(g_opts.mpprcFile)))
                cmd = "sed -i '/default_realm.*/i default_ccache_name = " \
                      "FILE:%s/auth_config/krb5cc_%s' '%s'" % \
                      (os.path.dirname(g_opts.mpprcFile),
                       pwd.getpwnam(g_opts.user).pw_uid, destfile)
                (status, output) = subprocess.getstatusoutput(cmd)
                if status != 0:
                    g_logger.debug("The cmd is %s " % cmd)
                    raise Exception("Config 'krb5.conf' failed.cmd: %s" % cmd)
                g_logger.log("Client Config \"krb5.conf\" successfully.")

        else:
            if os.path.isfile(destfile):
                os.remove(destfile)

            g_logger.log("Clear \"krb5.conf\" successfully.")

    def __initUser(self):

        # create kerberos database
        kerberos_database_file = \
            os.path.realpath(os.path.join(g_opts.gausshome,
                                          "var", "krb5kdc", "principal"))
        if os.path.isfile(kerberos_database_file):
            g_logger.debug("kerberos database has existed.")
        else:
            dir_permission = 0o700
            os.makedirs(os.path.dirname(kerberos_database_file),
                        mode=dir_permission)
            passwd = RandomValue.getRandStr()
            cmd = "source %s && echo -e '%s\n%s\n%s' | kdb5_util create -r OPENGAUSS.ORG -s -m" % \
                  (g_opts.mpprcFile, str(passwd), str(passwd), str(passwd))
            proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
            stdout, stderr = proc.communicate()
            output = stdout + stderr
            status = proc.returncode
            # clean pwd info
            del passwd, cmd
            gc.collect()
            if status != 0:
                g_logger.debug("The cmd is kdb5_util")
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
                                "kdb5_util")
            g_logger.debug("Create kerberos database successfully.")

        # create kerberos database user
        cmd = "source %s && kadmin.local -q \"addprinc  " \
              "-randkey %s/opengauss.org\"" % \
              (g_opts.mpprcFile, g_opts.user)
        proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
        stdout, stderr = proc.communicate()
        output = stdout + stderr
        status = proc.returncode
        if status != 0:
            raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
        g_logger.debug("Create kerberos database user successfully.")

        # create kerberos keytab
        cmd = "source %s && kadmin.local -q \"ktadd -k %s/%s.keytab " \
              "%s/opengauss.org@OPENGAUSS.ORG\"" % \
                (g_opts.mpprcFile, g_opts.gausshome_kerberso,
                 g_opts.user, g_opts.user)
        proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
        stdout, stderr = proc.communicate()
        output = stdout + stderr
        status = proc.returncode
        if status != 0:
            raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
        g_logger.debug("Create kerberos keytab successfully.")

        g_logger.log("Initialize kerberos user successfully.")

    def __startServer(self):
        # start kdc
        cmd = "source %s && krb5kdc" % g_opts.mpprcFile
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
        g_logger.debug("Start kerberos kdc successfully.")

        g_logger.log("Start kerberos server successfully.")

    def __distributeKeyAndSite(self):
        hostlist = []
        for hostName in g_sshTool.hostNames:
            if hostName != g_opts.dbNodeInfo.name:
                hostlist.append(hostName)
        g_logger.debug("Distribute nodes: %s" % ",".join(hostlist))
        # distribute keytab
        dest_kerberos_dir = os.path.dirname(g_opts.gausshome_kerberso) + '/'
        g_sshTool.scpFiles(g_opts.gausshome_kerberso,
                           dest_kerberos_dir, hostlist)

        # create auth_config
        mppdb_site_dir = os.path.join(os.path.dirname(g_opts.mpprcFile),
                                      "auth_config")
        cmd = "if [ ! -d '%s' ]; then mkdir %s; fi" % (mppdb_site_dir,
                                                       mppdb_site_dir)
        g_sshTool.executeCommand(cmd, DefaultValue.SUCCESS, g_sshTool.hostNames,
                                 g_opts.mpprcFile)
        # copy mppdb-site.xml
        src_path = os.path.realpath(os.path.join(g_opts.gausshome, "etc",
                                                 "kerberos", "mppdb-site.xml"))
        if not os.path.isfile(src_path):
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % src_path)
        dest_path = os.path.realpath(os.path.join(mppdb_site_dir,
                                                  "mppdb-site.xml"))
        try:
            shutil.copy(src_path, dest_path)
        except Exception as e:
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50214"] % src_path)
        # init mppdb-site.xml
        self.__initMppdbSite(mppdb_site_dir)
        # distribute mppdb-site.xml
        g_sshTool.scpFiles(dest_path, dest_path, hostlist)

    def __restartOMmonitor(self):
        """
        function: restart OM_monitor for new environment variable
        input:  NA
        output: NA
        """
        #1. find om_monitor process
        DefaultValue.KillAllProcess(g_opts.user, "om_monitor")
        g_logger.log("Kill om_monitor successfully.")
        cmd = "source /etc/profile;source '%s';%s/bin/om_monitor " \
              "-L %s/%s/cm/om_monitor >> /dev/null 2>&1 &" % \
              (g_opts.mpprcFile, g_clusterInfo.appPath,
               g_clusterInfo.logPath, g_opts.user)
        (status, output) = subprocess.getstatusoutput(cmd)
        if status != 0:
            g_logger.debug("The cmd is %s " % cmd)
            g_logger.debug("Start om_monitor process failed.")
            g_logger.debug("Error:%s\n" % output)

        g_logger.log("Restart om_monitor succeed.")

    def __cleanAuthConfig(self):
        auth_config = os.path.join(os.path.dirname(g_opts.mpprcFile),
                                   "auth_config")
        if os.path.isdir(auth_config):
            try:
                shutil.rmtree(auth_config)
            except Exception as e:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] %
                                auth_config)
        logPath = ClusterDir.getUserLogDirWithUser(g_opts.user)
        kerberosLog = "%s/kerberos" % logPath
        if os.path.exists(kerberosLog):
            FileUtil.removeDirectory(kerberosLog)
        g_logger.log("Clean auth config directory succeed.")

    def __cleanServer(self):
        if os.path.isdir(g_opts.gausshome_kerberso):
            try:
                shutil.rmtree(g_opts.gausshome_kerberso)
            except Exception as e:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] %
                                g_opts.gausshome_kerberso)

        krb_data = "%s/var/krb5kdc" % g_opts.gausshome
        if os.path.isdir(krb_data):
            try:
                shutil.rmtree(krb_data)
            except Exception as e:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] % krb_data)

        # Remove cron
        crontabFile = "%s/gauss_crontab_file_%d" % \
                      (EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
        cmd = "crontab -l > %s; " % crontabFile
        cmd += "sed -i '/^.*krb5kdc.*$/d' '%s'; " % crontabFile
        cmd += "crontab '%s';" % crontabFile
        cmd += "rm -f '%s'" % crontabFile
        (status, output) = subprocess.getstatusoutput(cmd)
        if (status != 0):
            #no need raise error here, user can do it manually.
            g_logger.debug("The cmd is %s " % cmd)
            g_logger.debug("Failed to delete regular tasks. Error: \n%s  "
                           "You can do it manually." % str(output))

        cmd = "source /etc/profile; source '%s' && \
               proc_pid_list=`ps ux | grep -E 'krb5kdc'|  \
               grep -v 'grep'|awk '{print \$2}'` && \
               (if [ X\"$proc_pid_list\" != X\"\" ];  \
               then echo \"$proc_pid_list\" | xargs -r -n 100 kill -9 ; fi)" \
                % (g_opts.mpprcFile)
        (status, output) = subprocess.getstatusoutput(cmd)
        if (status != 0):
            raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)

        g_logger.log("Clean Server files and process succeed.")

    def __install(self):
        try:
            self.__configKrb5(False, g_opts.server)
            self.__setUserEnvVariable(False, g_opts.server)
            self.__triggerJob(False, g_opts.server)
            if not g_opts.server:
                self.__configPostgresql(False)
                self.__configPgHba(False)
                self.__configDNPgHba(False)
                self.__restartOMmonitor()
            g_logger.log("Successfully start Kerberos Authentication.")
        except Exception as e:
            self.__rollback(g_opts.server)
            raise e
        finally:
            pass


    def __uninstall(self, isRollBack=False):
        self.__configKrb5(True)
        self.__setUserEnvVariable(True, False, isRollBack)
        self.__triggerJob(True)
        self.__configPostgresql(True)
        self.__configPgHba(True)
        self.__configDNPgHba(True)
        if not isRollBack:
            self.__cleanAuthConfig()
            self.__cleanServer()
        g_logger.log("Successfully close Kerberos Authentication.")

    def run(self):
        '''
        function: call start or stop
        '''
        if(g_opts.action == "install"):
            self.__install()
        elif(g_opts.action  == "uninstall"):
            self.__uninstall(False)
        else:
            raise Exception(ErrorCode.GAUSS_500["GAUSS_50000"] % g_opts.action)


def parseCommandLine():
    """
    function: Check parameter from command line
    input : NA
    output: NA
    """
    try:
        opts, args = getopt.getopt(sys.argv[1:], "m:U:",
                                   ["help", "krb-server", "krb-client"])
    except Exception as e:
        usage()
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"] % str(e))

    if(len(args) > 0):
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"] %
                               str(args[0]))

    global g_opts
    g_opts = CmdOptions()

    for (key, value) in opts:
        if (key == "--help"):
            usage()
            sys.exit(0)
        elif(key == "-m"):
            g_opts.action = value
        elif (key == "-U"):
            g_opts.user = value
        elif (key == "--krb-server"):
            g_opts.server = True
        elif (key == "--krb-client"):
            g_opts.client = True

    if g_opts.action == 'install':
        if not g_opts.server and not g_opts.client:
            GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] %
                                   "-krb-server' or '--krb-client")
        if g_opts.server and g_opts.client:
            GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50005"] %
                                   ("-krb-server", "-krb-client"))


def usage():
    '''
 python3 KerberosUtility.py is a utility to config a {0} cluster.
Usage:
    KerberosUtility.py -m install -U USER --krb-server
    KerberosUtility.py -m install -U USER --krb-client
    KerberosUtility.py -m uninstall -U USER
General options:
    -m          "install" will set kerberos config for {0} cluster,
                "uninstall" will cancel to set kerberos config for {0} cluster.
    -U          Cluster User for {0} cluster
Install options:
    --krb-server          Execute install for server.
                          This parameter only work for install
    --krb-client          Execute install for client.
                          This parameter only work for install
Notes:
    --krb-server and --krb-client can only chose one
    '''
    print(usage.__doc__)

if __name__ == '__main__':
    """
    main function
    """
    try:
        parseCommandLine()
        initGlobals()
    except Exception as e:
        GaussLog.exitWithError(str(e))

    try:
        kbs = Kerberos()
        kbs.run()
        sys.exit(0)
    except Exception as e:
        g_logger.logExit(str(e))
