# -*- coding:utf-8 -*-
#############################################################################
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
#
# 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  : gs_om is a utility to manage a Gauss200 cluster.
#############################################################################

import subprocess
import os
import sys
import pwd

from datetime import datetime
import getpass

sys.path.append(sys.path[0] + "/../../../")
from gspylib.common.DbClusterInfo import dbClusterInfo, queryCmd
from gspylib.threads.SshTool import SshTool
from gspylib.common.DbClusterStatus import DbClusterStatus
from gspylib.common.ErrorCode import ErrorCode
from gspylib.common.Common import DefaultValue, ClusterCommand
from gspylib.common.OMCommand import OMCommand
from gspylib.os.gsfile import g_file
from base_utils.os.cmd_util import CmdUtil
from base_utils.os.compress_util import CompressUtil
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.os.user_util import UserUtil
from base_utils.common.constantsbase import ConstantsBase
from domain_utils.cluster_file.cluster_dir import ClusterDir
from base_utils.executor.cmd_executor import CmdExecutor

# Cert
EMPTY_CERT = "emptyCert"
EMPTY_FLAG = "emptyflag"

###########################################
class OmImpl:
    """
    init the command options
    save command line parameter values
    """

    def __init__(self, OperationManager):
        """
        function: constructor
        """
        # global
        self.context = OperationManager
        self.logger = OperationManager.logger
        self.user = OperationManager.user
        self.newClusterInfo = None
        self.oldClusterInfo = None
        self.utilsPath = None
        self.mpprcFile = OperationManager.g_opts.mpprcFile
        self.nodeId = OperationManager.g_opts.nodeId
        self.time_out = OperationManager.g_opts.time_out
        self.mode = OperationManager.g_opts.mode
        self.clusterInfo = OperationManager.clusterInfo
        self.dataDir = OperationManager.g_opts.dataDir
        self.sshTool = None

    def doStopCluster(self):
        """
        function: do stop cluster
        input: NA
        output: NA
        """
        pass

    def doStart(self):
        """
        function:Start cluster or node
        input:NA
        output:NA
        """
        self.doStartCluster()

    def doStop(self):
        """
        function:Stop cluster or node
        input:NA
        output:NA
        """
        self.logger.debug("Operating: Stopping.")
        self.doStopCluster()

    def getNodeStatus(self, nodename):
        """
        function: get node status
        input: nodename
        output: NA
        """
        try:
            # Create a temporary file to save cluster status
            tmpDir = EnvUtil.getTmpDirFromEnv()
            tmpFile = os.path.join(tmpDir, "gauss_cluster_status.dat_" + \
                                   str(datetime.now().strftime(
                                       '%Y%m%d%H%M%S')) + "_" + str(
                os.getpid()))

            # Perform the start operation
            # Writes the execution result to a temporary file
            cmd = ClusterCommand.getQueryStatusCmd("", tmpFile, True)
            (status, output) = subprocess.getstatusoutput(cmd)
            if (status != 0):
                self.logger.debug("The cmd is %s " % cmd)
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % \
                                cmd + "Error: \n%s" % output)

            # Initialize cluster status information for the temporary file
            clusterStatus = DbClusterStatus()
            clusterStatus.initFromFile(tmpFile)

            # Get node status
            nodeStatusInfo = None
            for dbNode in clusterStatus.dbNodes:
                if (dbNode.name == nodename):
                    nodeStatusInfo = dbNode
            if (nodeStatusInfo and nodeStatusInfo.isNodeHealthy()):
                nodeStatus = clusterStatus.OM_NODE_STATUS_NORMAL
            else:
                nodeStatus = clusterStatus.OM_NODE_STATUS_ABNORMAL

            FileUtil.cleanTmpFile(tmpFile)
            return nodeStatus
        except Exception as e:
            FileUtil.cleanTmpFile(tmpFile)
            self.logger.debug(
                "Failed to get node status. Error: \n%s." % str(e))
            return "Abnormal"

    def getQueryStatusByCm(self, nodeId):
        """
        function: query status by cm
        :param nodeId:
        :return:
        """
        # Call cm_ctl to query the cluster status
        get_cluster_status_cmd = ClusterCommand.getQueryStatusCmdForDisplay(
                                nodeId,
                                self.context.g_opts.outFile,
                                self.context.clusterInfo.clusterType,
                                self.context.g_opts.show_detail,
                                self.context.g_opts.showAll)

        if self.context.g_opts.outFile != "":
            get_cluster_status_cmd += "&& chmod %s '%s'" % (
            DefaultValue.KEY_FILE_MODE, self.context.g_opts.outFile)
        # Call cm_ctl to query the cluster status
        (status, output) = subprocess.getstatusoutput(get_cluster_status_cmd)
        if status != 0:
            if not(status == 255 and "Down" in output):
                raise Exception(ErrorCode.GAUSS_516[
                                    "GAUSS_51600"] + "\nCommand:%s\nError: \n%s" % (
                                    get_cluster_status_cmd, output))
        node_status_line = ""
        if self.context.g_opts.nodeName != "":
            node_status = self.getNodeStatus(self.context.g_opts.nodeName)
            node_status_line = "node_state                : %s\n\n" % node_status + \
                    "-----------------------------------------------------------------------\n"

        # Outputs the check result if no output file is specified
        if self.context.g_opts.outFile == "":
            if status == 0 and self.context.g_opts.show_detail:
                temp_lines = output.splitlines()
                node_head = temp_lines[-3].split("|")[0]
                node_split = "-" * len(node_head)
                node_info = [info.strip() for info in temp_lines[-1].split("|")]
                self.logger.log("\n".join(temp_lines[:-3] + [node_head] + [node_split] +
                                          node_info))
            else:
                self.logger.log(output)
            if node_status_line:
                self.logger.log(node_status_line)
        else:
            if node_status_line:
                FileUtil.createFileInSafeMode(self.context.g_opts.outFile)
                with open(self.context.g_opts.outFile, "a") as fp:
                    fp.write(node_status_line)
                    fp.write(os.linesep)
                    fp.flush()
                    fp.close()
            self.logger.log("Status check is completed.")

    def getQueryStatusWithoutCm(self, nodeId=0, sshtool=None, hostName=""):
        """
        function:query status without cm
        :param nodeId:
        :param sshtool:
        :param hostName:
        :return:
        """
        cmd = queryCmd()
        if self.context.g_opts.outFile != "":
            cmd.outputFile = self.context.g_opts.outFile
        else:
            cmd.outputFile = self.logger.logFile
        if self.context.g_opts.show_detail:
            if (self.context.clusterInfo.clusterType
                    == DefaultValue.CLUSTER_TYPE_SINGLE_PRIMARY_MULTI_STANDBY):
                cmd.dataPathQuery = True
                cmd.azNameQuery = True
            else:
                cmd.dataPathQuery = True
        else:
            if nodeId > 0:
                self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
                                                       nodeId, cmd.outputFile)
                return
            az_name = self.context.g_opts.azName
            if az_name:
                self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
                                                       nodeId, cmd.outputFile, az_name)
                return
            if self.context.g_opts.showAll:
                self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
                                                       nodeId, cmd.outputFile)
                return
            cmd.clusterStateQuery = True
        db_nums = len(self.context.clusterInfo.dbNodes)
        ssh_tools = []
        for _ in range(db_nums - 1):
            ssh_tools.append(SshTool([], timeout=self.time_out))
        self.context.clusterInfo.queryClsInfo(hostName, ssh_tools,
                                              self.context.mpprcFile, cmd)
    def doStatus(self):
        """
        function:Get the status of cluster or node
        input:NA
        output:NA
        """
        host_name = NetUtil.GetHostIpOrName()
        sshtool = SshTool(self.context.clusterInfo.getClusterNodeNames(), timeout=self.time_out)
        node_id = 0
        if self.context.g_opts.nodeName != "":
            for db_node in self.context.clusterInfo.dbNodes:
                if db_node.name == self.context.g_opts.nodeName:
                    node_id = db_node.id
            if node_id == 0:
                raise Exception(
                    ErrorCode.GAUSS_516["GAUSS_51619"]
                    % self.context.g_opts.nodeName)
        if ((not self.context.clusterInfo.hasNoCm())
            and DefaultValue.isgreyUpgradeNodeSpecify(self.context.user,
            DefaultValue.GREY_UPGRADE_STEP_UPGRADE_PROCESS, None, self.context.logger)):
            self.getQueryStatusByCm(node_id)
        else:
            self.getQueryStatusWithoutCm(node_id, sshtool, host_name)
        self.logger.debug("Successfully obtained the cluster status.")

    def change_cluster_info(self):
        temp_change_dic = {}
        for i in range(0, len(self.context.g_opts.old_values)):
            temp_change_dic['90123456789%d' % i] = (self.context.g_opts.old_values[i],
                                                    self.context.g_opts.new_values[i])
        # change old value to middle value
        for key, value in temp_change_dic.items():
            for node in self.context.clusterInfo.dbNodes:
                self.change_node_info(node, key, value[0])
                for inst in node.datanodes:
                    self.change_inst_info(inst, key, value[0])
        # change middle value to new value
        for key, value in temp_change_dic.items():
            for node in self.context.clusterInfo.dbNodes:
                self.change_node_info(node, value[1], key)
                for inst in node.datanodes:
                    self.change_inst_info(inst, value[1], key)

    def change_node_info(self, node, new_value, old_value):
        if node.name == old_value:
            node.name = new_value
        for i in range(len(node.backIps)):
            if node.backIps[i] == old_value:
                node.backIps[i] = new_value
        for i in range(len(node.virtualIp)):
            if node.virtualIp[i] == old_value:
                node.virtualIp[i] = new_value
        for i in range(len(node.sshIps)):
            if node.sshIps[i] == old_value:
                node.sshIps[i] = new_value
        self.logger.debug("Change the info of node %s successfully." % node.name)

    def change_inst_info(self, inst, new_value, old_value):
        if inst.hostname == old_value:
            inst.hostname = new_value
        if str(inst.port) == old_value:
            inst.port = int(new_value)
        if str(inst.haPort) == old_value:
            inst.haPort = int(new_value)
        for i in range(len(inst.listenIps)):
            if inst.listenIps[i] == old_value:
                inst.listenIps[i] = new_value
        for i in range(len(inst.haIps)):
            if inst.haIps[i] == old_value:
                inst.haIps[i] = new_value
        self.logger.debug("Change the DN inst on %s successfully." % inst.hostname)

    def doRebuildConf(self):
        """
        generating static configuration files for all nodes
        input:NA
        output:NA
        """
        try:
            self.logger.log(
                "Generating static configuration files for all nodes.")
            tmpDirName = ""
            # Initialize the cluster information according to the XML file
            self.context.clusterInfo = dbClusterInfo()
            if self.context.g_opts.old_values:
                self.context.clusterInfo.initFromStaticConfig(self.context.user)
                self.change_cluster_info()
            else:
                self.context.clusterInfo.initFromXml(self.context.g_opts.confFile)

            # 1.create a tmp dir
            self.logger.log(
                "Creating temp directory to store static configuration files.")
            dirName = os.path.dirname(os.path.realpath(__file__))
            tmpDirName = os.path.realpath(
                "%s/../../static_config_files" % dirName)
            cmd = f"mkdir -p -m {DefaultValue.KEY_DIRECTORY_MODE} {tmpDirName}"
            status, output = subprocess.getstatusoutput(cmd)
            if (status != 0):
                raise Exception(
                    ErrorCode.GAUSS_502["GAUSS_50208"]
                    % "temporary directory" + "\nCommand:%s\nError: %s"
                    % (cmd, output))
            self.logger.log("Successfully created the temp directory.")

            # create static files
            self.logger.log("Generating static configuration files.")
            for dbNode in self.context.clusterInfo.dbNodes:
                staticConfigPath = "%s/cluster_static_config_%s" % (
                    tmpDirName, dbNode.name)
                self.context.clusterInfo.saveToStaticConfig(staticConfigPath,
                                                            dbNode.id)
            self.logger.log(
                "Successfully generated static configuration files.")
            self.logger.log(
                "Static configuration files for all nodes are saved in %s."
                % tmpDirName)

            # check if need send static config files
            if not self.context.g_opts.distribute:
                self.logger.debug(
                    "No need to distribute static configuration files "
                    "to installation directory.")
                return

            # distribute static config file
            self.logger.log(
                "Distributing static configuration files to all nodes.")
            for dbNode in self.context.clusterInfo.dbNodes:
                if (dbNode.name != NetUtil.GetHostIpOrName()):
                    cmd = \
                        "pscp -H %s '%s'/cluster_static_config_%s '%s'" \
                        "/bin/cluster_static_config" % (
                            dbNode.name, tmpDirName,
                            dbNode.name, self.context.clusterInfo.appPath)
                else:
                    cmd = \
                        "cp '%s'/cluster_static_config_%s '%s'" \
                        "/bin/cluster_static_config" % (
                            tmpDirName,
                            dbNode.name, self.context.clusterInfo.appPath)
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    raise Exception(
                        ErrorCode.GAUSS_502["GAUSS_50216"]
                        % "static configuration file"
                        + "Node: %s.\nCommand: \n%s\nError: \n%s"
                        % (dbNode.name, cmd, output))
            self.logger.log(
                "Successfully distributed static configuration files.")

        except Exception as e:
            FileUtil.removeDirectory(tmpDirName)
            raise Exception(str(e))

    ##########################################################################
    # doReplaceSSLCert start
    ##########################################################################
    def doReplaceSSLCert(self):
        """
        function: replace ssl cert files
        input: NA
        output: NA
        """
        try:
            # Initialize the cluster information according to the xml file
            self.context.clusterInfo = dbClusterInfo()
            self.context.clusterInfo.initFromStaticConfig(
                UserUtil.getPathOwner(self.context.g_opts.certFile)[0])
            self.sshTool = SshTool(
                self.context.clusterInfo.getClusterNodeNames(),
                self.logger.logFile)
        except Exception as e:
            raise Exception(str(e))

        try:
            self.logger.log("Starting ssl cert files replace.", "addStep")
            tempDir = os.path.join(EnvUtil.getTmpDirFromEnv(),
                                   "tempCertDir")

            # unzip files to temp directory
            if (os.path.exists(tempDir)):
                FileUtil.removeDirectory(tempDir)
            FileUtil.createDirectory(tempDir, True,
                                   DefaultValue.KEY_DIRECTORY_MODE)
            CompressUtil.decompressZipFiles(self.context.g_opts.certFile, tempDir)

            realCertList = DefaultValue.CERT_FILES_LIST
            clientCertList = DefaultValue.CLIENT_CERT_LIST
            # check file exists
            for clientCert in clientCertList:
                sslFile = os.path.join(tempDir, clientCert)
                if (not os.path.isfile(sslFile)):
                    raise Exception(
                        (ErrorCode.GAUSS_502["GAUSS_50201"] % sslFile) + \
                        "Missing SSL client cert file in ZIP file.")

            certList = []
            dnDict = self.getDnNodeDict()
            for cert in realCertList:
                sslFile = os.path.join(tempDir, cert)

                if (not os.path.isfile(
                        sslFile) and cert != DefaultValue.SSL_CRL_FILE):
                    raise Exception(
                        (ErrorCode.GAUSS_502["GAUSS_50201"] % sslFile) + \
                        "Missing SSL server cert file in ZIP file.")
                if (os.path.isfile(sslFile)):
                    certList.append(cert)

            # distribute cert files to datanodes
            self.doDNBackup()
            self.distributeDNCert(certList, dnDict)

            # clear temp directory
            FileUtil.removeDirectory(tempDir)
            if (not self.context.g_opts.localMode):
                self.logger.log(
                    "Successfully distributed cert files on all nodes.")
        except Exception as e:
            FileUtil.removeDirectory(tempDir)
            raise Exception(str(e))

    def isDnEmpty(self, nodeName=""):
        """
        function: Is there exists empty file in dbnodes directory.
        input: node name
        output: True/False
        """
        allDnNodeDict = self.getDnNodeDict()
        nodeDnDir = allDnNodeDict[nodeName]
        emptyCert = os.path.join(nodeDnDir, EMPTY_CERT)
        status = self.sshTool.checkRemoteFileExist(
            nodeName, emptyCert,
            self.context.g_opts.mpprcFile)
        return status

    def backup_cert_files(self, ssl_dir):
        """
        function: Back up the certificate files in the ssl_dir directory.
        input: certificate directory
        output: NA
        """
        if self.context.g_opts.localMode:
            # empty flag
            if os.path.isfile(
                    os.path.join(ssl_dir, DefaultValue.CERT_BACKUP_FILE)):
                FileUtil.removeFile(
                    os.path.join(ssl_dir, DefaultValue.CERT_BACKUP_FILE))
            if not os.path.exists(os.path.join(ssl_dir, EMPTY_FLAG)):
                os.mknod(os.path.join(ssl_dir, EMPTY_FLAG))
            cmd = " %s && " % CmdUtil.getCdCmd(ssl_dir)
            cmd += CompressUtil.getCompressFilesCmd(DefaultValue.CERT_BACKUP_FILE, "*")
            (status, output) = CmdUtil.retryGetstatusoutput(cmd)
            if status != 0:
                FileUtil.removeFile(os.path.join(ssl_dir, EMPTY_FLAG))
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % \
                                cmd + "Failed to backup cert files on local node." +
                                "Error: \n%s" % output)
            if os.path.exists(os.path.join(ssl_dir, EMPTY_FLAG)):
                os.remove(os.path.join(ssl_dir, EMPTY_FLAG))
        else:
            sshcmd = "if [ -d '%s' ]; then " % ssl_dir
            sshcmd += " %s && " % CmdUtil.getCdCmd(ssl_dir)
            sshcmd += g_file.SHELL_CMD_DICT["deleteFile"] % (
                DefaultValue.CERT_BACKUP_FILE, DefaultValue.CERT_BACKUP_FILE) + ";"
            sshcmd += CmdUtil.getTouchCmd(EMPTY_FLAG)
            sshcmd += " && " + CompressUtil.getCompressFilesCmd(DefaultValue.CERT_BACKUP_FILE, "*;")
            sshcmd += g_file.SHELL_CMD_DICT["deleteFile"] % (EMPTY_FLAG, EMPTY_FLAG)
            sshcmd += " && " + g_file.SHELL_CMD_DICT["changeMode"] % (
                DefaultValue.KEY_FILE_MODE, DefaultValue.CERT_BACKUP_FILE)
            sshcmd += "; fi"
            self.sshTool.executeCommand(sshcmd, DefaultValue.SUCCESS,
                                        [node.name for node in self.context.clusterInfo.dbNodes],
                                        self.context.g_opts.mpprcFile)

    def doDNBackup(self):
        """
        function: backup SSL cert files on single_inst cluster.
        input: backupFlag is a flag of exist DB in node
        output: NA
        """
        self.logger.log("Backing up old ssl cert files.")

        backupList = DefaultValue.CERT_FILES_LIST[:]
        allDnNodeDict = self.getDnNodeDict()
        normalNodeList = []
        dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
                                   "share/sslcert/dss/")
        cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
                                  "share/sslcert/cm/")
        om_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
                                  "share/sslcert/om/")

        tarBackupList = []
        if (self.context.g_opts.localMode):
            self.logger.debug("Backing up database node SSL cert files.")
            nodeDnDir = allDnNodeDict[NetUtil.GetHostIpOrName()]
            backupFlagFile = os.path.join(nodeDnDir, "certFlag")
            if (os.path.isfile(backupFlagFile)):
                self.logger.log("There is no need to backup ssl cert files.")
                return

            os.mknod(backupFlagFile, ConstantsBase.KEY_FILE_PERMISSION)
            for certFile in backupList:
                realCertFile = os.path.join(nodeDnDir, certFile)
                if (os.path.isfile(realCertFile)):
                    tarBackupList.append(certFile)

            if (len(tarBackupList) == 0):
                os.mknod(os.path.join(nodeDnDir, EMPTY_CERT))
                cmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
                cmd += CompressUtil.getCompressFilesCmd(
                    DefaultValue.CERT_BACKUP_FILE, EMPTY_CERT)
            else:
                cmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
                cmd += "tar -zcvf %s" % (DefaultValue.CERT_BACKUP_FILE)
                for certFile in tarBackupList:
                    cmd += " %s" % certFile
            (status, output) = CmdUtil.retryGetstatusoutput(cmd)
            if (status != 0):
                raise Exception(
                    ErrorCode.GAUSS_514["GAUSS_51400"]
                    % cmd + "Failed backup gds cert files on local node."
                    + "Error: \n%s" % output)

            # Clear empty file
            if (os.path.isfile(os.path.join(nodeDnDir, EMPTY_CERT))):
                os.remove(os.path.join(nodeDnDir, EMPTY_CERT))
            if os.path.isdir(dss_ssl_dir):
                self.backup_cert_files(dss_ssl_dir)
            if os.path.isdir(cm_ssl_dir):
                self.backup_cert_files(cm_ssl_dir)
            if os.path.isdir(om_ssl_dir):
                self.backup_cert_files(om_ssl_dir)
            self.logger.log("Successfully executed local backup.")
            return
        # 1 check backup flag file on all dbnodes.
        for node in allDnNodeDict.keys():
            nodeDnDir = allDnNodeDict[node]
            backupFlagFile = os.path.join(nodeDnDir, "certFlag")
            status = self.sshTool.checkRemoteFileExist(
                node, backupFlagFile,
                self.context.g_opts.mpprcFile)
            if not status:
                normalNodeList.append(node)
        # 2 if exists flag file on anyone node, there will be return.
        if (len(normalNodeList) != len(allDnNodeDict.keys())):
            self.logger.log("There is no need to backup on all dbnodes.")
            return
        # 3 backup cert files on all dbnodes.
        for node in allDnNodeDict.keys():
            nodeDnDir = allDnNodeDict[node]
            backupFlagFile = os.path.join(nodeDnDir, "certFlag")
            backupTar = os.path.join(nodeDnDir, DefaultValue.CERT_BACKUP_FILE)
            sshcmd = g_file.SHELL_CMD_DICT["overWriteFile"] % (
                "backupflagfile", backupFlagFile)
            sshcmd += " && " + g_file.SHELL_CMD_DICT["changeMode"] % (
                DefaultValue.KEY_FILE_MODE, backupFlagFile)
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS, [node],
                                        self.context.g_opts.mpprcFile)
            for certFile in backupList:
                realCertFile = os.path.join(nodeDnDir, certFile)
                status = self.sshTool.checkRemoteFileExist(
                    node, realCertFile,
                    self.context.g_opts.mpprcFile)
                if status:
                    tarBackupList.append(certFile)
                # if no cert files,
                # there will be create a file for '.tar' file.
                if (len(tarBackupList) == 0):
                    sshcmd = CmdUtil.getCreateFileCmd(
                        os.path.join(nodeDnDir, EMPTY_CERT))
                    self.sshTool.executeCommand(sshcmd,
                                                DefaultValue.SUCCESS, [node],
                                                self.context.g_opts.mpprcFile)
                    sshcmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
                    sshcmd += CompressUtil.getCompressFilesCmd(
                        DefaultValue.CERT_BACKUP_FILE, EMPTY_CERT)
                else:
                    sshcmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
                    sshcmd += "tar -zcvf %s" % (DefaultValue.CERT_BACKUP_FILE)
                    for certDir in tarBackupList:
                        sshcmd += " %s" % certDir
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS, [node],
                                        self.context.g_opts.mpprcFile)
            # Clear empty file
            if (self.isDnEmpty(node)):
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(nodeDnDir, EMPTY_CERT),
                    os.path.join(nodeDnDir, EMPTY_CERT))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS, [node],
                                            self.context.g_opts.mpprcFile)
            self.logger.log(
                "Successfully backup SSL cert files on [%s]." % node)
            sshcmd = g_file.SHELL_CMD_DICT["changeMode"] % (
                DefaultValue.KEY_FILE_MODE, backupTar)
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS, [node],
                                        self.context.g_opts.mpprcFile)
        self.backup_cert_files(dss_ssl_dir)
        self.backup_cert_files(cm_ssl_dir)
        self.backup_cert_files(om_ssl_dir)

    def local_rollback_cert(self, ssl_dir, cert_list):
        """
        function: rollback SSL cert files
        input: Certificate directory, which is used to replace the certificate file.
        output: NA
        """
        # create dss temp dir
        temp_dir = os.path.join(ssl_dir, "dssTempDir")
        if not os.path.exists(temp_dir):
            os.mkdir(temp_dir)
        else:
            FileUtil.removeDirectory(temp_dir)
            os.mkdir(temp_dir)

        # backup cert cert to temp dir
        for num in iter(cert_list):
            certfile = os.path.join(ssl_dir, num)
            if os.path.exists(certfile):
                FileUtil.moveFile(certfile, temp_dir)

        # decompress backup package to cert dir
        cmd = "cd '%s' && if [ -f '%s' ];then tar -zxf %s;fi" % \
              (ssl_dir, DefaultValue.CERT_BACKUP_FILE, DefaultValue.CERT_BACKUP_FILE)
        status, _ = subprocess.getstatusoutput(cmd)
        if status != 0:
            # copy cert files from temp dir to cert dir
            cmd = "cp '%s'/* '%s' && rm -rf '%s' && rm -rf '%s'" % \
                   (temp_dir, temp_dir, temp_dir, os.path.join(temp_dir, EMPTY_FLAG))
            CmdUtil.getstatusoutput_by_fast_popen(cmd)

        FileUtil.removeDirectory(temp_dir)
        FileUtil.removeDirectory(os.path.join(temp_dir, EMPTY_FLAG))
        self.logger.debug("Successfully rollback ssl cert files.")

    def cert_rollback(self):
        """
        function: Certificate Rollback
        input: NA
        output: NA
        """
        dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user), "share/sslcert/dss/")
        cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user), "share/sslcert/cm/")
        om_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user), "share/sslcert/om/")
        if self.context.g_opts.localMode:
            if os.path.exists(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
                    getpass.getuser()) == 'on':
                self.local_rollback_cert(dss_ssl_dir,
                                         DefaultValue.GDS_CERT_LIST)
                self.regen_dss_cert()
                self.logger.log("Successfully rollback dss ssl cert files.")
            if os.path.exists(cm_ssl_dir):
                self.local_rollback_cert(cm_ssl_dir, DefaultValue.GDS_CERT_LIST)
                self.logger.log("Successfully rollback cm ssl cert files.")
            if os.path.exists(om_ssl_dir):
                self.local_rollback_cert(om_ssl_dir, DefaultValue.SERVER_CERT_LIST)
                self.logger.log("Successfully rollback om ssl cert files.")
        else:
            # rollback dss cert files
            if os.path.exists(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
                    getpass.getuser()) == 'on':
                self.rollback_cert(dss_ssl_dir, DefaultValue.GDS_CERT_LIST)
                self.regen_dss_cert()
                self.logger.log("Successfully replace dss SSL cert files.")

            # rollback cm cert files
            if os.path.exists(cm_ssl_dir):
                self.rollback_cert(cm_ssl_dir, DefaultValue.GDS_CERT_LIST)
                self.logger.log("Successfully replace cm SSL cert files.")

            # rollback om cert files
            if os.path.exists(om_ssl_dir):
                self.rollback_cert(om_ssl_dir, DefaultValue.SERVER_CERT_LIST)
                self.logger.log("Successfully replace om SSL cert files.")

    def doDNSSLCertRollback(self):
        """
        function: rollback SSL cert file in DN instance directory
        input:  NA
        output: NA
        """
        self.context.clusterInfo = dbClusterInfo()
        self.context.clusterInfo.initFromStaticConfig(
            pwd.getpwuid(os.getuid()).pw_name)
        self.sshTool = SshTool(self.context.clusterInfo.getClusterNodeNames(),
                               self.logger.logFile)
        backupList = DefaultValue.CERT_FILES_LIST[:]

        allDnNodeDict = self.getDnNodeDict()
        noBackupList = []

        temp = "tempDir"
        if self.context.g_opts.localMode:
            if ((NetUtil.GetHostIpOrName() in allDnNodeDict.keys()) and
                    os.path.isfile(os.path.join(
                        allDnNodeDict[NetUtil.GetHostIpOrName()],
                        DefaultValue.CERT_BACKUP_FILE))):

                localDnDir = allDnNodeDict[NetUtil.GetHostIpOrName()]
                tempDir = os.path.join(localDnDir, temp)
                if (os.path.exists(tempDir)):
                    FileUtil.removeDirectory(tempDir)
                os.mkdir(tempDir, ConstantsBase.KEY_DIRECTORY_PERMISSION)

                for certFile in backupList:
                    realCertFile = os.path.join(localDnDir, certFile)
                    if (os.path.exists(realCertFile)):
                        FileUtil.moveFile(realCertFile, tempDir)

                cmd = "cd '%s' && if [ -f '%s' ];then tar -zxvf %s;fi" % \
                      (localDnDir, DefaultValue.CERT_BACKUP_FILE,
                       DefaultValue.CERT_BACKUP_FILE)
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    cmd = "cp '%s'/* '%s' && rm -rf '%s'" % (
                        tempDir, localDnDir, tempDir)
                    (status, output) = subprocess.getstatusoutput(cmd)
                    raise Exception(
                        (ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
                        + "Failed uncompression SSL backup file."
                        + "Error: \n%s" % output)

                # remove temp directory
                if (os.path.exists(tempDir)):
                    FileUtil.removeDirectory(tempDir)

                # set guc option
                if (os.path.isfile(
                        os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
                    cmd = \
                        "gs_guc set -D %s " \
                        "-c \"ssl_crl_file=\'%s\'\"" \
                        % (localDnDir, DefaultValue.SSL_CRL_FILE)
                else:
                    cmd = \
                        "gs_guc set -D %s " \
                        "-c \"ssl_crl_file=\'\'\"" % localDnDir
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    raise Exception(
                        ErrorCode.GAUSS_514["GAUSS_51400"]
                        % cmd + "Error: \n%s" % output)

                if (os.path.isfile(os.path.join(localDnDir, EMPTY_CERT))):
                    os.remove(os.path.join(localDnDir, EMPTY_CERT))
                self.cert_rollback()

                self.logger.log(
                    "Successfully rollback SSL cert files with local mode.")
                return
            else:
                self.cert_rollback()
                self.logger.log("There is not node data exists backup files.")
                return
        # 1.check backup file "gsql_cert_backup.tar.gz" on all dbnodes.
        for node in allDnNodeDict.keys():
            backupGzFile = os.path.join(allDnNodeDict[node],
                                        DefaultValue.CERT_BACKUP_FILE)
            status = self.sshTool.checkRemoteFileExist(
                node, backupGzFile,
                self.context.g_opts.mpprcFile)
            if not status:
                noBackupList.append(node)
        if (len(noBackupList) > 0):
            raise Exception(
                (ErrorCode.GAUSS_502["GAUSS_50201"]
                 % DefaultValue.CERT_BACKUP_FILE)
                + "Can't rollback SSL cert files on %s." % noBackupList)

        # 2.perform rollback on all dbnodes.
        for node in allDnNodeDict.keys():
            backupGzFile = os.path.join(
                allDnNodeDict[node], DefaultValue.CERT_BACKUP_FILE)
            # 2-1.move SSL cert files in dn directory to temp directory.
            sshcmd = "cd '%s' && if [ -d '%s' ];then rm -rf '%s'" \
                     " && mkdir '%s';else mkdir '%s';fi" % \
                     (allDnNodeDict[node], temp, temp, temp, temp)
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS,
                                        [node], self.context.g_opts.mpprcFile)
            for certFile in backupList:
                realCertFile = os.path.join(allDnNodeDict[node], certFile)
                sshcmd = " %s && " % CmdUtil.getCdCmd(
                    os.path.join(allDnNodeDict[node], temp))
                sshcmd += g_file.SHELL_CMD_DICT["renameFile"] % (
                    realCertFile, realCertFile, "./")
                self.sshTool.executeCommand(
                    sshcmd,
                    DefaultValue.SUCCESS,
                    [node],
                    self.context.g_opts.mpprcFile)

            # 2-2.uncompression "gsql_cert_backup.tar.gz" file
            sshcmd = "cd '%s' && if [ -f '%s' ];then tar -zxvf %s;fi" % \
                     (allDnNodeDict[node], DefaultValue.CERT_BACKUP_FILE,
                      DefaultValue.CERT_BACKUP_FILE)
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS,
                                        [node],
                                        self.context.g_opts.mpprcFile)

            # 2-3.clear temp directory
            sshcmd = " %s && " % CmdUtil.getCdCmd(allDnNodeDict[node])
            sshcmd += g_file.SHELL_CMD_DICT["deleteDir"] % (temp, temp)
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS,
                                        [node],
                                        self.context.g_opts.mpprcFile)

            # 2-4.is have "sslcrl-file.crl",config 'ssl_crl_file' option
            status = self.sshTool.checkRemoteFileExist(
                node, os.path.join(
                    allDnNodeDict[node],
                    DefaultValue.SSL_CRL_FILE),
                self.context.g_opts.mpprcFile)
            # exists 'sslcrl-file.crl' file ,config option of 'postgresql.conf'
            if (status):
                if node == NetUtil.GetHostIpOrName():
                    sshcmd = \
                        "gs_guc set -D %s " \
                        "-c \"ssl_crl_file='%s'\"" \
                        % (allDnNodeDict[node], DefaultValue.SSL_CRL_FILE)
                else:
                    sshcmd = "gs_guc set -D %s " \
                             "-c \"ssl_crl_file=\\\\\\'%s\\\\\\'\"" \
                             % (allDnNodeDict[node], DefaultValue.SSL_CRL_FILE)
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
            else:
                if (node == NetUtil.GetHostIpOrName()):
                    sshcmd = "gs_guc set " \
                             "-D %s -c \"ssl_crl_file=''\"" % (
                                 allDnNodeDict[node])
                else:
                    sshcmd = "gs_guc set " \
                             "-D %s -c \"ssl_crl_file=\\\\\\'\\\\\\'\"" \
                             % (allDnNodeDict[node])
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)

            # Clear empty file.
            if (self.isDnEmpty(node)):
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(allDnNodeDict[node], EMPTY_CERT),
                    os.path.join(allDnNodeDict[node], EMPTY_CERT))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
            self.logger.log(
                "Successfully rollback SSL cert files on [%s]." % node)

        self.cert_rollback()

    def rollback_cert(self, ssl_dir, cert_list):
        """
        function: Delete the certificate and decompress the backup package.
        input: Certificate directory, certificate list
        output: NA
        """
        cmd = "cd '%s';rm -f" % ssl_dir
        for num in cert_list:
            cmd += " {}".format(num)
        sshcmd = "%s && tar -zxf %s;rm -f '%s'" % (cmd, DefaultValue.CERT_BACKUP_FILE, EMPTY_FLAG)
        self.sshTool.executeCommand(sshcmd,
                                    DefaultValue.SUCCESS,
                                    [node.name for node in self.context.clusterInfo.dbNodes],
                                    self.context.g_opts.mpprcFile)

    def getDnNodeDict(self):
        """
        function: get dbnodes information
        input: NA
        output: dictionary
        """
        clusterDnNodes = {}
        if (not self.context.clusterInfo.isSingleInstCluster()):
            return clusterDnNodes
        for node in self.context.clusterInfo.dbNodes:
            if (len(node.datanodes) > 0):
                clusterDnNodes[node.datanodes[0].hostname] = node.datanodes[
                    0].datadir
        self.logger.debug("Successfully get database node dict.")
        return clusterDnNodes

    def distribute_ssl_cert(self, params):
        """
        function: Distributing SSL Certificate Files
        input: Certificate parameters
        output: NA
        """
        cert_path_list, ssl_dir, cert_lit, mode = params
        if self.context.g_opts.localMode:
            cert_path_list_num = len(cert_path_list)
            for num in range(cert_path_list_num):
                # distribute cert
                if os.path.isfile(os.path.join(ssl_dir, cert_lit[num])):
                    os.remove(os.path.join(ssl_dir, cert_lit[num]))
                if os.path.isfile(cert_path_list[num]):
                    FileUtil.cpFile(cert_path_list[num],
                                    os.path.join(ssl_dir, cert_lit[num]))
                    FileUtil.changeMode(mode,
                                        os.path.join(ssl_dir, cert_lit[num]))
        else:
            cert_lit_num = len(cert_lit)
            for num in range(cert_lit_num):
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(ssl_dir, cert_lit[num]),
                    os.path.join(ssl_dir, cert_lit[num]))
                self.sshTool.executeCommand(
                    sshcmd,
                    DefaultValue.SUCCESS,
                    [node.name for node in self.context.clusterInfo.dbNodes],
                    self.context.g_opts.mpprcFile)
            cert_path_list_num = len(cert_path_list)
            for num in range(cert_path_list_num):
                if os.path.exists(cert_path_list[num]):
                    cmd = g_file.SHELL_CMD_DICT["changeMode"] % (
                        mode, cert_path_list[num])
                    (status, output) = subprocess.getstatusoutput(cmd)
                    if status != 0:
                        raise Exception("Failed to chmod dss cert files" + "Error: \n%s" % output)
                    self.sshTool.scpFiles(cert_path_list[num], ssl_dir,
                                          [node.name for node in self.context.clusterInfo.dbNodes])

    def regen_dss_cert(self):
        """
        function: Re-generate the ciphertext of the DSS.
        input: NA
        output: NA
        """
        try:
            self.logger.debug("Re-generate the ciphertext of the DSS")
            cmd = "source %s; %s -t dss_cert_replacer -U %s -l %s" % (
                self.context.g_opts.mpprcFile,
                OMCommand.getLocalScript("Local_Collect"), self.context.user,
                self.context.localLog)
            CmdExecutor.execCommandWithMode(
                cmd, self.sshTool, self.context.g_opts.localMode,
                self.context.g_opts.mpprcFile,
                [node.name for node in self.context.clusterInfo.dbNodes])
            self.logger.debug("The cmd is %s " % cmd)
        except Exception as e:
            self.logger.log("Failed to re-generate the ciphertext of the DSS.")
            raise Exception(str(e))

    def distribute_cert(self):
        """
        function: Distributing Certificates
        input: NA
        output: NA
        """
        tempDir = "tempCertDir"
        gphost = EnvUtil.getTmpDirFromEnv()
        cm_dss_sslcert_cert_path_list = []
        server_sslcert_cert_path_list = []
        dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user),
            "share/sslcert/dss/")
        cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user),
            "share/sslcert/cm/")
        om_ssl_dir = os.path.join(ClusterDir.getInstallDir(
            self.context.g_opts.user),
            "share/sslcert/om/")
        for num in range(len(DefaultValue.GDS_CERT_LIST)):
            sslPath = os.path.join(os.path.join(gphost, tempDir),
                                   DefaultValue.GDS_CERT_LIST[num])
            cm_dss_sslcert_cert_path_list.append(sslPath)
        for num in range(len(DefaultValue.SERVER_CERT_LIST)):
            sslPath = os.path.join(os.path.join(gphost, tempDir),
                                   DefaultValue.SERVER_CERT_LIST[num])
            server_sslcert_cert_path_list.append(sslPath)

        # distribute dss SSL cert
        if os.path.isdir(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
                getpass.getuser()) == 'on':
            self.distribute_ssl_cert((cm_dss_sslcert_cert_path_list,
                                     dss_ssl_dir,
                                     DefaultValue.GDS_CERT_LIST,
                                     DefaultValue.MIN_FILE_MODE))
            self.regen_dss_cert()
            self.logger.log("Successfully replace dss ssl cert files.")

        # distribute cm SSL cert
        if os.path.isdir(cm_ssl_dir):
            self.distribute_ssl_cert((cm_dss_sslcert_cert_path_list,
                                     cm_ssl_dir,
                                     DefaultValue.GDS_CERT_LIST,
                                     DefaultValue.MIN_FILE_MODE))
            self.logger.log("Successfully replace cm ssl cert files.")

        # distribute om SSL cert
        if os.path.isdir(om_ssl_dir):
            self.distribute_ssl_cert((server_sslcert_cert_path_list,
                                     om_ssl_dir,
                                     DefaultValue.SERVER_CERT_LIST,
                                     DefaultValue.KEY_FILE_MODE))
            self.logger.log("Successfully replace om ssl cert files.")

    def distributeDNCert(self, certList, dnDict=None):
        """
        function: distribute ssl cert files on single_inst cluster
        input: certList:     cert files list
               dnDict:       dictionary
        output: NA
        """
        tempDir = "tempCertDir"
        gphost = EnvUtil.getTmpDirFromEnv()
        if dnDict is None:
            dnDict = {}
        dnName = dnDict.keys()
        certPathList = []
        self.logger.debug(certList)

        for num in iter(certList):
            sslPath = os.path.join(os.path.join(gphost, tempDir), num)
            certPathList.append(sslPath)
        # local mode
        if self.context.g_opts.localMode:
            localDnDir = dnDict[NetUtil.GetHostIpOrName()]
            for num in range(len(certList)):
                # distribute gsql SSL cert
                if os.path.isfile(os.path.join(localDnDir, certList[num])):
                    os.remove(os.path.join(localDnDir, certList[num]))
                if os.path.isfile(certPathList[num]):
                    FileUtil.cpFile(certPathList[num],
                                    os.path.join(localDnDir, certList[num]))
                    FileUtil.changeMode(DefaultValue.KEY_FILE_MODE,
                                        os.path.join(localDnDir, certList[num]))

            self.distribute_cert()
            # remove 'sslcrl-file.crl' file
            if (DefaultValue.SSL_CRL_FILE not in certList and
                    os.path.isfile(
                        os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
                os.remove(os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))

                # config 'sslcrl-file.crl' option in 'postgresql.conf'
            if (os.path.isfile(
                    os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
                cmd = "gs_guc set " \
                      "-D %s -c \"ssl_crl_file=\'%s\'\"" % \
                      (localDnDir, DefaultValue.SSL_CRL_FILE)
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    raise Exception(
                        (ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
                        + "Failed set 'ssl_crl_file' option."
                        + "Error: \n%s" % output)
            else:
                cmd = "gs_guc set -D %s -c \"ssl_crl_file=\'\'\"" \
                      % localDnDir
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    raise Exception(
                        (ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
                        + "Failed set 'ssl_crl_file' option."
                        + "Error: \n%s" % output)
                    # remove backup flag file 'certFlag'
            if (os.path.isfile(os.path.join(localDnDir, 'certFlag'))):
                os.remove(os.path.join(localDnDir, 'certFlag'))
            self.logger.log(
                "Replace SSL cert files with local mode successfully.")
            return
        # not local mode
        for node in dnName:
            for num in range(len(certList)):
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(dnDict[node], certList[num]),
                    os.path.join(dnDict[node], certList[num]))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)

                if (os.path.exists(certPathList[num])):
                    self.sshTool.scpFiles(certPathList[num], dnDict[node],
                                          [node])

                # change permission of cert file 600,
                # there no need to is exists file,
                # because the files must be exist.
                sshcmd = g_file.SHELL_CMD_DICT["changeMode"] % (
                    DefaultValue.KEY_FILE_MODE,
                    os.path.join(dnDict[node], certList[num]))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)

            if (DefaultValue.SSL_CRL_FILE in certList):
                if (node == NetUtil.GetHostIpOrName()):
                    sshcmd = "gs_guc set " \
                             "-D %s -c \"ssl_crl_file='%s'\"" \
                             % (dnDict[node], DefaultValue.SSL_CRL_FILE)
                else:
                    sshcmd = "gs_guc set " \
                             " -D %s -c \"ssl_crl_file=\\\\\\'%s\\\\\\'\"" \
                             % (dnDict[node], DefaultValue.SSL_CRL_FILE)
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
            else:
                # no ssl cert file there will delete old cert file,
                # and config option ssl_crl_file = ''
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE),
                    os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
                if (node == NetUtil.GetHostIpOrName()):
                    sshcmd = "gs_guc set " \
                             "-D %s -c \"ssl_crl_file=\'\'\"" % (dnDict[node])
                else:
                    sshcmd = \
                        "gs_guc set " \
                        "-D %s " \
                        "-c \"ssl_crl_file=\\\\\\'\\\\\\'\"" % (dnDict[node])
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
                # remove file 'sslcrl-file.crl'
                sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                    os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE),
                    os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE))
                self.sshTool.executeCommand(sshcmd,
                                            DefaultValue.SUCCESS,
                                            [node],
                                            self.context.g_opts.mpprcFile)
            # remove backup flag file 'certFlag'
            sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
                os.path.join(dnDict[node], "certFlag"),
                os.path.join(dnDict[node], "certFlag"))
            self.sshTool.executeCommand(sshcmd,
                                        DefaultValue.SUCCESS,
                                        [node],
                                        self.context.g_opts.mpprcFile)
            self.logger.log("%s replace SSL cert files successfully." % node)

        self.distribute_cert()

    ###########################################################################
    # Kerberos Flow
    ###########################################################################
    def doKerberos(self):
        """
        function: operation kerberos
        input: NA
        output: NA
        """
        try:
            if self.context.g_opts.kerberosMode == "install":
                self.logger.log("Starting install Kerberos.", "addStep")
                cmd = "%s -m %s -U %s --%s" % \
                      (OMCommand.getLocalScript("Local_Kerberos"),
                       "install",
                       self.context.g_opts.clusterUser,
                       self.context.g_opts.kerberosType)
                # local mode
                (status, output) = subprocess.getstatusoutput(cmd)
                if (status != 0):
                    raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
                                    "Command: %s. Error:\n%s" % (cmd, output))
                self.logger.log("Successfully install Kerberos.")
            elif self.context.g_opts.kerberosMode == "uninstall":
                self.logger.log("Starting uninstall Kerberos.", "addStep")
                cmd = "%s -m %s -U %s" % \
                      (OMCommand.getLocalScript("Local_Kerberos"),
                       "uninstall",
                       self.context.g_opts.clusterUser)
                # local mode
                (status, output) = subprocess.getstatusoutput(cmd)
                if status != 0:
                    raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
                                    "Command: %s. Error:\n%s" % (cmd, output))
                self.logger.log("Successfully uninstall Kerberos.")
        except Exception as e:
            raise Exception(str(e))

    def checkRemoteFileExist(self, filepath):
        """
        funciton:check file exist on remote node
        input:filepath
        output:dictionary
        """
        existNodes = []
        for nodeName in self.context.clusterInfo.getClusterNodeNames():
            if (nodeName == NetUtil.GetHostIpOrName()):
                continue
            if (self.sshTool.checkRemoteFileExist(nodeName, filepath, "")):
                existNodes.append(nodeName)

        return existNodes

    def recursivePath(self, filepath):
        """
        function: recursive path
        input: filepath
        output: NA
        """
        fileList = os.listdir(filepath)
        for fileName in fileList:
            fileName = os.path.join(filepath, fileName)
            # change the owner of files
            FileUtil.changeOwner(self.context.g_opts.user, fileName)
            if (os.path.isfile(fileName)):
                # change fileName permission
                FileUtil.changeMode(DefaultValue.KEY_FILE_MODE, fileName)
            else:
                # change directory permission
                FileUtil.changeMode(DefaultValue.KEY_DIRECTORY_MODE, fileName,
                                  True)
                self.recursivePath(fileName)

    def stopCluster(self):
        """
        function:Stop cluster
        input:NA
        output:NA
        """
        pass

    def startCluster(self):
        """
        function:Start cluster
        input:NA
        output:NA
        """
        pass